diff --git a/.htaccess b/.htaccess
index 07cf7e4..c29b0d5 100644
--- a/.htaccess
+++ b/.htaccess
@@ -97,14 +97,14 @@ AddEncoding gzip svgz
   # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
   #
   # To redirect all users to access the site WITH the 'www.' prefix,
-  # (http://example.com/foo will be redirected to http://www.example.com/foo)
+  # (http://example.com/... will be redirected to http://www.example.com/...)
   # uncomment the following:
   # RewriteCond %{HTTP_HOST} .
   # RewriteCond %{HTTP_HOST} !^www\. [NC]
   # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
   #
   # To redirect all users to access the site WITHOUT the 'www.' prefix,
-  # (http://www.example.com/foo will be redirected to http://example.com/foo)
+  # (http://www.example.com/... will be redirected to http://example.com/...)
   # uncomment the following:
   # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
   # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301]
diff --git a/core/CHANGELOG.txt b/core/CHANGELOG.txt
index e9fec1d..3420ece 100644
--- a/core/CHANGELOG.txt
+++ b/core/CHANGELOG.txt
@@ -96,7 +96,7 @@ Drupal 8.0, xxxx-xx-xx (development version)
       * Added language selectors to most configuration options (views, menus,
         etc.)
       * Added a configuration translation user interface that works with any
-        configuration with translatable values (blocks, views, fields, etc.).
+        configuration with translatable values (blocks, views, fields, etc).
       * Added language options to block visibility.
     * Much improved language APIs for developers:
       * Added simple APIs and hooks to save/delete/update languages.
@@ -682,7 +682,7 @@ Drupal 4.7.0, 2006-05-01
 - Added support for PHP5's 'mysqli' extension.
 - Search module:
     * Made indexer smarter and more robust.
-    * Added advanced search operators (e.g., phrase, node type, etc.).
+    * Added advanced search operators (e.g. phrase, node type, ...).
     * Added customizable result ranking.
 - PostgreSQL support:
     * Removed dependency on PL/pgSQL procedural language.
@@ -1059,7 +1059,7 @@ Drupal 4.0.0, 2002-06-15
     * Made each cloud site have its own settings.
     * Modules and themes can now be enabled/disabled using the administration pages.
     * Added URL abstraction for links.
-    * Usability changes (renamed links, better UI, etc.).
+    * Usability changes (renamed links, better UI, etc).
 - Collaboratively revised and expanded the Drupal documentation.
 
 Drupal 3.0.1, 2001-10-15
diff --git a/core/core.services.yml b/core/core.services.yml
index 589c5f6..7b41a1d 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -136,7 +136,7 @@ services:
     arguments: ['@database', '@cache_tags.invalidator.checksum']
   cache.backend.apcu:
     class: Drupal\Core\Cache\ApcuBackendFactory
-    arguments: ['@app.root', '@site.path', '@cache_tags.invalidator.checksum']
+    arguments: ['@app.root', '@cache_tags.invalidator.checksum']
   cache.backend.php:
     class: Drupal\Core\Cache\PhpBackendFactory
     arguments: ['@cache_tags.invalidator.checksum']
@@ -418,12 +418,6 @@ services:
       - { name: module_install.uninstall_validator }
     arguments: ['@entity.manager', '@string_translation']
     lazy: true
-  required_module_uninstall_validator:
-    class: Drupal\Core\Extension\RequiredModuleUninstallValidator
-    tags:
-      - { name: module_install.uninstall_validator }
-    arguments: ['@string_translation']
-    lazy: true
   theme_handler:
     class: Drupal\Core\Extension\ThemeHandler
     arguments: ['@app.root', '@config.factory', '@module_handler', '@state', '@info_parser']
@@ -498,7 +492,7 @@ services:
     arguments: ['@controller_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
   plugin.manager.menu.local_task:
     class: Drupal\Core\Menu\LocalTaskManager
-    arguments: ['@controller_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
+    arguments: ['@controller_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@router.builder', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
   plugin.manager.menu.contextual_link:
     class: Drupal\Core\Menu\ContextualLinkManager
     arguments: ['@controller_resolver', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user', '@request_stack']
@@ -545,15 +539,6 @@ services:
     class: Drupal\Core\AppRootFactory
     arguments: ['@kernel']
     public: false
-  site.path:
-    class: SplString
-    factory: site.path.factory:get
-    tags:
-      - { name: parameter_service }
-  site.path.factory:
-    class: Drupal\Core\SitePathFactory
-    arguments: ['@kernel']
-    public: false
   controller_resolver:
     class: Drupal\Core\Controller\ControllerResolver
     arguments: ['@class_resolver']
@@ -575,6 +560,10 @@ services:
   http_middleware.negotiation:
     class: Drupal\Core\StackMiddleware\NegotiationMiddleware
     arguments: ['@http_negotiation.format_negotiator']
+    calls:
+      - [registerFormat, ['drupal_ajax', ['application/vnd.drupal-ajax']]]
+      - [registerFormat, ['drupal_dialog', ['application/vnd.drupal-dialog']]]
+      - [registerFormat, ['drupal_modal', ['application/vnd.drupal-modal']]]
     tags:
       - { name: http_middleware, priority: 400 }
   http_middleware.reverse_proxy:
@@ -769,8 +758,8 @@ services:
   password:
     class: Drupal\Core\Password\PhpassHashedPassword
     arguments: [16]
-  request_format_route_filter:
-    class: Drupal\Core\Routing\RequestFormatRouteFilter
+  accept_header_matcher:
+    class: Drupal\Core\Routing\AcceptHeaderMatcher
     tags:
       - { name: route_filter }
   content_type_header_matcher:
@@ -1143,7 +1132,7 @@ services:
     arguments: ['@module_handler']
   date.formatter:
     class: Drupal\Core\Datetime\DateFormatter
-    arguments: ['@entity.manager', '@language_manager', '@string_translation', '@config.factory', '@request_stack']
+    arguments: ['@entity.manager', '@language_manager', '@string_translation', '@config.factory']
   feed.bridge.reader:
     class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer
     calls:
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 31bbf42..463dcd0 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -213,11 +213,6 @@ function entity_delete_multiple($entity_type, array $ids) {
  *
  * @return \Drupal\Core\Entity\EntityInterface
  *   A new entity object.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 9.0.0. Use
- *    the <EntityType>::create($values) method if the entity type is known or
- *    \Drupal::entityManager()->getStorage($entity_type)->create($values) if the
- *    entity type is variable.
  */
 function entity_create($entity_type, array $values = array()) {
   return \Drupal::entityManager()
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 402d41e..6f1add0 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -367,7 +367,7 @@ function install_begin_request($class_loader, &$install_state) {
 
   // Determine whether base system services are ready to operate.
   $install_state['config_verified'] = install_ensure_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_ensure_config_directory(CONFIG_STAGING_DIRECTORY);
-  $install_state['database_verified'] = install_verify_database_settings($site_path);
+  $install_state['database_verified'] = install_verify_database_settings();
   $install_state['settings_verified'] = $install_state['config_verified'] && $install_state['database_verified'];
 
   // Install factory tables only after checking the database.
@@ -1077,17 +1077,11 @@ function install_verify_completed_task() {
 
 /**
  * Verifies that settings.php specifies a valid database connection.
- *
- * @param string $site_path
- *  The site path.
- *
- * @return bool
- *  TRUE if there are no database errors.
  */
-function install_verify_database_settings($site_path) {
+function install_verify_database_settings() {
   if ($database = Database::getConnectionInfo()) {
     $database = $database['default'];
-    $settings_file = './' . $site_path . '/settings.php';
+    $settings_file = './' . conf_path(FALSE) . '/settings.php';
     $errors = install_database_errors($database, $settings_file);
     if (empty($errors)) {
       return TRUE;
@@ -1908,9 +1902,8 @@ function install_check_translations($langcode, $server_pattern) {
   $readable = FALSE;
   $writable = FALSE;
   // @todo: Make this configurable.
-  $site_path = \Drupal::service('site.path');
-  $files_directory =  $site_path . '/files';
-  $translations_directory = $site_path . '/files/translations';
+  $files_directory = conf_path() . '/files';
+  $translations_directory = conf_path() . '/files/translations';
   $translations_directory_exists = FALSE;
   $translation_available = FALSE;
   $online = FALSE;
@@ -2088,12 +2081,12 @@ function install_check_requirements($install_state) {
   foreach ($default_files as $default_file_info) {
     $readable = FALSE;
     $writable = FALSE;
-    $site_path = './' . \Drupal::service('site.path');
-    $file = $site_path . "/{$default_file_info['file']}";
+    $conf_path = './' . conf_path(FALSE);
+    $file = $conf_path . "/{$default_file_info['file']}";
     $default_file = "./sites/default/{$default_file_info['file_default']}";
     $exists = FALSE;
     // Verify that the directory exists.
-    if (drupal_verify_install_file($site_path, FILE_EXIST, 'dir')) {
+    if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) {
       if (drupal_verify_install_file($file, FILE_EXIST)) {
         // If it does, make sure it is writable.
         $readable = drupal_verify_install_file($file, FILE_READABLE);
@@ -2118,7 +2111,7 @@ function install_check_requirements($install_state) {
     // Otherwise, if $file does not exist yet, we can try to copy
     // $default_file to create it.
     elseif (!$exists) {
-      $copied = drupal_verify_install_file($site_path, FILE_EXIST | FILE_WRITABLE, 'dir') && @copy($default_file, $file);
+      $copied = drupal_verify_install_file($conf_path, FILE_EXIST | FILE_WRITABLE, 'dir') && @copy($default_file, $file);
       if ($copied) {
         // If the new $file file has the same owner as $default_file this means
         // $default_file is owned by the webserver user. This is an inherent
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 01d6166..6f7c8c7 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -197,7 +197,7 @@ function drupal_get_database_types() {
  */
 function drupal_rewrite_settings($settings = array(), $settings_file = NULL) {
   if (!isset($settings_file)) {
-    $settings_file = \Drupal::service('site.path') . '/settings.php';
+    $settings_file = conf_path(FALSE) . '/settings.php';
   }
   // Build list of setting names and insert the values into the global namespace.
   $variable_names = array();
@@ -470,13 +470,13 @@ function drupal_install_config_directories() {
   $config_directories_hash = Crypt::randomBytesBase64(55);
   if (empty($config_directories[CONFIG_ACTIVE_DIRECTORY])) {
     $settings['config_directories'][CONFIG_ACTIVE_DIRECTORY] = (object) [
-      'value' => \Drupal::service('site.path') . '/files/config_' . $config_directories_hash . '/active',
+      'value' => conf_path() . '/files/config_' . $config_directories_hash . '/active',
       'required' => TRUE,
     ];
   }
   if (empty($config_directories[CONFIG_STAGING_DIRECTORY])) {
     $settings['config_directories'][CONFIG_STAGING_DIRECTORY] = (object) [
-      'value' => \Drupal::service('site.path') . '/files/config_' . $config_directories_hash . '/staging',
+      'value' => conf_path() . '/files/config_' . $config_directories_hash . '/staging',
       'required' => TRUE,
     ];
   }
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 121da17..fa83a1b 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1362,9 +1362,9 @@ function template_preprocess_page(&$variables) {
   // Move some variables to the top level for themer convenience and template cleanliness.
   $variables['title'] = $variables['page']['#title'];
 
-  foreach (\Drupal::theme()->getActiveTheme()->getRegions() as $region) {
-    if (!isset($variables['page'][$region])) {
-      $variables['page'][$region] = array();
+  foreach (system_region_list(\Drupal::theme()->getActiveTheme()->getName()) as $region_key => $region_name) {
+    if (!isset($variables['page'][$region_key])) {
+      $variables['page'][$region_key] = array();
     }
   }
 
diff --git a/core/lib/Drupal/Component/Diff/Engine/HWLDFWordAccumulator.php b/core/lib/Drupal/Component/Diff/Engine/HWLDFWordAccumulator.php
index a10d0e8..a5ef64d 100644
--- a/core/lib/Drupal/Component/Diff/Engine/HWLDFWordAccumulator.php
+++ b/core/lib/Drupal/Component/Diff/Engine/HWLDFWordAccumulator.php
@@ -33,12 +33,11 @@ class HWLDFWordAccumulator {
   protected function _flushGroup($new_tag) {
     if ($this->group !== '') {
       if ($this->tag == 'mark') {
-        $format_string = '@original_line<span class="diffchange">@group</span>';
+        $this->line .= '<span class="diffchange">' . SafeMarkup::checkPlain($this->group) . '</span>';
       }
       else {
-        $format_string = '@original_line@group';
+        $this->line .= SafeMarkup::checkPlain($this->group);
       }
-      $this->line = SafeMarkup::format($format_string, ['@original_line' => $this->line, '@group' => $this->group]);
     }
     $this->group = '';
     $this->tag = $new_tag;
@@ -47,7 +46,9 @@ protected function _flushGroup($new_tag) {
   protected function _flushLine($new_tag) {
     $this->_flushGroup($new_tag);
     if ($this->line != '') {
-      array_push($this->lines, $this->line);
+      // @todo This is probably not the right place to do this. To be
+      //   addressed in https://www.drupal.org/node/2280963.
+      array_push($this->lines, SafeMarkup::set($this->line));
     }
     else {
       // make empty lines visible by inserting an NBSP
diff --git a/core/lib/Drupal/Component/Utility/NestedArray.php b/core/lib/Drupal/Component/Utility/NestedArray.php
index 8829fc8..e123b4a 100644
--- a/core/lib/Drupal/Component/Utility/NestedArray.php
+++ b/core/lib/Drupal/Component/Utility/NestedArray.php
@@ -42,7 +42,7 @@ class NestedArray {
    * $key_exists = NULL;
    * $value = NestedArray::getValue($form, $parents, $key_exists);
    * if ($key_exists) {
-   *   // Do something with $value.
+   *   // ... do something with $value ...
    * }
    * @endcode
    *
diff --git a/core/lib/Drupal/Core/Action/ActionBase.php b/core/lib/Drupal/Core/Action/ActionBase.php
index 9278deb..89e184a 100644
--- a/core/lib/Drupal/Core/Action/ActionBase.php
+++ b/core/lib/Drupal/Core/Action/ActionBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Action;
 
 use Drupal\Core\Plugin\PluginBase;
+use Drupal\Core\Action\ActionInterface;
 
 /**
  * Provides a base implementation for an Action plugin.
diff --git a/core/lib/Drupal/Core/Asset/CssOptimizer.php b/core/lib/Drupal/Core/Asset/CssOptimizer.php
index 6e32fbd..4b96888 100644
--- a/core/lib/Drupal/Core/Asset/CssOptimizer.php
+++ b/core/lib/Drupal/Core/Asset/CssOptimizer.php
@@ -176,7 +176,8 @@ protected function loadNestedFile($matches) {
     $directory = $directory == '.' ? '' : $directory .'/';
 
     // Alter all internal url() paths. Leave external paths alone. We don't need
-    // to normalize absolute paths here because that will be done later.
+    // to normalize absolute paths here (i.e. remove folder/... segments)
+    // because that will be done later.
     return preg_replace('/url\(\s*([\'"]?)(?![a-z]+:|\/+)([^\'")]+)([\'"]?)\s*\)/i', 'url(\1' . $directory . '\2\3)', $file);
   }
 
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index e6a4376..1c08bc9 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -213,7 +213,7 @@ public function buildByExtension($extension) {
   }
 
   /**
-   * Parses a given library file and allows modules and themes to alter it.
+   * Parses a given library file and allows module to alter it.
    *
    * This method sets the parsed information onto the library property.
    *
diff --git a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
index f744edc..97a201b 100644
--- a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
@@ -30,13 +30,11 @@ class ApcuBackendFactory implements CacheFactoryInterface {
    *
    * @param string $root
    *   The app root.
-   * @param string $site_path
-   *   The site path.
    * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
    *   The cache tags checksum provider.
    */
-  public function __construct($root, $site_path, CacheTagsChecksumInterface $checksum_provider) {
-    $this->sitePrefix = Settings::getApcuPrefix('apcu_backend', $root, $site_path);
+  public function __construct($root, CacheTagsChecksumInterface $checksum_provider) {
+    $this->sitePrefix = Settings::getApcuPrefix('apcu_backend', $root, conf_path());
     $this->checksumProvider = $checksum_provider;
   }
 
diff --git a/core/lib/Drupal/Core/Command/DbDumpApplication.php b/core/lib/Drupal/Core/Command/DbDumpApplication.php
deleted file mode 100644
index 080e20f..0000000
--- a/core/lib/Drupal/Core/Command/DbDumpApplication.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Command\DbDumpApplication.
- */
-
-namespace Drupal\Core\Command;
-
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Symfony\Component\Console\Application;
-use Symfony\Component\Console\Input\InputInterface;
-
-/**
- * Provides a command to dump a database generation script.
- */
-class DbDumpApplication extends Application {
-
-  /**
-   * The database connection.
-   *
-   * @var \Drupal\Core\Database\Connection
-   */
-  protected $connection;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * Construct the application.
-   *
-   * @param \Drupal\Core\Database\Connection $connection
-   *   The database connection.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   */
-  function __construct(Connection $connection, ModuleHandlerInterface $module_handler) {
-    $this->connection = $connection;
-    $this->moduleHandler = $module_handler;
-    parent::__construct();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getCommandName(InputInterface $input) {
-    return 'dump-database-d8-mysql';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getDefaultCommands() {
-    // Even though this is a single command, keep the HelpCommand (--help).
-    $default_commands = parent::getDefaultCommands();
-    $default_commands[] = new DbDumpCommand($this->connection, $this->moduleHandler);
-    return $default_commands;
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * Overridden so the application doesn't expect the command name as the first
-   * argument.
-   */
-  public function getDefinition() {
-    $definition = parent::getDefinition();
-    // Clears the normal first argument (the command name).
-    $definition->setArguments();
-    return $definition;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Command/DbDumpCommand.php b/core/lib/Drupal/Core/Command/DbDumpCommand.php
deleted file mode 100644
index d71bb37..0000000
--- a/core/lib/Drupal/Core/Command/DbDumpCommand.php
+++ /dev/null
@@ -1,434 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Command\DbDumpCommand.
- */
-
-namespace Drupal\Core\Command;
-
-use Drupal\Component\Utility\Variable;
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-/**
- * Provides a command to dump the current database to a script.
- *
- * This script exports all tables in the given database, and all data (except
- * for tables denoted as schema-only). The resulting script creates the tables
- * and populates them with the exported data.
- *
- * @todo This command is currently only compatible with MySQL. Making it
- *   backend-agnostic will require \Drupal\Core\Database\Schema support the
- *   ability to retrieve table schema information. Note that using a raw
- *   SQL dump file here (eg, generated from mysqldump or pg_dump) is not an
- *   option since these tend to still be database-backend specific.
- * @see https://www.drupal.org/node/301038
- *
- * @see \Drupal\Core\Command\DbDumpApplication
- */
-class DbDumpCommand extends Command {
-
-  /**
-   * The database connection.
-   *
-   * @var \Drupal\Core\Database\Connection $connection
-   */
-  protected $connection;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * An array of table patterns to exclude completely.
-   *
-   * This excludes any lingering simpletest tables generated during test runs.
-   *
-   * @var array
-   */
-  protected $excludeTables = ['simpletest.+'];
-
-  /**
-   * Table patterns for which to only dump the schema, no data.
-   *
-   * @var array
-   */
-  protected $schemaOnly = ['cache.*', 'sessions', 'watchdog'];
-
-  /**
-   * Construct the database dump command.
-   *
-   * @param \Drupal\Core\Database\Connection $connection
-   *   The database connection to use.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to use.
-   */
-  function __construct(Connection $connection, ModuleHandlerInterface $module_handler) {
-    // Check this is MySQL.
-    if ($connection->databaseType() !== 'mysql') {
-      throw new \RuntimeException('This script can only be used with MySQL database backends.');
-    }
-
-    $this->connection = $connection;
-    $this->moduleHandler = $module_handler;
-    parent::__construct();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function configure() {
-    $this->setName('dump-database-d8-mysql')
-      ->setDescription('Dump the current database to a generation script');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function execute(InputInterface $input, OutputInterface $output) {
-    // If not explicitly set, disable ANSI which will break generated php.
-    if ($input->hasParameterOption(['--ansi']) !== TRUE) {
-      $output->setDecorated(FALSE);
-    }
-
-    $output->writeln($this->generateScript());
-  }
-
-  /**
-   * Generates the database script.
-   *
-   * @return string
-   *   The PHP script.
-   */
-  protected function generateScript() {
-    $tables = '';
-    foreach ($this->getTables() as $table) {
-      $schema = $this->getTableSchema($table);
-      $data = $this->getTableData($table);
-      $tables .= $this->getTableScript($table, $schema, $data);
-    }
-    $script = $this->getTemplate();
-    // Substitute in the tables.
-    $script = str_replace('{{TABLES}}', trim($tables), $script);
-    // Modules.
-    $script = str_replace('{{MODULES}}', $this->getModulesScript(), $script);
-    return trim($script);
-  }
-
-  /**
-   * Returns a list of tables, not including those set to be excluded.
-   *
-   * @return array
-   *   An array of table names.
-   */
-  protected function getTables() {
-    $pattern = $this->connection->tablePrefix() . '%';
-    $tables = array_values($this->connection->schema()->findTables($pattern));
-    foreach ($tables as $key => $table) {
-      // The prefix is removed for the resultant script.
-      $table = $tables[$key] = str_replace($this->connection->tablePrefix(), '', $table);
-
-      // Remove any explicitly excluded tables.
-      foreach ($this->excludeTables as $pattern) {
-        if (preg_match('/^' . $pattern . '$/', $table)) {
-          unset($tables[$key]);
-        }
-      }
-    }
-    return $tables;
-  }
-
-  /**
-   * Returns a schema array for a given table.
-   *
-   * @param string $table
-   *   The table name.
-   *
-   * @return array
-   *   A schema array (as defined by hook_schema()).
-   *
-   * @todo This implementation is hard-coded for MySQL.
-   */
-  protected function getTableSchema($table) {
-    $query = $this->connection->query("SHOW FULL COLUMNS FROM {" . $table . "}");
-    $definition = [];
-    while (($row = $query->fetchAssoc()) !== FALSE) {
-      $name = $row['Field'];
-      // Parse out the field type and meta information.
-      preg_match('@([a-z]+)(?:\((\d+)(?:,(\d+))?\))?\s*(unsigned)?@', $row['Type'], $matches);
-      $type  = $this->fieldTypeMap($matches[1]);
-      if ($row['Extra'] === 'auto_increment') {
-        // If this is an auto increment, then the type is 'serial'.
-        $type = 'serial';
-      }
-      $definition['fields'][$name] = [
-        'type' => $type,
-        'not null' => $row['Null'] === 'NO',
-      ];
-      if ($size = $this->fieldSizeMap($matches[1])) {
-        $definition['fields'][$name]['size'] = $size;
-      }
-      if (isset($matches[2]) && $type === 'numeric') {
-        // Add precision and scale.
-        $definition['fields'][$name]['precision'] = $matches[2];
-        $definition['fields'][$name]['scale'] = $matches[3];
-      }
-      elseif ($type === 'time' || $type === 'datetime') {
-        // @todo Core doesn't support these, but copied from `migrate-db.sh` for now.
-        // Convert to varchar.
-        $definition['fields'][$name]['type'] = 'varchar';
-        $definition['fields'][$name]['length'] = '100';
-      }
-      elseif (!isset($definition['fields'][$name]['size'])) {
-        // Try use the provided length, if it doesn't exist default to 100. It's
-        // not great but good enough for our dumps at this point.
-        $definition['fields'][$name]['length'] = isset($matches[2]) ? $matches[2] : 100;
-      }
-
-      if (isset($row['Default'])) {
-        $definition['fields'][$name]['default'] = $row['Default'];
-      }
-
-      if (isset($matches[4])) {
-        $definition['fields'][$name]['unsigned'] = TRUE;
-      }
-
-      // Check for the 'varchar_ascii' type that should be 'binary'.
-      if (isset($row['Collation']) && $row['Collation'] == 'ascii_bin') {
-        $definition['fields'][$name]['type'] = 'varchar_ascii';
-        $definition['fields'][$name]['binary'] = TRUE;
-      }
-
-      // Check for the non-binary 'varchar_ascii'.
-      if (isset($row['Collation']) && $row['Collation'] == 'ascii_general_ci') {
-        $definition['fields'][$name]['type'] = 'varchar_ascii';
-      }
-
-      // Check for the 'utf8_bin' collation.
-      if (isset($row['Collation']) && $row['Collation'] == 'utf8_bin') {
-        $definition['fields'][$name]['binary'] = TRUE;
-      }
-    }
-
-    // Set primary key, unique keys, and indexes.
-    $this->getTableIndexes($table, $definition);
-
-    return $definition;
-  }
-
-  /**
-   * Adds primary key, unique keys, and index information to the schema.
-   *
-   * @param string $table
-   *   The table to find indexes for.
-   * @param array &$definition
-   *   The schema definition to modify.
-   */
-  protected function getTableIndexes($table, &$definition) {
-    // Note, this query doesn't support ordering, so that is worked around
-    // below by keying the array on Seq_in_index.
-    $query = $this->connection->query("SHOW INDEX FROM {" . $table . "}");
-    $indexes = [];
-    while (($row = $query->fetchAssoc()) !== FALSE) {
-      $index_name = $row['Key_name'];
-      $column = $row['Column_name'];
-      // Key the arrays by the index sequence for proper ordering (start at 0).
-      $order = $row['Seq_in_index'] - 1;
-
-      // If specified, add length to the index.
-      if ($row['Sub_part']) {
-        $column = [$column, $row['Sub_part']];
-      }
-
-      if ($index_name === 'PRIMARY') {
-        $definition['primary key'][$order] = $column;
-      }
-      elseif ($row['Non_unique'] == 0) {
-        $definition['unique keys'][$index_name][$order] = $column;
-      }
-      else {
-        $definition['indexes'][$index_name][$order] = $column;
-      }
-    }
-  }
-
-  /**
-   * Gets all data from a given table.
-   *
-   * If a table is set to be schema only, and empty array is returned.
-   *
-   * @param string $table
-   *   The table to query.
-   *
-   * @return array
-   *   The data from the table as an array.
-   */
-  protected function getTableData($table) {
-    // Check for schema only.
-    foreach ($this->schemaOnly as $schema_only) {
-      if (preg_match('/^' . $schema_only . '$/', $table)) {
-        return [];
-      }
-    }
-    $order = $this->getFieldOrder($table);
-    $query = $this->connection->query("SELECT * FROM {" . $table . "} " . $order );
-    $results = [];
-    while (($row = $query->fetchAssoc()) !== FALSE) {
-      $results[] = $row;
-    }
-    return $results;
-  }
-
-  /**
-   * Given a database field type, return a Drupal type.
-   *
-   * @param string $type
-   *   The MySQL field type.
-   *
-   * @return string
-   *   The Drupal schema field type. If there is no mapping, the original field
-   *   type is returned.
-   */
-  protected function fieldTypeMap($type) {
-    // Convert everything to lowercase.
-    $map = array_map('strtolower', $this->connection->schema()->getFieldTypeMap());
-    $map = array_flip($map);
-
-    // The MySql map contains type:size. Remove the size part.
-    return isset($map[$type]) ? explode(':', $map[$type])[0] : $type;
-  }
-
-  /**
-   * Given a database field type, return a Drupal size.
-   *
-   * @param string $type
-   *   The MySQL field type.
-   *
-   * @return string
-   *   The Drupal schema field size.
-   */
-  protected function fieldSizeMap($type) {
-    // Convert everything to lowercase.
-    $map = array_map('strtolower', $this->connection->schema()->getFieldTypeMap());
-    $map = array_flip($map);
-
-    $schema_type = explode(':', $map[$type])[0];
-    // Only specify size on these types.
-    if (in_array($schema_type, ['blob', 'float', 'int', 'text'])) {
-      // The MySql map contains type:size. Remove the type part.
-      return explode(':', $map[$type])[1];
-    }
-  }
-
-  /**
-   * Gets field ordering for a given table.
-   *
-   * @param string $table
-   *   The table name.
-   *
-   * @return string
-   *   The order string to append to the query.
-   */
-  protected function getFieldOrder($table) {
-    // @todo this is MySQL only since there are no Database API functions for
-    // table column data.
-    // @todo this code is duplicated in `core/scripts/migrate-db.sh`.
-    $connection_info = $this->connection->getConnectionOptions();
-    // Order by primary keys.
-    $order = '';
-    $query = "SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS`
-    WHERE (`TABLE_SCHEMA` = '" . $connection_info['database'] . "')
-    AND (`TABLE_NAME` = '{" . $table . "}') AND (`COLUMN_KEY` = 'PRI')
-    ORDER BY COLUMN_NAME";
-    $results = $this->connection->query($query);
-    while (($row = $results->fetchAssoc()) !== FALSE) {
-      $order .= $row['COLUMN_NAME'] . ', ';
-    }
-    if (!empty($order)) {
-      $order = ' ORDER BY ' . rtrim($order, ', ');
-    }
-    return $order;
-  }
-
-  /**
-   * The script template.
-   *
-   * @return string
-   *   The template for the generated PHP script.
-   */
-  protected function getTemplate() {
-    $script = <<<'ENDOFSCRIPT'
-<?php
-/**
- * @file
- * Filled installation of Drupal 8.0, for test purposes.
- *
- * This file was generated by the dump-database-d8.php script, from an
- * installation of Drupal 8. It has the following modules installed:
- *
-{{MODULES}}
- */
-
-use Drupal\Core\Database\Database;
-
-$connection = Database::getConnection();
-
-{{TABLES}}
-
-ENDOFSCRIPT;
-    return $script;
-  }
-
-  /**
-   * The part of the script for each table.
-   *
-   * @param string $table
-   *   Table name.
-   * @param array $schema
-   *   Drupal schema definition.
-   * @param array $data
-   *   Data for the table.
-   *
-   * @return string
-   *   The table create statement, and if there is data, the insert command.
-   */
-  protected function getTableScript($table, array $schema, array $data) {
-    $output = '';
-    $output .= "\$connection->schema()->createTable('" . $table . "', " . Variable::export($schema) . ");\n\n";
-    if (!empty($data)) {
-      $insert = '';
-      foreach ($data as $record) {
-        $insert .= "->values(" . Variable::export($record) . ")\n";
-      }
-      $output .= "\$connection->insert('" . $table . "')\n"
-        . "->fields(" . Variable::export(array_keys($schema['fields'])) . ")\n"
-        . $insert
-        . "->execute();\n\n";
-    }
-    return $output;
-  }
-
-  /**
-   * List of modules enabled for insertion into the script docblock.
-   *
-   * @return string
-   *   The formatted list of enabled modules.
-   */
-  protected function getModulesScript() {
-    $output = '';
-    $modules = $this->moduleHandler->getModuleList();
-    ksort($modules);
-    foreach ($modules as $module => $filename) {
-      $output .= " *  - $module\n";
-    }
-    return rtrim($output, "\n");
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Condition/ConditionPluginBase.php b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php
index 5237d0d..4b4a07b 100644
--- a/core/lib/Drupal/Core/Condition/ConditionPluginBase.php
+++ b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\Condition;
 
-use Drupal\Core\Executable\ExecutableManagerInterface;
 use Drupal\Core\Executable\ExecutablePluginBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
@@ -26,13 +25,6 @@
   use ContextAwarePluginAssignmentTrait;
 
   /**
-   * The condition manager to proxy execute calls through.
-   *
-   * @var \Drupal\Core\Executable\ExecutableInterface
-   */
-  protected $executableManager;
-
-  /**
    * {@inheritdoc}
    */
   public function __construct(array $configuration, $plugin_id, $plugin_definition) {
@@ -115,12 +107,4 @@ public function calculateDependencies() {
     return array();
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function setExecutableManager(ExecutableManagerInterface $executableManager) {
-    $this->executableManager = $executableManager;
-    return $this;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index ed50735..bae7618 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -755,7 +755,7 @@ protected function validate() {
   protected function processConfiguration($collection, $op, $name) {
     try {
       $processed = FALSE;
-      if ($collection == StorageInterface::DEFAULT_COLLECTION) {
+      if ($this->configManager->supportsConfigurationEntities($collection)) {
         $processed = $this->importInvokeOwner($collection, $op, $name);
       }
       if (!$processed) {
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 929731b..0ac79c0 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -175,39 +175,49 @@ public function installOptionalConfig(StorageInterface $storage = NULL, $depende
       $profile_storage = NULL;
     }
 
+    $collection_info = $this->configManager->getConfigCollectionInfo();
     $enabled_extensions = $this->getEnabledExtensions();
-    $existing_config = $this->getActiveStorages()->listAll();
 
-    $list = array_filter($storage->listAll(), function($config_name) use ($existing_config) {
-      // Only list configuration that:
-      // - does not already exist
-      // - is a configuration entity (this also excludes config that has an
-      //   implicit dependency on modules that are not yet installed)
-      return !in_array($config_name, $existing_config) && $this->configManager->getEntityTypeIdByName($config_name);
-    });
-
-    $all_config = array_merge($existing_config, $list);
-    $config_to_create = $storage->readMultiple($list);
-    // Check to see if the corresponding override storage has any overrides.
-    if ($profile_storage) {
-      $config_to_create = $profile_storage->readMultiple($list) + $config_to_create;
-    }
-    foreach ($config_to_create as $config_name => $data) {
-      // Exclude configuration where its dependencies cannot be met.
-      if (!$this->validateDependencies($config_name, $data, $enabled_extensions, $all_config)) {
-        unset($config_to_create[$config_name]);
+    foreach ($collection_info->getCollectionNames() as $collection) {
+      if (!$this->configManager->supportsConfigurationEntities($collection)) {
+        continue;
       }
-      // Exclude configuration that does not have a matching dependency.
-      elseif (!empty($dependency)) {
-        // Create a light weight dependency object to check dependencies.
-        $config_entity = new ConfigEntityDependency($config_name, $data);
-        if (!$config_entity->hasDependency(key($dependency), reset($dependency))) {
+      $existing_config = $this->getActiveStorages($collection)->listAll();
+
+      $list = array_filter($storage->listAll(), function($config_name) use ($existing_config) {
+        // Only list configuration that:
+        // - does not already exist
+        // - is a configuration entity (this also excludes config that has an
+        //   implicit dependency on modules that are not yet installed)
+        return !in_array($config_name, $existing_config) && $this->configManager->getEntityTypeIdByName($config_name);
+      });
+
+      $all_config = array_merge($existing_config, $list);
+      $config_to_create = $storage->readMultiple($list);
+      // Check to see if the corresponding override storage has any overrides.
+      if ($profile_storage) {
+        if ($profile_storage->getCollectionName() != $collection) {
+          $profile_storage = $profile_storage->createCollection($collection);
+        }
+        $config_to_create = $profile_storage->readMultiple($list) + $config_to_create;
+      }
+      foreach ($config_to_create as $config_name => $data) {
+        // Exclude configuration where its dependencies cannot be met.
+        if (!$this->validateDependencies($config_name, $data, $enabled_extensions, $all_config)) {
           unset($config_to_create[$config_name]);
         }
+        // Exclude configuration that does not have a matching dependency.
+        elseif (!empty($dependency)) {
+          // Create a light weight dependency object to check dependencies.
+          $config_entity = new ConfigEntityDependency($config_name, $data);
+          if (!$config_entity->hasDependency(key($dependency), reset($dependency))) {
+            unset($config_to_create[$config_name]);
+          }
+        }
+      }
+      if (!empty($config_to_create)) {
+        $this->createConfiguration($collection, $config_to_create, TRUE);
       }
-    }
-    if (!empty($config_to_create)) {
-      $this->createConfiguration(StorageInterface::DEFAULT_COLLECTION, $config_to_create, TRUE);
     }
   }
 
@@ -251,7 +261,8 @@ protected function getConfigToCreate(StorageInterface $storage, $collection, $pr
    */
   protected function createConfiguration($collection, array $config_to_create) {
     // Order the configuration to install in the order of dependencies.
-    if ($collection == StorageInterface::DEFAULT_COLLECTION) {
+    $config_entity_support = $this->configManager->supportsConfigurationEntities($collection);
+    if ($config_entity_support) {
       $dependency_manager = new ConfigDependencyManager();
       $config_names = $dependency_manager
         ->setData($config_to_create)
@@ -274,7 +285,7 @@ protected function createConfiguration($collection, array $config_to_create) {
       if ($config_to_create[$name] !== FALSE) {
         $new_config->setData($config_to_create[$name]);
       }
-      if ($collection == StorageInterface::DEFAULT_COLLECTION && $entity_type = $this->configManager->getEntityTypeIdByName($name)) {
+      if ($config_entity_support && $entity_type = $this->configManager->getEntityTypeIdByName($name)) {
         // If we are syncing do not create configuration entities. Pluggable
         // configuration entities can have dependencies on modules that are
         // not yet enabled. This approach means that any code that expects
diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index fb8f658..c70dd4c 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -355,6 +355,13 @@ public function getConfigEntitiesToChangeOnDependencyRemoval($type, array $names
   /**
    * {@inheritdoc}
    */
+  public function supportsConfigurationEntities($collection) {
+    return $collection == StorageInterface::DEFAULT_COLLECTION;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getConfigCollectionInfo() {
     if (!isset($this->configCollectionInfo)) {
       $this->configCollectionInfo = new ConfigCollectionInfo();
diff --git a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
index d908e3f..7da86f7 100644
--- a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
@@ -162,6 +162,17 @@ public function findConfigEntityDependentsAsEntities($type, array $names);
   public function getConfigEntitiesToChangeOnDependencyRemoval($type, array $names, $dry_run = TRUE);
 
   /**
+   * Determines if the provided collection supports configuration entities.
+   *
+   * @param string $collection
+   *   The collection to check.
+   *
+   * @return bool
+   *   TRUE if the collection support configuration entities, FALSE if not.
+   */
+  public function supportsConfigurationEntities($collection);
+
+  /**
    * Gets available collection information using the event system.
    *
    * @return \Drupal\Core\Config\ConfigCollectionInfo
diff --git a/core/lib/Drupal/Core/Config/StorageComparer.php b/core/lib/Drupal/Core/Config/StorageComparer.php
index 2e61f96..7b3b3d4 100644
--- a/core/lib/Drupal/Core/Config/StorageComparer.php
+++ b/core/lib/Drupal/Core/Config/StorageComparer.php
@@ -212,7 +212,7 @@ public function createChangelist() {
       $this->addChangelistUpdate($collection);
       $this->addChangelistDelete($collection);
       // Only collections that support configuration entities can have renames.
-      if ($collection == StorageInterface::DEFAULT_COLLECTION) {
+      if ($this->configManager->supportsConfigurationEntities($collection)) {
         $this->addChangelistRename($collection);
       }
     }
@@ -415,7 +415,7 @@ protected function getAndSortConfigData($collection) {
     $source_data = $source_storage->readMultiple($source_names);
     // If the collection only supports simple configuration do not use
     // configuration dependencies.
-    if ($collection == StorageInterface::DEFAULT_COLLECTION) {
+    if ($this->configManager->supportsConfigurationEntities($collection)) {
       $dependency_manager = new ConfigDependencyManager();
       $this->targetNames[$collection] = $dependency_manager->setData($target_data)->sortAll();
       $this->sourceNames[$collection] = $dependency_manager->setData($source_data)->sortAll();
diff --git a/core/lib/Drupal/Core/ContentNegotiation.php b/core/lib/Drupal/Core/ContentNegotiation.php
index 1074b81..e45c92d 100644
--- a/core/lib/Drupal/Core/ContentNegotiation.php
+++ b/core/lib/Drupal/Core/ContentNegotiation.php
@@ -10,7 +10,10 @@
 use Symfony\Component\HttpFoundation\Request;
 
 /**
- * Provides content negotation based upon query parameters.
+ * This class is a central library for content type negotiation.
+ *
+ * @todo Replace this class with a real content negotiation library based on
+ *   mod_negotiation. Development of that is a work in progress.
  */
 class ContentNegotiation {
 
@@ -33,8 +36,21 @@ public function getContentType(Request $request) {
       return 'iframeupload';
     }
 
-    if ($request->query->has('_format')) {
-      return $request->query->get('_format');
+    // Check all formats, if priority format is found return it.
+    $first_found_format = FALSE;
+    foreach ($request->getAcceptableContentTypes() as $mime_type) {
+      $format = $request->getFormat($mime_type);
+      if ($format === 'html') {
+        return $format;
+      }
+      if (!is_null($format) && !$first_found_format) {
+        $first_found_format = $format;
+      }
+    }
+
+    // No HTML found, return first found.
+    if ($first_found_format) {
+      return $first_found_format;
     }
 
     if ($request->isXmlHttpRequest()) {
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/ConditionResolver.php b/core/lib/Drupal/Core/Database/Driver/fake/ConditionResolver.php
new file mode 100644
index 0000000..ea69504
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/ConditionResolver.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\ConditionResolver.
+ */
+
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Query\Condition;
+
+class ConditionResolver {
+
+  /**
+   * Match a row against a group of conditions.
+   *
+   * @param \Drupal\Core\Database\Driver\fake\DatabaseRowInterface $row
+   *   The database row object.
+   * @param \Drupal\Core\Database\Query\Condition $condition_group
+   *   The condition group object.
+   *
+   * @return bool
+   *   TRUE if there is a match.
+   */
+  public static function matchGroup(DatabaseRowInterface $row, Condition $condition_group) {
+    $conditions = $condition_group->conditions();
+    $and = $conditions['#conjunction'] == 'AND';
+    unset($conditions['#conjunction']);
+    $match = TRUE;
+    foreach ($conditions as $condition) {
+      $match = $condition['field'] instanceof Condition ? static::matchGroup($row, $condition['field']) : static::matchSingle($row, $condition);
+      // For AND, finish matching on the first fail. For OR, finish on first
+      // success.
+      if ($and != $match) {
+        break;
+      }
+    }
+    return $match;
+  }
+
+  /**
+   * Match a single row and its condition.
+   *
+   * @param \Drupal\migrate\tests\DatabaseRowInterface $row
+   *   The row to match.
+   *
+   * @param array $condition
+   *   An array representing a single condition.
+   *
+   * @return bool
+   *   TRUE if the condition matches.
+   *
+   * @throws \Exception
+   */
+  protected static function matchSingle(DatabaseRowInterface $row, array $condition) {
+    $row_value = $row->getValue($condition['field']);
+    switch ($condition['operator']) {
+      case '=':
+        return $row_value == $condition['value'];
+
+      case '<=':
+        return $row_value <= $condition['value'];
+
+      case '>=':
+        return $row_value >= $condition['value'];
+
+      case '!=':
+        return $row_value != $condition['value'];
+
+      case '<>':
+        return $row_value != $condition['value'];
+
+      case '<':
+        return $row_value < $condition['value'];
+
+      case '>':
+        return $row_value > $condition['value'];
+
+      case 'IN':
+        return in_array($row_value, $condition['value']);
+
+      case 'IS NULL':
+        return !isset($row_value);
+
+      case 'IS NOT NULL':
+        return isset($row_value);
+
+      default:
+        throw new \Exception(sprintf('operator %s is not supported', $condition['operator']));
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRow.php b/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRow.php
new file mode 100644
index 0000000..ca98582
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRow.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\DatabaseRow.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+class DatabaseRow implements DatabaseRowInterface {
+
+  /**
+   * Construct a new row.
+   *
+   * @param array $row
+   *   The row data.
+   */
+  public function __construct(array $row) {
+    $this->row = $row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue($field) {
+    return $this->row[$field];
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRowInterface.php b/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRowInterface.php
new file mode 100644
index 0000000..9aa3965
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRowInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\DatabaseRowInterface.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+interface DatabaseRowInterface {
+
+  /**
+   * Get the field value from the row.
+   *
+   * @param mixed $field
+   *   The field to get the value of.
+   *
+   * @return mixed
+   *   The field value from the row.
+   */
+  public function getValue($field);
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRowSelect.php b/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRowSelect.php
new file mode 100644
index 0000000..41bbf55
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/DatabaseRowSelect.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\DatabaseRowSelect.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+class DatabaseRowSelect extends DatabaseRow {
+
+  /**
+   * Construct a new database row.
+   *
+   * @param array $row
+   *   The row data.
+   * @param array $fields_with_table
+   *   The fields with a table.
+   * @param array $fields
+   *   The fields.
+   */
+  public function __construct(array $row, array $fields_with_table, array $fields) {
+    $this->fieldsWithTable = $fields_with_table;
+    $this->fields = $fields;
+    parent::__construct($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue($field) {
+    $field_info = isset($this->fieldsWithTable[$field]) ? $this->fieldsWithTable[$field] : $this->fields[$field];
+    if (array_key_exists($field_info['field'], $this->row[$field_info['table']]['result'])) {
+      $index = 'result';
+    }
+    else {
+      $index = 'all';
+    }
+    return $this->row[$field_info['table']][$index][$field_info['field']];
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeConnection.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeConnection.php
new file mode 100644
index 0000000..1be5147
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeConnection.php
@@ -0,0 +1,167 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeConnection.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Connection;
+
+/**
+ * Defines a fake connection for use during testing.
+ */
+class FakeConnection extends Connection {
+
+  /**
+   * Table prefix on the database.
+   *
+   * @var string
+   */
+  protected $tablePrefix;
+
+  /**
+   * Connection options for the database.
+   *
+   * @var array
+   */
+  protected $connectionOptions;
+
+  /**
+   * Constructs a FakeConnection.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param array $connection_options
+   *   (optional) The array of connection options for the database.
+   * @param string $prefix
+   *   (optional) The table prefix on the database.
+   */
+  public function __construct(array $database_contents, $connection_options = array(), $prefix = '') {
+    $this->databaseContents = $database_contents;
+    $this->connectionOptions = $connection_options;
+    $this->tablePrefix = $prefix;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConnectionOptions() {
+    return $this->connectionOptions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tablePrefix($table = 'default') {
+    return $this->tablePrefix;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function select($table, $alias = NULL, array $options = array()) {
+    return new FakeSelect($this->databaseContents, $table, $alias);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function insert($table, array $options = array()) {
+    return new FakeInsert($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function merge($table, array $options = array()) {
+    return new FakeMerge($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function update($table, array $options = array()) {
+    return new FakeUpdate($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function delete($table, array $options = array()) {
+    return new FakeDelete($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function truncate($table, array $options = array()) {
+    return new FakeTruncate($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function schema() {
+    return new FakeDatabaseSchema($this->databaseContents);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query($query, array $args = array(), $options = array()) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function queryTemporary($query, array $args = array(), array $options = array()) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function driver() {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function databaseType() {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createDatabase($database) {
+    // There is nothing to do.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function mapConditionOperator($operator) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function nextId($existing_id = 0) {
+    throw new \Exception('Method not supported');
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeDatabaseSchema.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeDatabaseSchema.php
new file mode 100644
index 0000000..d3e9161
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeDatabaseSchema.php
@@ -0,0 +1,230 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeDatabaseSchema.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Schema;
+
+class FakeDatabaseSchema extends Schema {
+
+  /**
+   * As set on MigrateSqlSourceTestCase::databaseContents.
+   *
+   * @var array
+   */
+  public $databaseContents;
+
+  /**
+   * Constructs a fake database schema.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   */
+  public function __construct(array &$database_contents) {
+    $this->uniqueIdentifier = uniqid('', TRUE);
+
+    // @todo Maybe we can generate an internal representation.
+    $this->databaseContents = &$database_contents;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tableExists($table) {
+    return in_array($table, array_keys($this->databaseContents));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prefixNonTable($table) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getPrefixInfo($table = 'default', $add_prefix = TRUE) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addField($table, $field, $spec, $keys_new = array()) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addPrimaryKey($table, $fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addUniqueKey($table, $name, $fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * PHP magic __clone() method.
+   */
+  public function __clone() {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createTable($name, $table) {
+    #throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropField($table, $field) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropIndex($table, $name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropPrimaryKey($table) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropTable($table) {
+    unset($this->databaseContents[$table]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropUniqueKey($table, $name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldExists($table, $column) {
+    if (!empty($this->databaseContents[$table])) {
+      $row = reset($this->databaseContents[$table]);
+      return isset($row[$column]);
+    }
+    else {
+      throw new \Exception("Can't determine whether field exists with an empty / nonexistent table.");
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldNames($fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldSetDefault($table, $field, $default) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldSetNoDefault($table, $field) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function findTables($table_expression) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldTypeMap() {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function indexExists($table, $name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function nextPlaceholder() {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareComment($comment, $length = NULL) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function renameTable($table, $new_name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uniqueIdentifier() {
+    return $this->uniqueIdentifier;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeDelete.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeDelete.php
new file mode 100644
index 0000000..4a75bfb
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeDelete.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeDelete.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\Delete;
+use Drupal\Core\Database\Query\SelectInterface;
+
+/**
+ * Defines FakeDelete for use in database tests.
+ */
+class FakeDelete extends Delete {
+
+  /**
+   * The database table to delete from.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * The database contents.
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  /**
+   * Constructs a FakeDelete object.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to delete from.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    $affected = 0;
+    if (isset($this->databaseContents[$this->table])) {
+      $original_row_count = count($this->databaseContents[$this->table]);
+      $condition = $this->condition;
+      $this->databaseContents[$this->table] = array_filter($this->databaseContents[$this->table], function ($row_array) use ($condition) {
+        $row = new DatabaseRow($row_array);
+        return !ConditionResolver::matchGroup($row, $condition);
+      });
+      $affected = $original_row_count - count($this->databaseContents[$this->table]);
+    }
+    return $affected;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function exists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function where($snippet, $args = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeInsert.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeInsert.php
new file mode 100644
index 0000000..9d7012b
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeInsert.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeInsert.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Query\Insert;
+use Drupal\Core\Database\Query\SelectInterface;
+
+/**
+ * Defines FakeInsert for use in database tests.
+ */
+class FakeInsert extends Insert {
+
+  /**
+   * The database contents.
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  /**
+   * The database table to insert into.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * Constructs a fake insert object.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to insert into.
+   * @param array $options
+   *   (optional) The database options. Not used.
+   */
+  public function __construct(array &$database_contents, $table, array $options = array()) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function useDefaults(array $fields) {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function from(SelectInterface $query) {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    foreach ($this->insertValues as $values) {
+      $this->databaseContents[$this->table][] = array_combine($this->insertFields, $values);
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeMerge.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeMerge.php
new file mode 100644
index 0000000..dd3117e
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeMerge.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeMerge.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\InvalidMergeQueryException;
+use Drupal\Core\Database\Query\Merge;
+
+/**
+ * Defines FakeMerge for use in database tests.
+ */
+class FakeMerge extends Merge {
+
+  /**
+   * Constructs a fake merge object and initializes the conditions.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The database table to merge into.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+    $this->conditionTable = $table;
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    if (!count($this->condition)) {
+      throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
+    }
+    $select = new FakeSelect($this->databaseContents, $this->conditionTable, 'c');
+    $count = $select
+      ->condition($this->condition)
+      ->countQuery()
+      ->execute()
+      ->fetchField();
+    if ($count) {
+      $update = new FakeUpdate($this->databaseContents, $this->table);
+      $update
+        ->fields($this->updateFields)
+        ->condition($this->condition)
+        ->execute();
+      return self::STATUS_UPDATE;
+    }
+    $insert = new FakeInsert($this->databaseContents, $this->table);
+    $insert->fields($this->insertFields)->execute();
+    return self::STATUS_INSERT;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeSelect.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeSelect.php
new file mode 100644
index 0000000..9a95a6e
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeSelect.php
@@ -0,0 +1,529 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeSelect.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\PlaceholderInterface;
+use Drupal\Core\Database\Query\Select;
+use Drupal\Core\Database\Query\SelectInterface;
+
+class FakeSelect extends Select {
+
+  /**
+   * Contents of the pseudo-database.
+   *
+   * Keys are table names and values are arrays of rows in the table.
+   * Every row there contains all table field values keyed by field name.
+   *
+   * @code
+   * array(
+   *   'user' => array(
+   *     array(
+   *       'uid' => 1,
+   *       'name' => 'admin',
+   *     ),
+   *     array(
+   *       'uid' => 2,
+   *       'name' => 'alice',
+   *     ),
+   *   ),
+   *   'node' => array(
+   *     array(
+   *       'nid' => 1,
+   *     )
+   *   )
+   * )
+   * @endcode
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  protected $countQuery = FALSE;
+  protected $fieldsWithTable = array();
+
+  /**
+   * Constructs a new FakeSelect.
+   *
+   * @param array $database_contents
+   *   An array of mocked database content.
+   * @param string $table
+   *   The base table name used within fake select.
+   * @param string $alias
+   *   The base table alias used within fake select.
+   * @param string $conjunction
+   *   The operator to use to combine conditions: 'AND' or 'OR'.
+   */
+  public function __construct(array $database_contents, $table, $alias, $conjunction = 'AND') {
+    $this->databaseContents = $database_contents;
+    $this->addJoin(NULL, $table, $alias);
+    $this->where = new Condition($conjunction);
+    $this->having = new Condition($conjunction);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->addJoin('LEFT', $table, $alias, $condition, $arguments);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    if ($table instanceof SelectInterface) {
+      // @todo implement this.
+      throw new \Exception('Subqueries are not supported at this moment.');
+    }
+    $alias = parent::addJoin($type, $table, $alias, $condition, $arguments);
+    if (isset($type)) {
+      if ($type != 'INNER' && $type != 'LEFT') {
+        throw new \Exception(sprintf('%s type not supported, only INNER and LEFT.', $type));
+      }
+      if (!preg_match('/^(\w+\.)?(\w+)\s*=\s*(\w+)\.(\w+)$/', $condition, $matches)) {
+        throw new \Exception('Only x.field1 = y.field2 conditions are supported.' . $condition);
+      }
+      if (!$matches[1] && count($this->tables) == 2) {
+        $aliases = array_keys($this->tables);
+        $matches[1] = $aliases[0];
+      }
+      else {
+        $matches[1] = substr($matches[1], 0, -1);
+      }
+      if (!$matches[1]) {
+        throw new \Exception('Only x.field1 = y.field2 conditions are supported.' . $condition);
+      }
+      if ($matches[1] == $alias) {
+        $this->tables[$alias] += array(
+          'added_field' => $matches[2],
+          'original_table_alias' => $matches[3],
+          'original_field' => $matches[4],
+        );
+      }
+      elseif ($matches[3] == $alias) {
+        $this->tables[$alias] += array(
+          'added_field' => $matches[4],
+          'original_table_alias' => $matches[1],
+          'original_field' => $matches[2],
+        );
+      }
+      else {
+        throw new \Exception('The JOIN condition does not contain the alias of the joined table.');
+      }
+    }
+    return $alias;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    // @todo: Implement distinct() handling.
+
+    // Single table count queries often do not contain fields which this class
+    // does not support otherwise, so add a shortcut.
+    if (count($this->tables) == 1 && $this->countQuery) {
+      $table_info = reset($this->tables);
+      $where = $this->where;
+      if (!empty($this->databaseContents[$table_info['table']])) {
+        $results = array_filter($this->databaseContents[$table_info['table']], function ($row_array) use ($where) {
+          return ConditionResolver::matchGroup(new DatabaseRow($row_array), $where);
+        });
+      }
+      else {
+        $results = array();
+      }
+    }
+    else {
+      $all_rows = $this->executeJoins();
+      $all_rows = $this->resolveConditions($this->where, $all_rows);
+      if (!empty($this->order)) {
+        usort($all_rows, array($this, 'sortCallback'));
+      }
+      // Now flatten the rows so that each row becomes a field alias => value
+      // array.
+      $results = array();
+      foreach ($all_rows as $table_rows) {
+        $result_row = array();
+        foreach ($table_rows as $row) {
+          $result_row += $row['result'];
+        }
+        $results[] = $result_row;
+      }
+    }
+    if (!empty($this->range)) {
+      $results = array_slice($results, $this->range['start'], $this->range['length']);
+    }
+    if ($this->countQuery) {
+      $results = array(array(count($results)));
+    }
+    return new FakeStatement($results);
+  }
+
+  /**
+   * Create an initial result set by executing the joins and picking fields.
+   *
+   * @return array
+   *   A multidimensional array, the first key are table aliases, the second
+   *   are field aliases, the values are the database contents or NULL in case
+   *   of JOINs.
+   */
+  protected function executeJoins() {
+    $fields = array();
+    foreach ($this->fields as $field_info) {
+      $this->fieldsWithTable[$field_info['table'] . '.' . $field_info['field']] = $field_info;
+      $fields[$field_info['table']][$field_info['field']] = $field_info['alias'];
+    }
+    foreach ($this->tables as $alias => $table_info) {
+      if ($table = reset($this->databaseContents[$table_info['table']])) {
+        foreach (array_keys($table) as $field) {
+          if (!isset($this->fields[$field])) {
+            $this->fieldsWithTable[$field] = array(
+              'table' => $alias,
+              'field' => $field,
+            );
+            $this->fieldsWithTable["$alias.$field"] = array(
+              'table' => $alias,
+              'field' => $field,
+            );
+          }
+        }
+      }
+    }
+    // This will contain a multiple dimensional array. The first key will be a
+    // table alias, the second either result or all, the third will be a field
+    // alias. all contains every field in the table with the original field
+    // names while result contains only the fields requested. This allows for
+    // filtering on fields that were not added via addField().
+    $results = array();
+    foreach ($this->tables as $table_alias => $table_info) {
+      // The base table for this query.
+      if (empty($table_info['join type'])) {
+        foreach ($this->databaseContents[$table_info['table']] as $candidate_row) {
+          $results[] = $this->getNewRow($table_alias, $fields, $candidate_row);
+        }
+      }
+      else {
+        $new_rows = array();
+
+        // Dynamically build a set of joined rows. Check existing rows and see
+        // if they can be joined with incoming rows.
+        foreach ($results as $row) {
+          $joined = FALSE;
+          foreach ($this->databaseContents[$table_info['table']] as $candidate_row) {
+            if ($row[$table_info['original_table_alias']]['result'][$table_info['original_field']] == $candidate_row[$table_info['added_field']]) {
+              $joined = TRUE;
+              $new_rows[] = $this->getNewRow($table_alias, $fields, $candidate_row, $row);
+            }
+          }
+          if (!$joined && $table_info['join type'] == 'LEFT') {
+            // Because PHP doesn't scope their foreach statements,
+            // $candidate_row may contain the last value assigned to it from the
+            // previous statement.
+            // @TODO: empty tables? Those are a problem.
+            $keys = array_keys($candidate_row);
+            $values = array_fill(0, count($keys), NULL);
+            $new_row = array(
+              'result' => $fields[$table_alias],
+              'all' => array_combine($keys, $values),
+            );
+            $new_rows[] = array($table_alias => $new_row) + $row;
+          }
+        }
+        $results = $new_rows;
+      }
+    }
+    return $results;
+  }
+
+  /**
+   * Retrieves a new row.
+   *
+   * @param string $table_alias
+   * @param array $fields
+   * @param array $candidate_row
+   * @param array $row
+   *
+   * @return array
+   */
+  protected function getNewRow($table_alias, $fields, $candidate_row, $row = array()) {
+    $new_row[$table_alias]['all'] = $candidate_row;
+    foreach ($fields[$table_alias] as $field => $alias) {
+      $new_row[$table_alias]['result'][$alias] = $candidate_row[$field];
+    }
+    return $new_row + $row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function countQuery() {
+    $query = clone $this;
+    return $query->setCountQuery();
+  }
+
+  /**
+   * Set this query to be a count query.
+   */
+  protected function setCountQuery() {
+    $this->countQuery = TRUE;
+    return $this;
+  }
+
+  /**
+   * usort callback to order the results.
+   */
+  protected function sortCallback($a, $b) {
+    $a_row = new DatabaseRowSelect($a, $this->fieldsWithTable, $this->fields);
+    $b_row = new DatabaseRowSelect($b, $this->fieldsWithTable, $this->fields);
+    foreach ($this->order as $field => $direction) {
+      $a_value = $a_row->getValue($field);
+      $b_value = $b_row->getValue($field);
+      if ($a_value != $b_value) {
+        return (($a_value < $b_value) == ($direction == 'ASC')) ? -1 : 1;
+      }
+    }
+    return 0;
+  }
+
+  /**
+   * Resolves conditions by removing non-matching rows.
+   *
+   * @param \Drupal\Core\Database\Query\Condition $condition_group
+   *   The condition group to check.
+   * @param array $rows
+   *   An array of rows excluding non-matching rows.
+   *
+   * @return \Drupal\Core\Database\Driver\fake\ConditionResolver
+   *   The condition resolver object.
+   */
+  protected function resolveConditions(Condition $condition_group, array &$rows) {
+    $fields_with_table = $this->fieldsWithTable;
+    $fields = $this->fields;
+    return array_filter($rows, function ($row_array) use ($condition_group, $fields_with_table, $fields) {
+      $row = new DatabaseRowSelect($row_array, $fields_with_table, $fields);
+      return ConditionResolver::matchGroup($row, $condition_group);
+    });
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderBy($field, $direction = 'ASC') {
+    $this->order[$field] = strtoupper($direction);
+    return $this;
+  }
+
+  // ================== we could support these.
+  /**
+   * {@inheritdoc}
+   */
+  public function groupBy($field) {
+    // @todo: Implement groupBy() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function havingCondition($field, $value = NULL, $operator = NULL) {
+    // @todo: Implement havingCondition() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uniqueIdentifier() {
+    // TODO: Implement uniqueIdentifier() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  // ================== the rest won't be supported, ever.
+  /**
+   * {@inheritdoc}
+   */
+  public function nextPlaceholder() {
+    // TODO: Implement nextPlaceholder() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isPrepared() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preExecute(SelectInterface $query = NULL) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function where($snippet, $args = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extend($extender_name) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getExpressions() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getGroupBy() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getUnion() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function forUpdate($set = TRUE) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &conditions() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderRandom() {
+    // We could implement this but why bother.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function union(SelectInterface $query, $type = '') {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addExpression($expression, $alias = NULL, $arguments = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getTables() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getArguments(PlaceholderInterface $query_place_holder = NULL) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getOrderBy() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getFields() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function exists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function notExists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function arguments() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function compile(Connection $connection, PlaceholderInterface $query_place_holder) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function compiled() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields($table_alias, array $fields = array()) {
+    if (!$fields) {
+      $table = $this->tables[$table_alias]['table'];
+      if (!empty($this->databaseContents[$table])) {
+        $fields = array_keys(reset($this->databaseContents[$table]));
+      }
+      else {
+        throw new \Exception(SafeMarkup::format('All fields on empty table @table is not supported.', array('@table' => $table)));
+      }
+    }
+    return parent::fields($table_alias, $fields);
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeStatement.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeStatement.php
new file mode 100644
index 0000000..7aaf574
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeStatement.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeStatement.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\RowCountException;
+use Drupal\Core\Database\StatementInterface;
+
+/**
+ * Represents a fake prepared statement.
+ */
+class FakeStatement extends \ArrayIterator implements StatementInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute($args = array(), $options = array()) {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQueryString() {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function rowCount() {
+    throw new RowCountException();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchField($index = 0) {
+    $row = array_values($this->current());
+    $return = $row[$index];
+    $this->next();
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchAssoc() {
+    $return = FALSE;
+    if ($this->valid()) {
+      $return = $this->current();
+      $this->next();
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchCol($index = 0) {
+    $return = array();
+    foreach ($this as $row) {
+      $row = array_values($row);
+      $return[] = $row[$index];
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchAllKeyed($key_index = 0, $value_index = 1) {
+    $return = array();
+    foreach ($this as $row) {
+      $row = array_values($row);
+      $return[$row[$key_index]] = $row[$value_index];
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchAllAssoc($key, $fetch = NULL) {
+    $return = array();
+    foreach ($this as $row) {
+      $return[$row[$key]] = $row;
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchObject() {
+    $return = $this->fetchAssoc();
+    return $return === FALSE ? FALSE : (object) $return;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeTruncate.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeTruncate.php
new file mode 100644
index 0000000..d0be873
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeTruncate.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeTruncate.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+/**
+ * Defines FakeTruncate for use in database tests.
+ */
+class FakeTruncate {
+
+  /**
+   * Constructs a FakeTruncate object.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to truncate.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+  }
+
+  /**
+   * Executes the TRUNCATE query.
+   */
+  public function execute() {
+    $this->databaseContents[$this->table] = array();
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/FakeUpdate.php b/core/lib/Drupal/Core/Database/Driver/fake/FakeUpdate.php
new file mode 100644
index 0000000..0505c22
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/FakeUpdate.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\Driver\fake\FakeUpdate.
+ */
+
+namespace Drupal\Core\Database\Driver\fake;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\SelectInterface;
+use Drupal\Core\Database\Query\Update;
+
+/**
+ * Defines FakeUpdate for use in database tests.
+ */
+class FakeUpdate extends Update {
+
+  /**
+   * The database table to update.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * The database contents.
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  /**
+   * Constructs a FakeUpdate object and initializes the condition.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to update.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    $affected = 0;
+    if (isset($this->databaseContents[$this->table])) {
+      $fields = $this->fields;
+      $condition = $this->condition;
+      array_walk($this->databaseContents[$this->table], function (&$row_array) use ($fields, $condition, &$affected) {
+        $row = new DatabaseRow($row_array);
+        if (ConditionResolver::matchGroup($row, $condition)) {
+          $row_array = $fields + $row_array;
+          $affected++;
+        }
+      });
+    }
+    return $affected;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function exists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function where($snippet, $args = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function expression($field, $expression, array $arguments = NULL) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/fake/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/fake/Install/Tasks.php
new file mode 100644
index 0000000..11ed2f3
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/fake/Install/Tasks.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\fake\Install\Tasks
+ */
+
+namespace Drupal\Core\Database\Driver\fake\Install;
+
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Driver\mysql\Connection;
+use Drupal\Core\Database\DatabaseNotFoundException;
+
+/**
+ * Usually used to specify installation tasks but here we're only interested
+ * in setting $error to TRUE.
+ */
+class Tasks extends InstallTasks {
+  /**
+   * Prevent the installer from recognising this as a potential database driver.
+   * @TODO Looks like this is needed only if we define $pdoDriver to something valid e.g. mysql.
+   * Not sure we need to do that. We may not need this file at all?
+   *
+   * @var bool
+   */
+  protected $error = TRUE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function name() {
+    return t('Fake database connection for use in unit tests');
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
index 68324b2..89d4069 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
@@ -48,7 +48,7 @@ public function getFormOptions(array $database) {
     // Make the text more accurate for SQLite.
     $form['database']['#title'] = t('Database file');
     $form['database']['#description'] = t('The absolute path to the file where @drupal data will be stored. This must be writable by the web server and should exist outside of the web root.', array('@drupal' => drupal_install_profile_distribution_name()));
-    $default_database = \Drupal::service('site.path') . '/files/.ht.sqlite';
+    $default_database = conf_path(FALSE) . '/files/.ht.sqlite';
     $form['database']['#default_value'] = empty($database['database']) ? $default_database : $database['database'];
     return $form;
   }
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
index 21672fb..154470d 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
@@ -260,7 +260,7 @@ public function renameTable($table, $new_name) {
     $schema = $this->introspectSchema($table);
 
     // SQLite doesn't allow you to rename tables outside of the current
-    // database. So the syntax '... RENAME TO database.table' would fail.
+    // database. So the syntax '...RENAME TO database.table' would fail.
     // So we must determine the full table name here rather than surrounding
     // the table with curly braces in case the db_prefix contains a reference
     // to a database outside of our existing database.
diff --git a/core/lib/Drupal/Core/Datetime/DateFormatter.php b/core/lib/Drupal/Core/Datetime/DateFormatter.php
index 0aad043..82e9969 100644
--- a/core/lib/Drupal/Core/Datetime/DateFormatter.php
+++ b/core/lib/Drupal/Core/Datetime/DateFormatter.php
@@ -15,7 +15,6 @@
 use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
  * Provides a service to handler various date related functionality.
@@ -53,13 +52,6 @@ class DateFormatter {
    */
   protected $configFactory;
 
-  /**
-   * The request stack.
-   *
-   * @var \Symfony\Component\HttpFoundation\RequestStack
-   */
-  protected $requestStack;
-
   protected $country = NULL;
   protected $dateFormats = array();
 
@@ -93,15 +85,12 @@ class DateFormatter {
    *   The string translation.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The configuration factory.
-   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
-   *   The request stack.
    */
-  public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, TranslationInterface $translation, ConfigFactoryInterface $config_factory, RequestStack $request_stack) {
+  public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, TranslationInterface $translation, ConfigFactoryInterface $config_factory) {
     $this->dateFormatStorage = $entity_manager->getStorage('date_format');
     $this->languageManager = $language_manager;
     $this->stringTranslation = $translation;
     $this->configFactory = $config_factory;
-    $this->requestStack = $request_stack;
   }
 
   /**
@@ -122,13 +111,13 @@ public function __construct(EntityManagerInterface $entity_manager, LanguageMana
    *   (optional) If $type is 'custom', a PHP date format string suitable for
    *   input to date(). Use a backslash to escape ordinary text, so it does not
    *   get interpreted as date format characters.
-   * @param string|null $timezone
+   * @param string $timezone
    *   (optional) Time zone identifier, as described at
    *   http://php.net/manual/timezones.php Defaults to the time zone used to
    *   display the page.
-   * @param string|null $langcode
-   *   (optional) Language code to translate to. NULL (default) means to use
-   *   the user interface language for the page.
+   * @param string $langcode
+   *   (optional) Language code to translate to. Defaults to the language used to
+   *   display the page.
    *
    * @return string
    *   A translated date string in the requested format.
@@ -174,26 +163,17 @@ public function format($timestamp, $type = 'medium', $format = '', $timezone = N
   /**
    * Formats a time interval with the requested granularity.
    *
-   * Note that for intervals over 30 days, the output is approximate: a "month"
-   * is always exactly 30 days, and a "year" is always 365 days. It is not
-   * possible to make a more exact representation, given that there is only one
-   * input in seconds. If you are formatting an interval between two specific
-   * timestamps, use \Drupal\Core\Datetime\DateFormatter::formatDiff() instead.
-   *
    * @param int $interval
    *   The length of the interval in seconds.
    * @param int $granularity
    *   (optional) How many different units to display in the string (2 by
    *   default).
-   * @param string|null $langcode
-   *   (optional) langcode: The language code for the language used to format
-   *   the date. Defaults to NULL, which results in the user interface language
-   *   for the page being used.
+   * @param string $langcode
+   *   (optional) Language code to translate to a language other than what is
+   *   used to display the page. Defaults to NULL.
    *
    * @return string
    *   A translated string representation of the interval.
-   *
-   * @see \Drupal\Core\Datetime\DateFormatter::formatDiff()
    */
   public function formatInterval($interval, $granularity = 2, $langcode = NULL) {
     $output = '';
@@ -234,186 +214,12 @@ public function getSampleDateFormats($langcode = NULL, $timestamp = NULL, $timez
     // All date format characters for the PHP date() function.
     $date_chars = str_split('dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU');
     $date_elements = array_combine($date_chars, $date_chars);
-    return array_map(function ($character) use ($timestamp, $timezone, $langcode) {
+    return array_map(function($character) use ($timestamp, $timezone, $langcode) {
       return $this->format($timestamp, 'custom', $character, $timezone, $langcode);
     }, $date_elements);
   }
 
   /**
-   * Formats the time difference from the current request time to a timestamp.
-   *
-   * @param $timestamp
-   *   A UNIX timestamp to compare against the current request time.
-   * @param array $options
-   *   (optional) An associative array with additional options. The following
-   *   keys can be used:
-   *   - granularity: An integer value that signals how many different units to
-   *     display in the string. Defaults to 2.
-   *   - langcode: The language code for the language used to format the date.
-   *     Defaults to NULL, which results in the user interface language for the
-   *     page being used.
-   *   - strict: A Boolean value indicating whether or not the timestamp can be
-   *     before the current request time. If TRUE (default) and $timestamp is
-   *     before the current request time, the result string will be "0 seconds".
-   *     If FALSE and $timestamp is before the current request time, the result
-   *     string will be the formatted time difference.
-   *
-   * @return string
-   *   A translated string representation of the difference between the given
-   *   timestamp and the current request time. This interval is always positive.
-   *
-   * @see \Drupal\Core\Datetime\DateFormatter::formatDiff()
-   * @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffSince()
-   */
-  public function formatTimeDiffUntil($timestamp, $options = array()) {
-    $request_time = $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME');
-    return $this->formatDiff($request_time, $timestamp, $options);
-  }
-
-  /**
-   * Formats the time difference from a timestamp to the current request time.
-   *
-   * @param $timestamp
-   *   A UNIX timestamp to compare against the current request time.
-   * @param array $options
-   *   (optional) An associative array with additional options. The following
-   *   keys can be used:
-   *   - granularity: An integer value that signals how many different units to
-   *     display in the string. Defaults to 2.
-   *   - langcode: The language code for the language used to format the date.
-   *     Defaults to NULL, which results in the user interface language for the
-   *     page being used.
-   *   - strict: A Boolean value indicating whether or not the timestamp can be
-   *     after the current request time. If TRUE (default) and $timestamp is
-   *     after the current request time, the result string will be "0 seconds".
-   *     If FALSE and $timestamp is after the current request time, the result
-   *     string will be the formatted time difference.
-   *
-   * @return string
-   *   A translated string representation of the difference between the given
-   *   timestamp and the current request time. This interval is always positive.
-   *
-   * @see \Drupal\Core\Datetime\DateFormatter::formatDiff()
-   * @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffUntil()
-   */
-  public function formatTimeDiffSince($timestamp, $options = array()) {
-    $request_time = $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME');
-    return $this->formatDiff($timestamp, $request_time, $options);
-  }
-
-  /**
-   * Formats a time interval between two timestamps.
-   *
-   * @param int $from
-   *   A UNIX timestamp, defining the from date and time.
-   * @param int $to
-   *   A UNIX timestamp, defining the to date and time.
-   * @param array $options
-   *   (optional) An associative array with additional options. The following
-   *   keys can be used:
-   *   - granularity: An integer value that signals how many different units to
-   *     display in the string. Defaults to 2.
-   *   - langcode: The language code for the language used to format the date.
-   *     Defaults to NULL, which results in the user interface language for the
-   *     page being used.
-   *   - strict: A Boolean value indicating whether or not the $from timestamp
-   *     can be after the $to timestamp. If TRUE (default) and $from is after
-   *     $to, the result string will be "0 seconds". If FALSE and $from is
-   *     after $to, the result string will be the formatted time difference.
-   *
-   * @return string
-   *   A translated string representation of the interval. This interval is
-   *   always positive.
-   *
-   * @see \Drupal\Core\Datetime\DateFormatter::formatInterval()
-   * @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffSince()
-   * @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffUntil()
-   */
-  public function formatDiff($from, $to, $options = array()) {
-
-    $options += array(
-      'granularity' => 2,
-      'langcode' => NULL,
-      'strict' => TRUE,
-    );
-
-    if ($options['strict'] && $from > $to) {
-      return $this->t('0 seconds');
-    }
-
-    $date_time_from = new \DateTime();
-    $date_time_from->setTimestamp($from);
-
-    $date_time_to = new \DateTime();
-    $date_time_to->setTimestamp($to);
-
-    $interval = $date_time_to->diff($date_time_from);
-
-    $granularity = $options['granularity'];
-    $output = '';
-
-    // We loop over the keys provided by \DateInterval explicitly. Since we
-    // don't take the "invert" property into account, the resulting output value
-    // will always be positive.
-    foreach (array('y', 'm', 'd', 'h', 'i', 's') as $value) {
-      if ($interval->$value > 0) {
-        // Switch over the keys to call formatPlural() explicitly with literal
-        // strings for all different possibilities.
-        switch ($value) {
-          case 'y':
-            $interval_output = $this->formatPlural($interval->y, '1 year', '@count years', array(), array('langcode' => $options['langcode']));
-            break;
-
-          case 'm':
-            $interval_output = $this->formatPlural($interval->m, '1 month', '@count months', array(), array('langcode' => $options['langcode']));
-            break;
-
-          case 'd':
-            // \DateInterval doesn't support weeks, so we need to calculate them
-            // ourselves.
-            $interval_output = '';
-            $days = $interval->d;
-            if ($days >= 7) {
-              $weeks = floor($days / 7);
-              $interval_output .= $this->formatPlural($weeks, '1 week', '@count weeks', array(), array('langcode' => $options['langcode']));
-              $days -= $weeks * 7;
-              $granularity--;
-            }
-            if ($granularity > 0 && $days > 0) {
-              $interval_output .= ($interval_output ? ' ' : '') . $this->formatPlural($days, '1 day', '@count days', array(), array('langcode' => $options['langcode']));
-            }
-            break;
-
-          case 'h':
-            $interval_output = $this->formatPlural($interval->h, '1 hour', '@count hours', array(), array('langcode' => $options['langcode']));
-            break;
-
-          case 'i':
-            $interval_output = $this->formatPlural($interval->i, '1 minute', '@count minutes', array(), array('langcode' => $options['langcode']));
-            break;
-
-          case 's':
-            $interval_output = $this->formatPlural($interval->s, '1 second', '@count seconds', array(), array('langcode' => $options['langcode']));
-            break;
-
-        }
-        $output .= ($output ? ' ' : '') . $interval_output;
-        $granularity--;
-      }
-
-      if ($granularity == 0) {
-        break;
-      }
-    }
-
-    if (empty($output)) {
-      $output = $this->t('0 seconds');
-    }
-
-    return $output;
-  }
-
-  /**
    * Loads the given format pattern for the given langcode.
    *
    * @param string $format
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index b8eeb4f..d21a8fa 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -311,7 +311,7 @@ public static function findSitePath(Request $request, $require_settings = TRUE)
     if (!$script_name) {
       $script_name = $request->server->get('SCRIPT_FILENAME');
     }
-    $http_host = $request->getHttpHost();
+    $http_host = $request->getHost();
 
     $sites = array();
     include DRUPAL_ROOT . '/sites/sites.php';
diff --git a/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php b/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php
index e791d8a..cc139e0 100644
--- a/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php
+++ b/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php
@@ -18,13 +18,6 @@ class ContentUninstallValidator implements ModuleUninstallValidatorInterface {
   use StringTranslationTrait;
 
   /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
    * Constructs a new ContentUninstallValidator.
    *
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
diff --git a/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php b/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php
index 068c41f..b71b0ec 100644
--- a/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php
+++ b/core/lib/Drupal/Core/Entity/Display/EntityFormDisplayInterface.php
@@ -41,7 +41,7 @@
    *   // widget is 'single-value' (provides the input for one field value,
    *   // most common case), and will therefore be repeated as many times as
    *   // needed, or 'multiple-values' (one single widget allows the input of
-   *   // several values; e.g., checkboxes, select box, etc.).
+   *   // several values, e.g checkboxes, select box...).
    *   'field_foo' => array(
    *     '#access' => TRUE if the current user has 'edit' grants for the field,
    *       FALSE if not.
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 89a8e9f..4861138 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -972,22 +972,20 @@ public function getTranslationFromContext(EntityInterface $entity, $langcode = N
       }
 
       // Retrieve language fallback candidates to perform the entity language
-      // negotiation, unless the current translation is already the desired one.
-      if ($entity->language()->getId() != $langcode) {
-        $context['data'] = $entity;
-        $context += array('operation' => 'entity_view', 'langcode' => $langcode);
-        $candidates = $this->languageManager->getFallbackCandidates($context);
+      // negotiation.
+      $context['data'] = $entity;
+      $context += array('operation' => 'entity_view', 'langcode' => $langcode);
+      $candidates = $this->languageManager->getFallbackCandidates($context);
 
-        // Ensure the default language has the proper language code.
-        $default_language = $entity->getUntranslated()->language();
-        $candidates[$default_language->getId()] = LanguageInterface::LANGCODE_DEFAULT;
+      // Ensure the default language has the proper language code.
+      $default_language = $entity->getUntranslated()->language();
+      $candidates[$default_language->getId()] = LanguageInterface::LANGCODE_DEFAULT;
 
-        // Return the most fitting entity translation.
-        foreach ($candidates as $candidate) {
-          if ($entity->hasTranslation($candidate)) {
-            $translation = $entity->getTranslation($candidate);
-            break;
-          }
+      // Return the most fitting entity translation.
+      foreach ($candidates as $candidate) {
+        if ($entity->hasTranslation($candidate)) {
+          $translation = $entity->getTranslation($candidate);
+          break;
         }
       }
     }
diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
index 46d6c46..883927c 100644
--- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
@@ -198,7 +198,13 @@ public function onException(GetResponseForExceptionEvent $event) {
    *   The format as which to treat the exception.
    */
   protected function getFormat(Request $request) {
-    $format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
+    // @todo We are trying to switch to a more robust content negotiation
+    // library in https://www.drupal.org/node/1505080 that will make
+    // $request->getRequestFormat() reliable as a better alternative
+    // to this code. We therefore use this style for now on the expectation
+    // that it will get replaced with better code later. This approach makes
+    // that change easier when we get to it.
+    $format = \Drupal::service('http_negotiation.format_negotiator')->getContentType($request);
 
     // These are all JSON errors for our purposes. Any special handling for
     // them can/should happen in earlier listeners if desired.
diff --git a/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php b/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
index 6fcacc9..a14d327 100644
--- a/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
+++ b/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
@@ -86,12 +86,11 @@ public function onException(GetResponseForExceptionEvent $event) {
     $exception = $event->getException();
 
     // Make the exception available for example when rendering a block.
-    $request = $event->getRequest();
-    $request->attributes->set('exception', $exception);
+    $event->getRequest()->attributes->set('exception', $exception);
 
     $handled_formats = $this->getHandledFormats();
 
-    $format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
+    $format = $event->getRequest()->getRequestFormat();
 
     if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
       $method = 'on' . $exception->getStatusCode();
diff --git a/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php b/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php
index c438e1d..38767e1 100644
--- a/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php
+++ b/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php
@@ -17,6 +17,21 @@
 abstract class ExecutablePluginBase extends ContextAwarePluginBase implements ExecutableInterface {
 
   /**
+   * The condition manager to proxy execute calls through.
+   *
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  protected $executableManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setExecutableManager(ExecutableManagerInterface $executableManager) {
+    $this->executableManager = $executableManager;
+    return $this;
+  }
+
+  /**
    * Gets an array of definitions of available configuration options.
    *
    * @todo: This needs to go into an interface.
diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
index 3238ce6..508e1b3 100644
--- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
+++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
@@ -8,10 +8,8 @@
 namespace Drupal\Core\Extension;
 
 use Drupal\Component\FileCache\FileCacheFactory;
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Extension\Discovery\RecursiveExtensionFilterIterator;
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Discovers available extensions in the filesystem.
@@ -164,16 +162,8 @@ public function scan($type, $include_tests = NULL) {
       $searchdirs[static::ORIGIN_PARENT_SITE] = $parent_site;
     }
 
-    // Find the site-specific directory to search. Since we are using this
-    // method to discover extensions including profiles, we might be doing this
-    // at install time. Therefore Kernel service is not always available, but is
-    // preferred.
-    if (\Drupal::hasService('kernel')) {
-      $searchdirs[static::ORIGIN_SITE] = \Drupal::service('site.path');
-    }
-    else {
-      $searchdirs[static::ORIGIN_SITE] = DrupalKernel::findSitePath(Request::createFromGlobals());
-    }
+    // Search the site-specific directory.
+    $searchdirs[static::ORIGIN_SITE] = conf_path();
 
     // Unless an explicit value has been passed, manually check whether we are
     // in a test environment, in which case test extensions must be included.
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index d99c9dd..9c93000 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -334,7 +334,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
         $reason_message[] = implode(', ', $reason);
       }
       throw new ModuleUninstallValidatorException(format_string('The following reasons prevents the modules from being uninstalled: @reasons', array(
-        '@reasons' => implode('; ', $reason_message),
+        '@reasons' => implode(', ', $reason_message),
       )));
     }
     // Set the actual module weights.
diff --git a/core/lib/Drupal/Core/Extension/ModuleUninstallValidatorInterface.php b/core/lib/Drupal/Core/Extension/ModuleUninstallValidatorInterface.php
index eeabca5..5e62b0e 100644
--- a/core/lib/Drupal/Core/Extension/ModuleUninstallValidatorInterface.php
+++ b/core/lib/Drupal/Core/Extension/ModuleUninstallValidatorInterface.php
@@ -20,10 +20,6 @@
    *
    * @return string[]
    *   An array of reasons the module can not be uninstalled, empty if it can.
-   *   Each reason should not end with any punctuation since multiple reasons
-   *   can be displayed together.
-   *
-   * @see theme_system_modules_uninstall()
    */
   public function validate($module);
 }
diff --git a/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php b/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php
deleted file mode 100644
index a285e00..0000000
--- a/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Extension\RequiredModuleUninstallValidator.
- */
-
-namespace Drupal\Core\Extension;
-
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-
-/**
- * Ensures that required modules cannot be uninstalled.
- */
-class RequiredModuleUninstallValidator implements ModuleUninstallValidatorInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * Constructs a new RequiredModuleUninstallValidator.
-   *
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   */
-  public function __construct(TranslationInterface $string_translation) {
-    $this->stringTranslation = $string_translation;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($module) {
-    $reasons = [];
-    $module_info = $this->getModuleInfoByModule($module);
-    if (!empty($module_info['required'])) {
-      $reasons[] = $this->t('The @module module is required', ['@module' => $module_info['name']]);
-    }
-    return $reasons;
-  }
-
-  /**
-   * Returns the module info for a specific module.
-   *
-   * @param string $module
-   *   The name of the module.
-   *
-   * @return array
-   *   The module info, or NULL if that module does not exist.
-   */
-  protected function getModuleInfoByModule($module) {
-    $modules = system_rebuild_module_data();
-    return isset($modules[$module]->info) ? $modules[$module]->info : [];
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Field/FieldModuleUninstallValidator.php b/core/lib/Drupal/Core/Field/FieldModuleUninstallValidator.php
index b2e474d..b54579c 100644
--- a/core/lib/Drupal/Core/Field/FieldModuleUninstallValidator.php
+++ b/core/lib/Drupal/Core/Field/FieldModuleUninstallValidator.php
@@ -53,7 +53,7 @@ public function validate($module_name) {
             if ($storage_definition->getProvider() == $module_name) {
               $storage = $this->entityManager->getStorage($entity_type_id);
               if ($storage instanceof FieldableEntityStorageInterface && $storage->countFieldData($storage_definition, TRUE)) {
-                $reasons[] = $this->t('There is data for the field @field-name on entity type @entity_type', array(
+                $reasons[] = $this->t('There is data for the field @field-name on entity type @entity_type.', array(
                   '@field-name' => $storage_definition->getName(),
                   '@entity_type' => $entity_type->getLabel(),
                 ));
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php
index 30dae80..04f96fa 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php
@@ -87,7 +87,7 @@ public function viewElements(FieldItemListInterface $items) {
 
     foreach ($items as $delta => $item) {
       if ($item->value) {
-        $updated = $this->t('@time ago', array('@time' => $this->dateFormatter->formatTimeDiffSince($item->value)));
+        $updated = $this->t('@time ago', array('@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $item->value)));
       }
       else {
         $updated = $this->t('never');
diff --git a/core/lib/Drupal/Core/Field/WidgetInterface.php b/core/lib/Drupal/Core/Field/WidgetInterface.php
index 39f7cc4..d110cec 100644
--- a/core/lib/Drupal/Core/Field/WidgetInterface.php
+++ b/core/lib/Drupal/Core/Field/WidgetInterface.php
@@ -66,18 +66,18 @@ public function settingsSummary();
    * hook_field_widget_WIDGET_TYPE_form_alter().
    *
    * The FAPI element callbacks (such as #process, #element_validate,
-   * #value_callback, etc.) used by the widget do not have access to the
-   * original $field_definition passed to the widget's constructor. Therefore,
-   * if any information is needed from that definition by those callbacks, the
-   * widget implementing this method, or a
-   * hook_field_widget[_WIDGET_TYPE]_form_alter() implementation, must extract
-   * the needed properties from the field definition and set them as ad-hoc
-   * $element['#custom'] properties, for later use by its element callbacks.
+   * #value_callback...) used by the widget do not have access to the original
+   * $field_definition passed to the widget's constructor. Therefore, if any
+   * information is needed from that definition by those callbacks, the widget
+   * implementing this method, or a hook_field_widget[_WIDGET_TYPE]_form_alter()
+   * implementation, must extract the needed properties from the field
+   * definition and set them as ad-hoc $element['#custom'] properties, for later
+   * use by its element callbacks.
    *
    * @param \Drupal\Core\Field\FieldItemListInterface $items
    *   Array of default values for this field.
    * @param int $delta
-   *   The order of this item in the array of sub-elements (0, 1, 2, etc.).
+   *   The order of this item in the array of sub-elements (0, 1, 2, etc).
    * @param array $element
    *   A form element array containing basic properties for the widget:
    *   - #field_parents: The 'parents' space for the field in the form. Most
diff --git a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php
index d17f065..0f2f3a7 100644
--- a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php
+++ b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php
@@ -21,13 +21,6 @@
 class SiteConfigureForm extends ConfigFormBase {
 
   /**
-   * The site path.
-   *
-   * @var string
-   */
-  protected $sitePath;
-
-  /**
    * The user storage.
    *
    * @var \Drupal\user\UserStorageInterface
@@ -67,8 +60,6 @@ class SiteConfigureForm extends ConfigFormBase {
    *
    * @param string $root
    *   The app root.
-   * @param string $site_path
-   *   The site path.
    * @param \Drupal\user\UserStorageInterface $user_storage
    *   The user storage.
    * @param \Drupal\Core\State\StateInterface $state
@@ -78,9 +69,8 @@ class SiteConfigureForm extends ConfigFormBase {
    * @param \Drupal\Core\Locale\CountryManagerInterface $country_manager
    *   The country manager.
    */
-  public function __construct($root, $site_path, UserStorageInterface $user_storage, StateInterface $state, ModuleInstallerInterface $module_installer, CountryManagerInterface $country_manager) {
+  public function __construct($root, UserStorageInterface $user_storage, StateInterface $state, ModuleInstallerInterface $module_installer, CountryManagerInterface $country_manager) {
     $this->root = $root;
-    $this->sitePath = $site_path;
     $this->userStorage = $user_storage;
     $this->state = $state;
     $this->moduleInstaller = $module_installer;
@@ -93,7 +83,6 @@ public function __construct($root, $site_path, UserStorageInterface $user_storag
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('app.root'),
-      $container->get('site.path'),
       $container->get('entity.manager')->getStorage('user'),
       $container->get('state'),
       $container->get('module_installer'),
@@ -126,7 +115,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['#title'] = $this->t('Configure site');
 
     // Warn about settings.php permissions risk
-    $settings_dir = $this->sitePath;
+    $settings_dir = conf_path();
     $settings_file = $settings_dir . '/settings.php';
     // Check that $_POST is empty so we only show this message when the form is
     // first displayed, not on the next page after it is submitted. (We do not
diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
index 4d0f9fe..8cf65c9 100644
--- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
+++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
@@ -11,7 +11,6 @@
 use Drupal\Core\Database\Database;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides a form to configure and rewrite settings.php.
@@ -19,32 +18,6 @@
 class SiteSettingsForm extends FormBase {
 
   /**
-   * The site path.
-   *
-   * @var string
-   */
-  protected $sitePath;
-
-  /**
-   * Constructs a new SiteSettingsForm.
-   *
-   * @param string $site_path
-   *   The site path.
-   */
-  public function __construct($site_path) {
-    $this->sitePath = $site_path;
-}
-
-  /**
-    * {@inheritdoc}
-    */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('site.path')
-    );
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function getFormId() {
@@ -55,7 +28,8 @@ public function getFormId() {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state) {
-    $settings_file = './' . $this->sitePath . '/settings.php';
+    $conf_path = './' . conf_path(FALSE);
+    $settings_file = $conf_path . '/settings.php';
 
     $form['#title'] = $this->t('Database configuration');
 
diff --git a/core/lib/Drupal/Core/Menu/LocalTaskManager.php b/core/lib/Drupal/Core/Menu/LocalTaskManager.php
index 86136d0..2ef5de1 100644
--- a/core/lib/Drupal/Core/Menu/LocalTaskManager.php
+++ b/core/lib/Drupal/Core/Menu/LocalTaskManager.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Cache\NullBackend;
 use Drupal\Core\Controller\ControllerResolverInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
@@ -18,6 +19,7 @@
 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\Core\Plugin\Discovery\YamlDiscovery;
 use Drupal\Core\Plugin\Factory\ContainerFactory;
+use Drupal\Core\Routing\RouteBuilderInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -89,6 +91,13 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
   protected $routeProvider;
 
   /**
+   * The route builder.
+   *
+   * @var \Drupal\Core\Routing\RouteBuilderInterface
+   */
+  protected $routeBuilder;
+
+  /**
    * The access manager.
    *
    * @var \Drupal\Core\Access\AccessManagerInterface
@@ -113,6 +122,8 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
    *   The current route match.
    * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
    *   The route provider to load routes by name.
+   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
+   *   The route builder.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
@@ -124,7 +135,7 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The current user.
    */
-  public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
+  public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, RouteBuilderInterface $route_builder, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
     $this->discovery = new YamlDiscovery('links.task', $module_handler->getModuleDirectories());
     $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
     $this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\LocalTaskInterface');
@@ -132,6 +143,7 @@ public function __construct(ControllerResolverInterface $controller_resolver, Re
     $this->requestStack = $request_stack;
     $this->routeMatch = $route_match;
     $this->routeProvider = $route_provider;
+    $this->routeBuilder = $route_builder;
     $this->accessManager = $access_manager;
     $this->account = $account;
     $this->moduleHandler = $module_handler;
diff --git a/core/lib/Drupal/Core/Render/Element/Checkbox.php b/core/lib/Drupal/Core/Render/Element/Checkbox.php
index 5f39bcc..6574685 100644
--- a/core/lib/Drupal/Core/Render/Element/Checkbox.php
+++ b/core/lib/Drupal/Core/Render/Element/Checkbox.php
@@ -13,17 +13,6 @@
 /**
  * Provides a form element for a single checkbox.
  *
- * Properties:
- * - #return_value: The value to return when the checkbox is checked.
- *
- * Usage example:
- * @code
- * $form['copy'] = array(
- *   '#type' => 'checkbox',
- *   '#title' => t('Send me a copy'),
- * );
- * @endcode
- *
  * @see \Drupal\Core\Render\Element\Checkboxes
  *
  * @FormElement("checkbox")
diff --git a/core/lib/Drupal/Core/Render/Element/Checkboxes.php b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
index d931460..1891ceb 100644
--- a/core/lib/Drupal/Core/Render/Element/Checkboxes.php
+++ b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
@@ -12,21 +12,9 @@
 /**
  * Provides a form element for a set of checkboxes.
  *
- * Properties:
- * - #options: An associative array whose keys are the values returned for each
- *   checkbox, and whose values are the labels next to each checkbox. The
- *   #options array cannot have a 0 key, as it would not be possible to discern
- *   checked and unchecked states.
- *
- * Usage example:
- * @code
- * $form['high_school']['tests_taken'] = array(
- *   '#type' => 'checkboxes',
- *   '#options' => array('SAT' => t('SAT'), 'ACT' => t('ACT'))),
- *   '#title' => t('What standardized tests did you take?'),
- *   ...
- * );
- * @endcode
+ * #options is an associative array, where the key is the #return_value of the
+ * checkbox and the value is displayed. The #options array cannot have a 0 key,
+ * as it would not be possible to discern checked and unchecked states.
  *
  * @see \Drupal\Core\Render\Element\Radios
  * @see \Drupal\Core\Render\Element\Checkbox
diff --git a/core/lib/Drupal/Core/Render/Element/File.php b/core/lib/Drupal/Core/Render/Element/File.php
index c8b3c7f..5f72c8d 100644
--- a/core/lib/Drupal/Core/Render/Element/File.php
+++ b/core/lib/Drupal/Core/Render/Element/File.php
@@ -65,7 +65,7 @@ public static function processFile(&$element, FormStateInterface $form_state, &$
   public static function preRenderFile($element) {
     $element['#attributes']['type'] = 'file';
     Element::setAttributes($element, array('id', 'name', 'size'));
-    static::setAttributes($element, array('js-form-file', 'form-file'));
+    static::setAttributes($element, array('form-file'));
 
     return $element;
   }
diff --git a/core/lib/Drupal/Core/Render/Element/HtmlTag.php b/core/lib/Drupal/Core/Render/Element/HtmlTag.php
index 5dc3afe..9b2ab57 100644
--- a/core/lib/Drupal/Core/Render/Element/HtmlTag.php
+++ b/core/lib/Drupal/Core/Render/Element/HtmlTag.php
@@ -69,9 +69,6 @@ public function getInfo() {
    *     wrapper prefix.
    *   - #value_suffix: (optional) A string to append to #value, e.g. a CDATA
    *     wrapper suffix.
-   *   - #noscript: (optional) If TRUE, the markup (including any prefix or
-   *     suffix) will be wrapped in a <noscript> element. (Note that passing
-   *     any non-empty value here will add the <noscript> tag.)
    *
    * @return array
    */
diff --git a/core/lib/Drupal/Core/Render/Element/LanguageSelect.php b/core/lib/Drupal/Core/Render/Element/LanguageSelect.php
index 3b01ba1..433e508 100644
--- a/core/lib/Drupal/Core/Render/Element/LanguageSelect.php
+++ b/core/lib/Drupal/Core/Render/Element/LanguageSelect.php
@@ -12,8 +12,6 @@
 /**
  * Provides a form element for selecting a language.
  *
- * @see \Drupal\Core\Render\Element\Select
- *
  * @FormElement("language_select")
  */
 class LanguageSelect extends FormElement {
diff --git a/core/lib/Drupal/Core/Render/Element/Radio.php b/core/lib/Drupal/Core/Render/Element/Radio.php
index 2e8b28c..3b5f144 100644
--- a/core/lib/Drupal/Core/Render/Element/Radio.php
+++ b/core/lib/Drupal/Core/Render/Element/Radio.php
@@ -12,11 +12,7 @@
 /**
  * Provides a form element for a single radio button.
  *
- * This is an internal element that is primarily used to render the radios form
- * element. Refer to \Drupal\Core\Render\Element\Radios for more documentation.
- *
  * @see \Drupal\Core\Render\Element\Radios
- * @see \Drupal\Core\Render\Element\Checkbox
  *
  * @FormElement("radio")
  */
diff --git a/core/lib/Drupal/Core/Render/Element/Radios.php b/core/lib/Drupal/Core/Render/Element/Radios.php
index 619c0b9..4b27b5a 100644
--- a/core/lib/Drupal/Core/Render/Element/Radios.php
+++ b/core/lib/Drupal/Core/Render/Element/Radios.php
@@ -13,23 +13,8 @@
 /**
  * Provides a form element for a set of radio buttons.
  *
- * Properties:
- * - #options: An associative array, where the keys are the returned values for
- *   each radio button, and the values are the labels next to each radio button.
- *
- * Usage example:
- * @code
- * $form['settings']['active'] = array(
- *   '#type' => 'radios',
- *   '#title' => t('Poll status'),
- *   '#default_value' => 1
- *   '#options' => array(0 => t('Closed'), 1 => t('Active'),
- * );
- * @endcode
- *
  * @see \Drupal\Core\Render\Element\Checkboxes
  * @see \Drupal\Core\Render\Element\Radio
- * @see \Drupal\Core\Render\Element\Select
  *
  * @FormElement("radios")
  */
diff --git a/core/lib/Drupal/Core/Render/Element/Select.php b/core/lib/Drupal/Core/Render/Element/Select.php
index b028c42..9f30c68 100644
--- a/core/lib/Drupal/Core/Render/Element/Select.php
+++ b/core/lib/Drupal/Core/Render/Element/Select.php
@@ -13,12 +13,8 @@
 /**
  * Provides a form element for a drop-down menu or scrolling selection box.
  *
- * Properties:
- * - #options: An associative array, where the keys are the retured values for
- *   each option, and the values are the options to be shown in the drop-down
- *   list.
- * - #empty_option: The label that will be displayed to denote no selection.
- * - #empty_value: The value of the option that is used to denote no selection.
+ * See #empty_option and #empty_value for an explanation of various settings for
+ * a select element, including behavior if #required is TRUE or FALSE.
  *
  * @FormElement("select")
  */
diff --git a/core/lib/Drupal/Core/Render/Element/Tableselect.php b/core/lib/Drupal/Core/Render/Element/Tableselect.php
index 1c117f1..a3ec290 100644
--- a/core/lib/Drupal/Core/Render/Element/Tableselect.php
+++ b/core/lib/Drupal/Core/Render/Element/Tableselect.php
@@ -14,14 +14,9 @@
 /**
  * Provides a form element for a table with radios or checkboxes in left column.
  *
- * Properties:
- * - #headers: Table headers used in the table.
- * - #options: An associative array where each key is the value returned when
- *   a user selects the radio button or checkbox, and each value is the row of
- *   table data.
- *
- * Usage example:
- * See https://www.drupal.org/node/945102 for an example and full explanation.
+ * Build the table headings and columns with the #headers property, and the rows
+ * with the #options property. See https://www.drupal.org/node/94510 for a full
+ * explanation.
  *
  * @see \Drupal\Core\Render\Element\Table
  *
diff --git a/core/lib/Drupal/Core/Render/Element/Weight.php b/core/lib/Drupal/Core/Render/Element/Weight.php
index dacac46..ffcda6b 100644
--- a/core/lib/Drupal/Core/Render/Element/Weight.php
+++ b/core/lib/Drupal/Core/Render/Element/Weight.php
@@ -12,22 +12,8 @@
 /**
  * Provides a form element for input of a weight.
  *
- * Weights are integers used to indicate ordering, with larger numbers later in
- * the order.
- *
- * Properties:
- * - #delta: The range of possible weight values used. A delta of 10 would
- *   indicate possible weight values between -10 and 10.
- *
- * Usage example:
- * @code
- * $form['weight'] = array(
- *   '#type' => 'weight',
- *   '#title' => t('Weight'),
- *   '#default_value' => $edit['weight'],
- *   '#delta' => 10,
- * );
- * @endcode
+ * Weights are integers used to indicate ordering, with larger numbers later
+ * in the order.
  *
  * @FormElement("weight")
  */
diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
index d61bb24..5f84857 100644
--- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
+++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
@@ -220,8 +220,8 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte
 
     // $page is now fully built. Find all non-empty page regions, and add a
     // theme wrapper function that allows them to be consistently themed.
-    $regions = \Drupal::theme()->getActiveTheme()->getRegions();
-    foreach ($regions as $region) {
+    $regions = system_region_list(\Drupal::theme()->getActiveTheme()->getName());
+    foreach (array_keys($regions) as $region) {
       if (!empty($page[$region])) {
         $page[$region]['#theme_wrappers'][] = 'region';
         $page[$region]['#region'] = $region;
diff --git a/core/lib/Drupal/Core/Render/RenderCacheInterface.php b/core/lib/Drupal/Core/Render/RenderCacheInterface.php
index c0e580b..0e24f1b 100644
--- a/core/lib/Drupal/Core/Render/RenderCacheInterface.php
+++ b/core/lib/Drupal/Core/Render/RenderCacheInterface.php
@@ -42,7 +42,7 @@ public function getCacheableRenderArray(array $elements);
    * @param array $elements
    *   A renderable array.
    *
-   * @return array|false
+   * @return array
    *   A renderable array, with the original element and all its children pre-
    *   rendered, or FALSE if no cached copy of the element is available.
    *
diff --git a/core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php b/core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php
similarity index 93%
rename from core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php
rename to core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php
index 0f52fba..7794800 100644
--- a/core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php
+++ b/core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php
@@ -2,13 +2,12 @@
 
 /**
  * @file
- * Contains \Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher.
+ * Contains Drupal\Core\Routing\AcceptHeaderMatcher.
  */
 
-namespace Drupal\accept_header_routing_test\Routing;
+namespace Drupal\Core\Routing;
 
 use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Core\Routing\RouteFilterInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
 use Symfony\Component\Routing\Route;
diff --git a/core/lib/Drupal/Core/Routing/LazyRouteFilter.php b/core/lib/Drupal/Core/Routing/LazyRouteFilter.php
index 5cb85a7..288e09b 100644
--- a/core/lib/Drupal/Core/Routing/LazyRouteFilter.php
+++ b/core/lib/Drupal/Core/Routing/LazyRouteFilter.php
@@ -10,7 +10,6 @@
 use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface as BaseRouteFilterInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\RouteCollection;
 
@@ -96,9 +95,7 @@ public function filter(RouteCollection $collection, Request $request) {
 
     if (isset($filter_ids)) {
       foreach ($filter_ids as $filter_id) {
-        if ($filter = $this->container->get($filter_id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
-          $collection = $filter->filter($collection, $request);
-        }
+        $collection = $this->container->get($filter_id)->filter($collection, $request);
       }
     }
     return $collection;
diff --git a/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php b/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php
deleted file mode 100644
index 4d5189a..0000000
--- a/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Routing\RequestFormatRouteFilter.
- */
-
-namespace Drupal\Core\Routing;
-
-use Drupal\Component\Utility\SafeMarkup;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * Provides a route filter, which filters by the request format.
- */
-class RequestFormatRouteFilter implements RouteFilterInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function applies(Route $route) {
-    return $route->hasRequirement('_format');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function filter(RouteCollection $collection, Request $request) {
-    $format = $request->getRequestFormat('html');
-    /** @var \Symfony\Component\Routing\Route $route */
-    foreach ($collection as $name => $route) {
-      // If the route has no _format specification, we move it to the end. If it
-      // does, then no match means the route is removed entirely.
-      if ($supported_formats = array_filter(explode('|', $route->getRequirement('_format')))) {
-        if (!in_array($format, $supported_formats)) {
-          $collection->remove($name);
-        }
-      }
-      else {
-        $collection->add($name, $route);
-      }
-    }
-
-    if (count($collection)) {
-      return $collection;
-    }
-
-    // We do not throw a
-    // \Symfony\Component\Routing\Exception\ResourceNotFoundException here
-    // because we don't want to return a 404 status code, but rather a 406.
-    throw new NotAcceptableHttpException(SafeMarkup::format('No route found for the specified format @format.', ['@format' => $format]));
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index c757d1e..18f55ff 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -117,6 +117,7 @@ public static function initialize($app_root, $site_path, &$class_loader) {
     $config = array();
     $databases = array();
 
+    // Make conf_path() available as local variable in settings.php.
     if (is_readable($app_root . '/' . $site_path . '/settings.php')) {
       require $app_root . '/' . $site_path . '/settings.php';
     }
diff --git a/core/lib/Drupal/Core/SitePathFactory.php b/core/lib/Drupal/Core/SitePathFactory.php
deleted file mode 100644
index 3adade2..0000000
--- a/core/lib/Drupal/Core/SitePathFactory.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\SitePathFactory.
- */
-
-namespace Drupal\Core;
-
-/**
- * Gets the site path from the kernel.
- */
-class SitePathFactory {
-
-  /**
-   * The Drupal kernel.
-   *
-   * @var \Drupal\Core\DrupalKernelInterface
-   */
-  protected $drupalKernel;
-
-  /**
-   * Constructs an SitePathFactory instance.
-   *
-   * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel
-   *   The Drupal kernel.
-   */
-  public function __construct(DrupalKernelInterface $drupal_kernel) {
-    $this->drupalKernel = $drupal_kernel;
-  }
-
-  /**
-   * Gets the site path.
-   *
-   * @return string
-   *   The site path.
-   */
-  public function get() {
-    return $this->drupalKernel->getSitePath();
-  }
-
-}
-
diff --git a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php b/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
index 3b0bf76..295857d 100644
--- a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
+++ b/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
@@ -38,7 +38,7 @@ class NegotiationMiddleware implements HttpKernelInterface {
    *
    * @var array
    */
-  protected $formats = [];
+  protected $formats;
 
   /**
    * Constructs a new NegotiationMiddleware.
@@ -57,12 +57,10 @@ public function __construct(HttpKernelInterface $app, ContentNegotiation $negoti
    * {@inheritdoc}
    */
   public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) {
-    // Register available mime types.
     foreach ($this->formats as $format => $mime_type) {
       $request->setFormat($format, $mime_type);
     }
 
-    // Determine the request format using the negotiator.
     $request->setRequestFormat($this->negotiator->getContentType($request));
     return $this->app->handle($request, $type, $catch);
   }
diff --git a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
index ea7d1e6..e2b78ec 100644
--- a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
+++ b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
@@ -8,9 +8,7 @@
 namespace Drupal\Core\StreamWrapper;
 
 use Drupal\Component\Utility\UrlHelper;
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Defines a Drupal public (public://) stream wrapper class.
@@ -59,39 +57,12 @@ public function getExternalUrl() {
   /**
    * Returns the base path for public://.
    *
-   * If we have a setting for the public:// scheme's path, we use that.
-   * Otherwise we build a reasonable default based on the site.path service if
-   * it's available, or a default behavior based on the request.
-   *
-   * The site path is injectable from the site.path service:
-   * @code
-   * $base_path = PublicStream::basePath(\Drupal::service('site.path'));
-   * @endcode
-   *
-   * @param \SplString $site_path
-   *   (optional) The site.path service parameter, which is typically the path
-   *   to sites/ in a Drupal installation. This allows you to inject the site
-   *   path using services from the caller. If omitted, this method will use the
-   *   global service container or the kernel's default behavior to determine
-   *   the site path.
-   *
    * @return string
    *   The base path for public:// typically sites/default/files.
    */
-  public static function basePath(\SplString $site_path = NULL) {
-    if ($site_path === NULL) {
-      // Find the site path. Kernel service is not always available at this
-      // point, but is preferred, when available.
-      if (\Drupal::hasService('kernel')) {
-        $site_path = \Drupal::service('site.path');
-      }
-      else {
-        // If there is no kernel available yet, we call the static
-        // findSitePath().
-        $site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
-      }
-    }
-    return Settings::get('file_public_path', $site_path . '/files');
+  public static function basePath() {
+    $base_path = Settings::get('file_public_path', conf_path() . '/files');
+    return $base_path;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Theme/ActiveTheme.php b/core/lib/Drupal/Core/Theme/ActiveTheme.php
index c35afad..aace6f9 100644
--- a/core/lib/Drupal/Core/Theme/ActiveTheme.php
+++ b/core/lib/Drupal/Core/Theme/ActiveTheme.php
@@ -74,13 +74,6 @@ class ActiveTheme {
   protected $libraries;
 
   /**
-   * The regions provided by the theme.
-   *
-   * @var array
-   */
-  protected $regions;
-
-  /**
    * Constructs an ActiveTheme object.
    *
    * @param array $values
@@ -95,7 +88,6 @@ public function __construct(array $values) {
       'libraries' => [],
       'extension' => 'html.twig',
       'base_themes' => [],
-      'regions' => [],
     ];
 
     $this->name = $values['name'];
@@ -106,7 +98,6 @@ public function __construct(array $values) {
     $this->libraries = $values['libraries'];
     $this->extension = $values['extension'];
     $this->baseThemes = $values['base_themes'];
-    $this->regions = $values['regions'];
   }
 
   /**
@@ -186,16 +177,4 @@ public function getBaseThemes() {
     return $this->baseThemes;
   }
 
-  /**
-   * The regions used by the theme.
-   *
-   * @return string[]
-   *   The list of region machine names supported by the theme.
-   *
-   * @see system_region_list()
-   */
-  public function getRegions() {
-    return array_keys($this->regions);
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Theme/ThemeInitialization.php b/core/lib/Drupal/Core/Theme/ThemeInitialization.php
index 3f055c1..a77271e 100644
--- a/core/lib/Drupal/Core/Theme/ThemeInitialization.php
+++ b/core/lib/Drupal/Core/Theme/ThemeInitialization.php
@@ -214,9 +214,6 @@ public function getActiveTheme(Extension $theme, array $base_themes = []) {
     }
 
     $values['base_themes'] = $base_active_themes;
-    if (!empty($theme->info['regions'])) {
-      $values['regions'] = $theme->info['regions'];
-    }
 
     return new ActiveTheme($values);
   }
diff --git a/core/misc/active-link.js b/core/misc/active-link.js
index 97c9966..3a2f818 100644
--- a/core/misc/active-link.js
+++ b/core/misc/active-link.js
@@ -18,8 +18,6 @@
    *
    * Does not discriminate based on element type, so allows you to set the
    * is-active class on any element: a, li…
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.activeLinks = {
     attach: function (context) {
@@ -30,8 +28,7 @@
       var originalSelectors = ['[data-drupal-link-system-path="' + path.currentPath + '"]'];
       var selectors;
 
-      // If this is the front page, we have to check for the <front> path as
-      // well.
+      // If this is the front page, we have to check for the <front> path as well.
       if (path.isFront) {
         originalSelectors.push('[data-drupal-link-system-path="<front>"]');
       }
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 3cb1c8d..db8dd26 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -1,24 +1,9 @@
-/**
- * @file
- * Provides Ajax page updating via jQuery $.ajax.
- *
- * Ajax is a method of making a request via JavaScript while viewing an HTML
- * page. The request returns an array of commands encoded in JSON, which is
- * then executed to make any changes that are necessary to the page.
- *
- * Drupal uses this file to enhance form elements with `#ajax['url']` and
- * `#ajax['wrapper']` properties. If set, this file will automatically be
- * included to provide Ajax capabilities.
- */
-
 (function ($, window, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Attaches the Ajax behavior to each Ajax form element.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.AJAX = {
     attach: function (context, settings) {
@@ -73,8 +58,7 @@ function loadAjaxBehavior(base) {
         element_settings.setClick = true;
         // Form buttons use the 'click' event rather than mousedown.
         element_settings.event = 'click';
-        // Clicked form buttons look better with the throbber than the progress
-        // bar.
+        // Clicked form buttons look better with the throbber than the progress bar.
         element_settings.progress = {'type': 'throbber'};
         element_settings.base = $(this).attr('id');
         element_settings.element = this;
@@ -86,15 +70,6 @@ function loadAjaxBehavior(base) {
 
   /**
    * Extends Error to provide handling for Errors in Ajax.
-   *
-   * @constructor
-   *
-   * @augments Error
-   *
-   * @param {XMLHttpRequest} xmlhttp
-   *   XMLHttpRequest object used for the failed request.
-   * @param {string} uri
-   *   The URI where the error occurred.
    */
   Drupal.AjaxError = function (xmlhttp, uri) {
 
@@ -112,15 +87,14 @@ function loadAjaxBehavior(base) {
     statusCode += "\n" + Drupal.t("Debugging information follows.");
     pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri});
     statusText = '';
-    // In some cases, when statusCode === 0, xmlhttp.statusText may not be
-    // defined. Unfortunately, testing for it with typeof, etc, doesn't seem to
-    // catch that and the test causes an exception. So we need to catch the
-    // exception here.
+    // In some cases, when statusCode === 0, xmlhttp.statusText may not be defined.
+    // Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
+    // and the test causes an exception. So we need to catch the exception here.
     try {
       statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
     }
     catch (e) {
-      // Empty.
+      // empty
     }
 
     responseText = '';
@@ -140,18 +114,7 @@ function loadAjaxBehavior(base) {
     // We don't need readyState except for status == 0.
     readyStateText = xmlhttp.status === 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
 
-    /**
-     * Formatted and translated error message.
-     *
-     * @type {string}
-     */
     this.message = statusCode + pathText + statusText + responseText + readyStateText;
-
-    /**
-     * Used by some browsers to display a more accurate stack trace.
-     *
-     * @type {string}
-     */
     this.name = 'AjaxError';
   };
 
@@ -162,8 +125,8 @@ function loadAjaxBehavior(base) {
    * Provides Ajax page updating via jQuery $.ajax.
    *
    * This function is designed to improve developer experience by wrapping the
-   * initialization of {@link Drupal.Ajax} objects and storing all created
-   * objects in the {@link Drupal.ajax.instances} array.
+   * initialization of Drupal.Ajax objects and storing all created object in the
+   * Drupal.ajax.instances array.
    *
    * @example
    * Drupal.behaviors.myCustomAJAXStuff = {
@@ -195,18 +158,17 @@ function loadAjaxBehavior(base) {
    *   }
    * };
    *
+   * @see Drupal.AjaxCommands
+   *
    * @param {object} settings
-   *   The settings object passed to {@link Drupal.Ajax} constructor.
+   *   The settings object passed to Drupal.Ajax constructor.
    * @param {string} [settings.base]
-   *   Base is passed to {@link Drupal.Ajax} constructor as the 'base'
-   *   parameter.
+   *   Base is passed to Drupal.Ajax constructor as the 'base' parameter.
    * @param {HTMLElement} [settings.element]
-   *   Element parameter of {@link Drupal.Ajax} constructor, element on which
+   *   Element parameter of Drupal.Ajax constructor, element on which
    *   event listeners will be bound.
    *
    * @return {Drupal.Ajax}
-   *
-   * @see Drupal.AjaxCommands
    */
   Drupal.ajax = function (settings) {
     if (arguments.length !== 1) {
@@ -233,7 +195,7 @@ function loadAjaxBehavior(base) {
   /**
    * Contains all created Ajax objects.
    *
-   * @type {Array.<Drupal.Ajax>}
+   * @type {Array}
    */
   Drupal.ajax.instances = [];
 
@@ -243,16 +205,16 @@ function loadAjaxBehavior(base) {
    * The Ajax request returns an array of commands encoded in JSON, which is
    * then executed to make any changes that are necessary to the page.
    *
-   * Drupal uses this file to enhance form elements with `#ajax['url']` and
-   * `#ajax['wrapper']` properties. If set, this file will automatically be
+   * Drupal uses this file to enhance form elements with #ajax['url'] and
+   * #ajax['wrapper'] properties. If set, this file will automatically be
    * included to provide Ajax capabilities.
    *
    * @constructor
    *
    * @param {string} [base]
-   *   Base parameter of {@link Drupal.Ajax} constructor
+   *   Base parameter of Drupal.Ajax constructor
    * @param {HTMLElement} [element]
-   *   Element parameter of {@link Drupal.Ajax} constructor, element on which
+   *   Element parameter of Drupal.Ajax constructor, element on which
    *   event listeners will be bound.
    * @param {object} element_settings
    * @param {string} element_settings.url
@@ -282,9 +244,6 @@ function loadAjaxBehavior(base) {
 
     $.extend(this, defaults, element_settings);
 
-    /**
-     * @type {Drupal.AjaxCommands}
-     */
     this.commands = new Drupal.AjaxCommands();
     this.instanceIndex = false;
 
@@ -293,30 +252,15 @@ function loadAjaxBehavior(base) {
     //   - Include the '#' for ID-based selectors.
     //   - Support non-ID-based selectors.
     if (this.wrapper) {
-
-      /**
-       * @type {string}
-       */
       this.wrapper = '#' + this.wrapper;
     }
 
-    /**
-     * @type {HTMLElement}
-     */
     this.element = element;
-
-    /**
-     * @type {object}
-     */
     this.element_settings = element_settings;
 
     // If there isn't a form, jQuery.ajax() will be used instead, allowing us to
     // bind Ajax to links as well.
     if (this.element && this.element.form) {
-
-      /**
-       * @type {jQuery}
-       */
       this.$form = $(this.element.form);
     }
 
@@ -329,16 +273,15 @@ function loadAjaxBehavior(base) {
       else if (this.element && element.form) {
         this.url = this.$form.attr('action');
 
-        // @todo If there's a file input on this form, then jQuery will submit
-        //   the AJAX response with a hidden Iframe rather than the XHR object.
-        //   If the response to the submission is an HTTP redirect, then the
-        //   Iframe will follow it, but the server won't content negotiate it
-        //   correctly, because there won't be an ajax_iframe_upload POST
-        //   variable. Until we figure out a work around to this problem, we
-        //   prevent AJAX-enabling elements that submit to the same URL as the
-        //   form when there's a file input. For example, this means the Delete
-        //   button on the edit form of an Article node doesn't open its
-        //   confirmation form in a dialog.
+        // @todo If there's a file input on this form, then jQuery will submit the
+        //   Ajax response with a hidden Iframe rather than the XHR object. If the
+        //   response to the submission is an HTTP redirect, then the Iframe will
+        //   follow it, but the server won't content negotiate it correctly,
+        //   because there won't be an ajax_iframe_upload POST variable. Until we
+        //   figure out a work around to this problem, we prevent Ajax-enabling
+        //   elements that submit to the same URL as the form when there's a file
+        //   input. For example, this means the Delete button on the edit form of
+        //   an Article node doesn't open its confirmation form in a dialog.
         if (this.$form.find(':file').length) {
           return;
         }
@@ -357,26 +300,6 @@ else if (this.element && element.form) {
     // Set the options for the ajaxSubmit function.
     // The 'this' variable will not persist inside of the options object.
     var ajax = this;
-
-    /**
-     * Options for the ajaxSubmit function.
-     *
-     * @name Drupal.Ajax#options
-     *
-     * @type {object}
-     *
-     * @prop {string} url
-     * @prop {object} data
-     * @prop {function} beforeSerialize
-     * @prop {function} beforeSubmit
-     * @prop {function} beforeSend
-     * @prop {function} success
-     * @prop {function} complete
-     * @prop {string} dataType
-     * @prop {object} accepts
-     * @prop {string} accepts.json
-     * @prop {string} type
-     */
     ajax.options = {
       url: ajax.url,
       data: ajax.submit,
@@ -450,8 +373,6 @@ else if (this.element && element.form) {
    *
    * The wrapper format determines how the HTML is wrapped, for example in a
    * modal dialog.
-   *
-   * @const {string}
    */
   Drupal.ajax.WRAPPER_FORMAT = '_wrapper_format';
 
@@ -488,9 +409,6 @@ else if (this.element && element.form) {
    * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13
    * and 32. RETURN is often used to submit a form when in a textfield, and
    * SPACE is often used to activate an element without submitting.
-   *
-   * @param {HTMLElement} element
-   * @param {jQuery.Event} event
    */
   Drupal.Ajax.prototype.keypressResponse = function (element, event) {
     // Create a synonym for this to reduce code confusion.
@@ -499,8 +417,8 @@ else if (this.element && element.form) {
     // Detect enter key and space bar and allow the standard response for them,
     // except for form elements of type 'text', 'tel', 'number' and 'textarea',
     // where the spacebar activation causes inappropriate activation if
-    // #ajax['keypress'] is TRUE. On a text-type widget a space should always
-    // be a space.
+    // #ajax['keypress'] is TRUE. On a text-type widget a space should always be a
+    // space.
     if (event.which === 13 || (event.which === 32 && element.type !== 'text' &&
       element.type !== 'textarea' && element.type !== 'tel' && element.type !== 'number')) {
       event.preventDefault();
@@ -516,9 +434,6 @@ else if (this.element && element.form) {
    * perform the actual Ajax call. It is bound to the event using
    * bind() in the constructor, and it uses the options specified on the
    * Ajax object.
-   *
-   * @param {HTMLElement} element
-   * @param {jQuery.Event} event
    */
   Drupal.Ajax.prototype.eventResponse = function (element, event) {
     event.preventDefault();
@@ -564,10 +479,6 @@ else if (this.element && element.form) {
    *
    * Runs before the beforeSend() handler (see below), and unlike that one, runs
    * before field data is collected.
-   *
-   * @param {HTMLElement} element
-   * @param {object} options
-   * @param {object} options.data
    */
   Drupal.Ajax.prototype.beforeSerialize = function (element, options) {
     // Allow detaching behaviors to update field values before collecting them.
@@ -604,10 +515,6 @@ else if (this.element && element.form) {
 
   /**
    * Modify form values prior to form submission.
-   *
-   * @param {object} form_values
-   * @param {HTMLElement} element
-   * @param {object} options
    */
   Drupal.Ajax.prototype.beforeSubmit = function (form_values, element, options) {
     // This function is left empty to make it simple to override for modules
@@ -616,35 +523,30 @@ else if (this.element && element.form) {
 
   /**
    * Prepare the Ajax request before it is sent.
-   *
-   * @param {XMLHttpRequest} xmlhttprequest
-   * @param {object} options
-   * @param {object} options.extraData
    */
   Drupal.Ajax.prototype.beforeSend = function (xmlhttprequest, options) {
-    // For forms without file inputs, the jQuery Form plugin serializes the
-    // form values, and then calls jQuery's $.ajax() function, which invokes
-    // this handler. In this circumstance, options.extraData is never used. For
-    // forms with file inputs, the jQuery Form plugin uses the browser's normal
-    // form submission mechanism, but captures the response in a hidden IFRAME.
-    // In this circumstance, it calls this handler first, and then appends
-    // hidden fields to the form to submit the values in options.extraData.
-    // There is no simple way to know which submission mechanism will be used,
-    // so we add to extraData regardless, and allow it to be ignored in the
-    // former case.
+    // For forms without file inputs, the jQuery Form plugin serializes the form
+    // values, and then calls jQuery's $.ajax() function, which invokes this
+    // handler. In this circumstance, options.extraData is never used. For forms
+    // with file inputs, the jQuery Form plugin uses the browser's normal form
+    // submission mechanism, but captures the response in a hidden IFRAME. In this
+    // circumstance, it calls this handler first, and then appends hidden fields
+    // to the form to submit the values in options.extraData. There is no simple
+    // way to know which submission mechanism will be used, so we add to extraData
+    // regardless, and allow it to be ignored in the former case.
     if (this.$form) {
       options.extraData = options.extraData || {};
 
       // Let the server know when the IFRAME submission mechanism is used. The
-      // server can use this information to wrap the JSON response in a
-      // TEXTAREA, as per http://jquery.malsup.com/form/#file-upload.
+      // server can use this information to wrap the JSON response in a TEXTAREA,
+      // as per http://jquery.malsup.com/form/#file-upload.
       options.extraData.ajax_iframe_upload = '1';
 
       // The triggering element is about to be disabled (see below), but if it
-      // contains a value (e.g., a checkbox, textfield, select, etc.), ensure
-      // that value is included in the submission. As per above, submissions
-      // that use $.ajax() are already serialized prior to the element being
-      // disabled, so this is only needed for IFRAME submissions.
+      // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that
+      // value is included in the submission. As per above, submissions that use
+      // $.ajax() are already serialized prior to the element being disabled, so
+      // this is only needed for IFRAME submissions.
       var v = $.fieldValue(this.element);
       if (v !== null) {
         options.extraData[this.element.name] = v;
@@ -661,7 +563,7 @@ else if (this.element && element.form) {
       return;
     }
 
-    // Insert progress indicator.
+    // Insert progress indicator
     var progressIndicatorMethod = 'setProgressIndicator' + this.progress.type.slice(0, 1).toUpperCase() + this.progress.type.slice(1).toLowerCase();
     if (progressIndicatorMethod in this && typeof this[progressIndicatorMethod] === 'function') {
       this[progressIndicatorMethod].call(this);
@@ -705,9 +607,6 @@ else if (this.element && element.form) {
 
   /**
    * Handler for the form redirection completion.
-   *
-   * @param {Array.<Drupal.AjaxCommands~commandDefinition>} response
-   * @param {number} status
    */
   Drupal.Ajax.prototype.success = function (response, status) {
     // Remove the progress element.
@@ -740,13 +639,7 @@ else if (this.element && element.form) {
   };
 
   /**
-   * Build an effect object to apply an effect when adding new HTML.
-   *
-   * @param {object} response
-   * @param {string} [response.effect]
-   * @param {string|number} [response.speed]
-   *
-   * @return {object}
+   * Build an effect object which tells us how to apply the effect when adding new HTML.
    */
   Drupal.Ajax.prototype.getEffect = function (response) {
     var type = response.effect || this.effect;
@@ -774,9 +667,6 @@ else if (type === 'fade') {
 
   /**
    * Handler for the form redirection error.
-   *
-   * @param {object} response
-   * @param {string} uri
    */
   Drupal.Ajax.prototype.error = function (response, uri) {
     // Remove the progress element.
@@ -799,46 +689,12 @@ else if (type === 'fade') {
   };
 
   /**
-   * @typedef {object} Drupal.AjaxCommands~commandDefinition
-   *
-   * @prop {string} command
-   * @prop {string} [method]
-   * @prop {string} [selector]
-   * @prop {string} [data]
-   * @prop {object} [settings]
-   * @prop {bool} [asterisk]
-   * @prop {string} [text]
-   * @prop {string} [title]
-   * @prop {string} [url]
-   * @prop {object} [argument]
-   * @prop {string} [name]
-   * @prop {string} [value]
-   * @prop {string} [old]
-   * @prop {string} [new]
-   * @prop {bool} [merge]
-   * @prop {Array} [args]
-   *
-   * @see Drupal.AjaxCommands
-   */
-
-  /**
-   * Provide a series of commands that the client will perform.
-   *
-   * @constructor
+   * Provide a series of commands that the server can request the client perform.
    */
   Drupal.AjaxCommands = function () {};
   Drupal.AjaxCommands.prototype = {
-
     /**
      * Command to insert new content into the DOM.
-     *
-     * @param {Drupal.Ajax} ajax
-     * @param {object} response
-     * @param {string} response.data
-     * @param {string} [response.method]
-     * @param {string} [response.selector]
-     * @param {object} [response.settings]
-     * @param {number} [status]
      */
     insert: function (ajax, response, status) {
       // Get information from the response. If it is not there, default to
@@ -856,17 +712,16 @@ else if (type === 'fade') {
       var new_content_wrapped = $('<div></div>').html(response.data);
       var new_content = new_content_wrapped.contents();
 
-      // For legacy reasons, the effects processing code assumes that
-      // new_content consists of a single top-level element. Also, it has not
-      // been sufficiently tested whether attachBehaviors() can be successfully
-      // called with a context object that includes top-level text nodes.
-      // However, to give developers full control of the HTML appearing in the
-      // page, and to enable Ajax content to be inserted in places where DIV
-      // elements are not allowed (e.g., within TABLE, TR, and SPAN parents),
-      // we check if the new content satisfies the requirement of a single
-      // top-level element, and only use the container DIV created above when
-      // it doesn't. For more information, please see
-      // https://www.drupal.org/node/736066.
+      // For legacy reasons, the effects processing code assumes that new_content
+      // consists of a single top-level element. Also, it has not been
+      // sufficiently tested whether attachBehaviors() can be successfully called
+      // with a context object that includes top-level text nodes. However, to
+      // give developers full control of the HTML appearing in the page, and to
+      // enable Ajax content to be inserted in places where DIV elements are not
+      // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new
+      // content satisfies the requirement of a single top-level element, and
+      // only use the container DIV created above when it doesn't. For more
+      // information, please see https://www.drupal.org/node/736066.
       if (new_content.length !== 1 || new_content.get(0).nodeType !== 1) {
         new_content = new_content_wrapped;
       }
@@ -901,9 +756,9 @@ else if (effect.showEffect !== 'show') {
         new_content[effect.showEffect](effect.showSpeed);
       }
 
-      // Attach all JavaScript behaviors to the new content, if it was
-      // successfully added to the page, this if statement allows
-      // `#ajax['wrapper']` to be optional.
+      // Attach all JavaScript behaviors to the new content, if it was successfully
+      // added to the page, this if statement allows #ajax['wrapper'] to be
+      // optional.
       if (new_content.parents('html').length > 0) {
         // Apply any settings from the returned JSON if available.
         settings = response.settings || ajax.settings || drupalSettings;
@@ -913,12 +768,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to remove a chunk from the page.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.selector
-     * @param {object} [response.settings]
-     * @param {number} [status]
      */
     remove: function (ajax, response, status) {
       var settings = response.settings || ajax.settings || drupalSettings;
@@ -930,12 +779,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to mark a chunk changed.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.selector
-     * @param {bool} [response.asterisk]
-     * @param {number} [status]
      */
     changed: function (ajax, response, status) {
       if (!$(response.selector).hasClass('ajax-changed')) {
@@ -948,12 +791,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to provide an alert.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.text
-     * @param {string} response.title
-     * @param {number} [status]
      */
     alert: function (ajax, response, status) {
       window.alert(response.text, response.title);
@@ -961,11 +798,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to set the window.location, redirecting the browser.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.url
-     * @param {number} [status]
      */
     redirect: function (ajax, response, status) {
       window.location = response.url;
@@ -973,24 +805,13 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to provide the jQuery css() function.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {object} response.argument
-     * @param {number} [status]
      */
     css: function (ajax, response, status) {
       $(response.selector).css(response.argument);
     },
 
     /**
-     * Command to set the settings used for other commands in this response.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {bool} response.merge
-     * @param {object} response.settings
-     * @param {number} [status]
+     * Command to set the settings that will be used for other commands in this response.
      */
     settings: function (ajax, response, status) {
       if (response.merge) {
@@ -1003,13 +824,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to attach data using jQuery's data API.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.name
-     * @param {string} response.selector
-     * @param {string|object} response.value
-     * @param {number} [status]
      */
     data: function (ajax, response, status) {
       $(response.selector).data(response.name, response.value);
@@ -1017,13 +831,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to apply a jQuery method.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {Array} response.args
-     * @param {string} response.method
-     * @param {string} response.selector
-     * @param {number} [status]
      */
     invoke: function (ajax, response, status) {
       var $element = $(response.selector);
@@ -1032,11 +839,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to restripe a table.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.selector
-     * @param {number} [status]
      */
     restripe: function (ajax, response, status) {
       // :even and :odd are reversed because jQuery counts from 0 and
@@ -1050,12 +852,6 @@ else if (effect.showEffect !== 'show') {
 
     /**
      * Command to update a form's build ID.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.old
-     * @param {string} response.new
-     * @param {number} [status]
      */
     update_build_id: function (ajax, response, status) {
       $('input[name="form_build_id"][value="' + response.old + '"]').val(response.new);
@@ -1067,11 +863,6 @@ else if (effect.showEffect !== 'show') {
      * Uses the proprietary addImport method if available as browsers which
      * support that method ignore @import statements in dynamically added
      * stylesheets.
-     *
-     * @param {Drupal.Ajax} [ajax]
-     * @param {object} response
-     * @param {string} response.data
-     * @param {number} [status]
      */
     add_css: function (ajax, response, status) {
       // Add the styles in the normal way.
diff --git a/core/misc/announce.js b/core/misc/announce.js
index 0a0abeb..9aafbbc 100644
--- a/core/misc/announce.js
+++ b/core/misc/announce.js
@@ -1,12 +1,9 @@
 /**
- * @file
  * Adds an HTML element and method to trigger audio UAs to read system messages.
  *
- * Use {@link Drupal.announce} to indicate to screen reader users that an
- * element on the page has changed state. For instance, if clicking a link
- * loads 10 more items into a list, one might announce the change like this.
- *
- * @example
+ * Use Drupal.announce() to indicate to screen reader users that an element on
+ * the page has changed state. For instance, if clicking a link loads 10 more
+ * items into a list, one might announce the change like this.
  * $('#search-list')
  *   .on('itemInsert', function (event, data) {
  *     // Insert the new items.
@@ -17,7 +14,6 @@
  *     ));
  *   });
  */
-
 (function (Drupal, debounce) {
 
   "use strict";
@@ -26,9 +22,8 @@
   var announcements = [];
 
   /**
-   * Builds a div element with the aria-live attribute and add it to the DOM.
-   *
-   * @type {Drupal~behavior}
+   * Builds a div element with the aria-live attribute and attaches it
+   * to the DOM.
    */
   Drupal.behaviors.drupalAnnounce = {
     attach: function (context) {
@@ -85,19 +80,17 @@ function announce() {
    *
    * The aria-live region will only read the text that currently populates its
    * text node. Replacing text quickly in rapid calls to announce results in
-   * only the text from the most recent call to {@link Drupal.announce} being
-   * read. By wrapping the call to announce in a debounce function, we allow for
-   * time for multiple calls to {@link Drupal.announce} to queue up their
-   * messages. These messages are then joined and append to the aria-live region
-   * as one text node.
+   * only the text from the most recent call to Drupal.announce() being read.
+   * By wrapping the call to announce in a debounce function, we allow for
+   * time for multiple calls to Drupal.announce() to queue up their messages.
+   * These messages are then joined and append to the aria-live region as one
+   * text node.
    *
-   * @param {string} text
+   * @param String text
    *   A string to be read by the UA.
-   * @param {string} [priority='polite']
+   * @param String priority
    *   A string to indicate the priority of the message. Can be either
-   *   'polite' or 'assertive'.
-   *
-   * @return {function}
+   *   'polite' or 'assertive'. Polite is the default.
    *
    * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops
    */
diff --git a/core/misc/autocomplete.js b/core/misc/autocomplete.js
index f826281..92bb867 100644
--- a/core/misc/autocomplete.js
+++ b/core/misc/autocomplete.js
@@ -1,8 +1,3 @@
-/**
- * @file
- * Autocomplete based on jQuery UI.
- */
-
 (function ($, Drupal) {
 
   "use strict";
@@ -12,9 +7,7 @@
   /**
    * Helper splitting terms from the autocomplete value.
    *
-   * @function Drupal.autocomplete.splitValues
-   *
-   * @param {string} value
+   * @param {String} value
    *
    * @return {Array}
    */
@@ -50,11 +43,9 @@ else if (character === ',' && !quote) {
   /**
    * Returns the last value of an multi-value textfield.
    *
-   * @function Drupal.autocomplete.extractLastTerm
+   * @param {String} terms
    *
-   * @param {string} terms
-   *
-   * @return {string}
+   * @return {String}
    */
   function extractLastTerm(terms) {
     return autocomplete.splitValues(terms).pop();
@@ -63,11 +54,9 @@ function extractLastTerm(terms) {
   /**
    * The search handler is called before a search is performed.
    *
-   * @function Drupal.autocomplete.options.search
+   * @param {Object} event
    *
-   * @param {object} event
-   *
-   * @return {bool}
+   * @return {Boolean}
    */
   function searchHandler(event) {
     var options = autocomplete.options;
@@ -81,10 +70,10 @@ function searchHandler(event) {
   }
 
   /**
-   * JQuery UI autocomplete source callback.
+   * jQuery UI autocomplete source callback.
    *
-   * @param {object} request
-   * @param {function} response
+   * @param {Object} request
+   * @param {Function} response
    */
   function sourceData(request, response) {
     var elementId = this.element.attr('id');
@@ -97,7 +86,7 @@ function sourceData(request, response) {
      * Filter through the suggestions removing all terms already tagged and
      * display the available terms to the user.
      *
-     * @param {object} suggestions
+     * @param {Object} suggestions
      */
     function showSuggestions(suggestions) {
       var tagged = autocomplete.splitValues(request.term);
@@ -114,7 +103,7 @@ function showSuggestions(suggestions) {
     /**
      * Transforms the data object into an array and update autocomplete results.
      *
-     * @param {object} data
+     * @param {Object} data
      */
     function sourceCallbackHandler(data) {
       autocomplete.cache[elementId][term] = data;
@@ -139,7 +128,7 @@ function sourceCallbackHandler(data) {
   /**
    * Handles an autocompletefocus event.
    *
-   * @return {bool}
+   * @return {Boolean}
    */
   function focusHandler() {
     return false;
@@ -148,10 +137,10 @@ function focusHandler() {
   /**
    * Handles an autocompleteselect event.
    *
-   * @param {jQuery.Event} event
-   * @param {object} ui
+   * @param {Object} event
+   * @param {Object} ui
    *
-   * @return {bool}
+   * @return {Boolean}
    */
   function selectHandler(event, ui) {
     var terms = autocomplete.splitValues(event.target.value);
@@ -172,10 +161,10 @@ function selectHandler(event, ui) {
   /**
    * Override jQuery UI _renderItem function to output HTML by default.
    *
-   * @param {object} ul
-   * @param {object} item
+   * @param {Object} ul
+   * @param {Object} item
    *
-   * @return {object}
+   * @return {Object}
    */
   function renderItem(ul, item) {
     return $("<li>")
@@ -185,8 +174,6 @@ function renderItem(ul, item) {
 
   /**
    * Attaches the autocomplete behavior to all required fields.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.autocomplete = {
     attach: function (context) {
@@ -215,8 +202,6 @@ function renderItem(ul, item) {
 
   /**
    * Autocomplete object implementation.
-   *
-   * @namespace Drupal.autocomplete
    */
   autocomplete = {
     cache: {},
@@ -224,12 +209,6 @@ function renderItem(ul, item) {
     splitValues: autocompleteSplitValues,
     extractLastTerm: extractLastTerm,
     // jQuery UI autocomplete options.
-
-    /**
-     * JQuery UI option object.
-     *
-     * @name Drupal.autocomplete.options
-     */
     options: {
       source: sourceData,
       focus: focusHandler,
diff --git a/core/misc/batch.js b/core/misc/batch.js
index 43242ea..ee6cf68 100644
--- a/core/misc/batch.js
+++ b/core/misc/batch.js
@@ -1,16 +1,12 @@
 /**
- * @file
  * Drupal's batch API.
  */
-
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Attaches the batch behavior to progress bars.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.batch = {
     attach: function (context, settings) {
diff --git a/core/misc/collapse.js b/core/misc/collapse.js
index 1ad89f7..2d44e3f 100644
--- a/core/misc/collapse.js
+++ b/core/misc/collapse.js
@@ -1,18 +1,9 @@
-/**
- * @file
- * Polyfill for HTML5 details elements.
- */
-
 (function ($, Modernizr, Drupal) {
 
   "use strict";
 
   /**
-   * The collapsible details object represents a single details element.
-   *
-   * @constructor Drupal.CollapsibleDetails
-   *
-   * @param {HTMLElement} node
+   * The collapsible details object represents a single collapsible details element.
    */
   function CollapsibleDetails(node) {
     this.$node = $(node);
@@ -29,24 +20,22 @@ function CollapsibleDetails(node) {
     this.setupLegend();
   }
 
-  $.extend(CollapsibleDetails, /** @lends Drupal.CollapsibleDetails */{
-
+  /**
+   * Extend CollapsibleDetails function.
+   */
+  $.extend(CollapsibleDetails, {
     /**
      * Holds references to instantiated CollapsibleDetails objects.
-     *
-     * @type {Array.<Drupal.CollapsibleDetails>}
      */
     instances: []
   });
 
-  $.extend(CollapsibleDetails.prototype, /** @lends Drupal.CollapsibleDetails# */{
-
+  /**
+   * Extend CollapsibleDetails prototype.
+   */
+  $.extend(CollapsibleDetails.prototype, {
     /**
      * Initialize and setup summary events and markup.
-     *
-     * @fires event:summaryUpdated
-     *
-     * @listens event:summaryUpdated
      */
     setupSummary: function () {
       this.$summary = $('<span class="summary"></span>');
@@ -54,7 +43,6 @@ function CollapsibleDetails(node) {
         .on('summaryUpdated', $.proxy(this.onSummaryUpdated, this))
         .trigger('summaryUpdated');
     },
-
     /**
      * Initialize and setup legend markup.
      */
@@ -77,25 +65,20 @@ function CollapsibleDetails(node) {
         .append(this.$summary)
         .on('click', $.proxy(this.onLegendClick, this));
     },
-
     /**
-     * Handle legend clicks.
-     *
-     * @param {jQuery.Event} e
+     * Handle legend clicks
      */
     onLegendClick: function (e) {
       this.toggle();
       e.preventDefault();
     },
-
     /**
-     * Update summary.
+     * Update summary
      */
     onSummaryUpdated: function () {
       var text = $.trim(this.$node.drupalGetSummary());
       this.$summary.html(text ? ' (' + text + ')' : '');
     },
-
     /**
      * Toggle the visibility of a details element using smooth animations.
      */
@@ -116,11 +99,6 @@ function CollapsibleDetails(node) {
     }
   });
 
-  /**
-   * Polyfill HTML5 details element.
-   *
-   * @type {Drupal~behavior}
-   */
   Drupal.behaviors.collapse = {
     attach: function (context) {
       if (Modernizr.details) {
diff --git a/core/misc/debounce.js b/core/misc/debounce.js
index 0239ce6..45a5b87 100644
--- a/core/misc/debounce.js
+++ b/core/misc/debounce.js
@@ -1,11 +1,8 @@
 /**
- * @file
- * Adapted from underscore.js with the addition Drupal namespace.
- */
-
-/**
  * Limits the invocations of a function in a given time frame.
  *
+ * Adapted from underscore.js with the addition Drupal namespace.
+ *
  * The debounce function wrapper should be used sparingly. One clear use case
  * is limiting the invocation of a callback attached to the window resize event.
  *
@@ -14,17 +11,13 @@
  * function can be written in such a way that it is only invoked under specific
  * conditions.
  *
- * @param {function} func
+ * @param {Function} callback
  *   The function to be invoked.
- * @param {number} wait
+ *
+ * @param {Number} wait
  *   The time period within which the callback function should only be
  *   invoked once. For example if the wait period is 250ms, then the callback
  *   will only be called at most 4 times per second.
- * @param {bool} immediate
- *   Whether we wait at the beginning or end to execute the function.
- *
- * @return {function}
- *   The debounced function.
  */
 Drupal.debounce = function (func, wait, immediate) {
 
diff --git a/core/misc/details-aria.js b/core/misc/details-aria.js
index 4de6bdf..b400b4f 100644
--- a/core/misc/details-aria.js
+++ b/core/misc/details-aria.js
@@ -7,11 +7,6 @@
 
   "use strict";
 
-  /**
-   * Handles `aria-expanded` and `aria-pressed` attributes on details elements.
-   *
-   * @type {Drupal~behavior}
-   */
   Drupal.behaviors.detailsAria = {
     attach: function () {
       $('body').once('detailsAria').on('click.detailsAria', 'summary', function (event) {
diff --git a/core/misc/dialog/dialog.ajax.js b/core/misc/dialog/dialog.ajax.js
index 47f6852..e786d5a 100644
--- a/core/misc/dialog/dialog.ajax.js
+++ b/core/misc/dialog/dialog.ajax.js
@@ -7,11 +7,6 @@
 
   "use strict";
 
-  /**
-   * Initialize dialogs for Ajax purposes.
-   *
-   * @type {Drupal~behavior}
-   */
   Drupal.behaviors.dialog = {
     attach: function (context, settings) {
       var $context = $(context);
@@ -51,10 +46,9 @@
     /**
      * Scan a dialog for any primary buttons and move them to the button area.
      *
-     * @param {jQuery} $dialog
+     * @param $dialog
      *   An jQuery object containing the element that is the dialog target.
-     *
-     * @return {Array}
+     * @return
      *   An array of buttons that need to be added to the button area.
      */
     prepareDialogButtons: function ($dialog) {
@@ -76,7 +70,7 @@
           'text': $originalButton.html() || $originalButton.attr('value'),
           'class': $originalButton.attr('class'),
           'click': function (e) {
-            $originalButton.trigger('mousedown').trigger('mouseup').trigger('click');
+            $originalButton.trigger('mousedown').trigger('click').trigger('mouseup');
             e.preventDefault();
           }
         });
@@ -87,12 +81,6 @@
 
   /**
    * Command to open a dialog.
-   *
-   * @param {Drupal.Ajax} ajax
-   * @param {object} response
-   * @param {number} [status]
-   *
-   * @return {bool|undefined}
    */
   Drupal.AjaxCommands.prototype.openDialog = function (ajax, response, status) {
     if (!response.selector) {
@@ -119,7 +107,7 @@
       response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
     }
 
-    // Bind dialogButtonsChange.
+    // Bind dialogButtonsChange
     $dialog.on('dialogButtonsChange', function () {
       var buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
       $dialog.dialog('option', 'buttons', buttons);
@@ -143,12 +131,6 @@
    * Command to close a dialog.
    *
    * If no selector is given, it defaults to trying to close the modal.
-   *
-   * @param {Drupal.Ajax} [ajax]
-   * @param {object} response
-   * @param {string} response.selector
-   * @param {bool} response.persist
-   * @param {number} [status]
    */
   Drupal.AjaxCommands.prototype.closeDialog = function (ajax, response, status) {
     var $dialog = $(response.selector);
@@ -159,21 +141,14 @@
       }
     }
 
-    // Unbind dialogButtonsChange.
+    // Unbind dialogButtonsChange
     $dialog.off('dialogButtonsChange');
   };
 
   /**
    * Command to set a dialog property.
    *
-   * JQuery UI specific way of setting dialog options.
-   *
-   * @param {Drupal.Ajax} [ajax]
-   * @param {object} response
-   * @param {string} response.selector
-   * @param {string} response.optionsName
-   * @param {string} response.optionValue
-   * @param {number} [status]
+   * jQuery UI specific way of setting dialog options.
    */
   Drupal.AjaxCommands.prototype.setDialogOption = function (ajax, response, status) {
     var $dialog = $(response.selector);
@@ -184,11 +159,6 @@
 
   /**
    * Binds a listener on dialog creation to handle the cancel link.
-   *
-   * @param {jQuery.Event} e
-   * @param {Drupal.dialog~dialogDefinition} dialog
-   * @param {jQuery} $element
-   * @param {object} settings
    */
   $(window).on('dialog:aftercreate', function (e, dialog, $element, settings) {
     $element.on('click.dialog', '.dialog-cancel', function (e) {
@@ -200,10 +170,6 @@
 
   /**
    * Removes all 'dialog' listeners.
-   *
-   * @param {jQuery.Event} e
-   * @param {Drupal.dialog~dialogDefinition} dialog
-   * @param {jQuery} $element
    */
   $(window).on('dialog:beforeclose', function (e, dialog, $element) {
     $element.off('.dialog');
diff --git a/core/misc/dialog/dialog.jquery-ui.js b/core/misc/dialog/dialog.jquery-ui.js
index 27fff75..cd6e863 100644
--- a/core/misc/dialog/dialog.jquery-ui.js
+++ b/core/misc/dialog/dialog.jquery-ui.js
@@ -2,7 +2,6 @@
  * @file
  * Adds default classes to buttons for styling purposes.
  */
-
 (function ($) {
 
   "use strict";
diff --git a/core/misc/dialog/dialog.js b/core/misc/dialog/dialog.js
index cb7fb92..f63b405 100644
--- a/core/misc/dialog/dialog.js
+++ b/core/misc/dialog/dialog.js
@@ -1,64 +1,30 @@
 /**
  * @file
- * Dialog API inspired by HTML5 dialog element.
  *
- * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
+ * Dialog API inspired by HTML5 dialog element:
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
  */
-
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
-  /**
-   * Default dialog options.
-   *
-   * @type {object}
-   *
-   * @prop {bool} [autoOpen=true]
-   * @prop {string} [dialogClass='']
-   * @prop {string} [buttonClass='button']
-   * @prop {string} [buttonPrimaryClass='button--primary']
-   * @prop {function} close
-   */
   drupalSettings.dialog = {
     autoOpen: true,
     dialogClass: '',
     // Drupal-specific extensions: see dialog.jquery-ui.js.
     buttonClass: 'button',
     buttonPrimaryClass: 'button--primary',
-    // When using this API directly (when generating dialogs on the client
-    // side), you may want to override this method and do
-    // `jQuery(event.target).remove()` as well, to remove the dialog on
-    // closing.
+    // When using this API directly (when generating dialogs on the client side),
+    // you may want to override this method and do
+    // @code
+    // jQuery(event.target).remove()
+    // @endcode
+    // as well, to remove the dialog on closing.
     close: function (event) {
       Drupal.detachBehaviors(event.target, null, 'unload');
     }
   };
 
-  /**
-   * @typedef {object} Drupal.dialog~dialogDefinition
-   *
-   * @prop {boolean} open
-   *   Is the dialog open or not.
-   * @prop {*} returnValue
-   *   Return value of the dialog.
-   * @prop {function} show
-   *   Method to display the dialog on the page.
-   * @prop {function} showModal
-   *   Method to display the dialog as a modal on the page.
-   * @prop {function} close
-   *   Method to hide the dialog from the page.
-   */
-
-  /**
-   * Polyfill HTML5 dialog element with jQueryUI.
-   *
-   * @param {HTMLElement} element
-   * @param {object} options
-   *   jQuery UI options to be passed to the dialog.
-   *
-   * @return {Drupal.dialog~dialogDefinition}
-   */
   Drupal.dialog = function (element, options) {
 
     function openDialog(settings) {
diff --git a/core/misc/dialog/dialog.position.js b/core/misc/dialog/dialog.position.js
index a356477..3e08574 100644
--- a/core/misc/dialog/dialog.position.js
+++ b/core/misc/dialog/dialog.position.js
@@ -1,14 +1,3 @@
-/**
- * @file
- * Positioning extensions for dialogs.
- */
-
-/**
- * Triggers when content inside a dialog changes.
- *
- * @event dialogContentResize
- */
-
 (function ($, Drupal, drupalSettings, debounce, displace) {
 
   "use strict";
@@ -22,13 +11,7 @@
    * This is used as a window resize and scroll callback to reposition the
    * jQuery UI dialog. Although not a built-in jQuery UI option, this can
    * be disabled by setting autoResize: false in the options array when creating
-   * a new {@link Drupal.dialog}.
-   *
-   * @function Drupal.dialog~resetSize
-   *
-   * @param {jQuery.Event} event
-   *
-   * @fires event:dialogContentResize
+   * a new Drupal.dialog().
    */
   function resetSize(event) {
     var positionOptions = ['width', 'height', 'minWidth', 'minHeight', 'maxHeight', 'maxWidth', 'position'];
@@ -63,12 +46,6 @@ function resetSize(event) {
 
   /**
    * Position the dialog's center at the center of displace.offsets boundaries.
-   *
-   * @function Drupal.dialog~resetPosition
-   *
-   * @param {object} options
-   *
-   * @return {object}
    */
   function resetPosition(options) {
     var offsets = displace.offsets;
diff --git a/core/misc/displace.js b/core/misc/displace.js
index 5e21ca1..a52a826 100644
--- a/core/misc/displace.js
+++ b/core/misc/displace.js
@@ -1,38 +1,13 @@
 /**
- * @file
  * Manages elements that can offset the size of the viewport.
  *
  * Measures and reports viewport offset dimensions from elements like the
  * toolbar that can potentially displace the positioning of other elements.
  */
-
-/**
- * @typedef {object} Drupal~displaceOffset
- *
- * @prop {number} top
- * @prop {number} left
- * @prop {number} right
- * @prop {number} bottom
- */
-
-/**
- * Triggers when layout of the page changes.
- *
- * This is used to position fixed element on the page during page resize and
- * Toolbar toggling.
- *
- * @event drupalViewportOffsetChange
- */
-
 (function ($, Drupal, debounce) {
 
   "use strict";
 
-  /**
-   * @name Drupal.displace.offsets
-   *
-   * @type {Drupal~displaceOffset}
-   */
   var offsets = {
     top: 0,
     right: 0,
@@ -42,8 +17,6 @@
 
   /**
    * Registers a resize handler on the window.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.drupalDisplace = {
     attach: function () {
@@ -60,20 +33,14 @@
   /**
    * Informs listeners of the current offset dimensions.
    *
-   * @function Drupal.displace
-   *
-   * @prop {Drupal~displaceOffset} offsets
-   *
-   * @param {bool} [broadcast]
-   *   When true or undefined, causes the recalculated offsets values to be
+   * @param {boolean} broadcast
+   *   (optional) When true or undefined, causes the recalculated offsets values to be
    *   broadcast to listeners.
    *
-   * @return {Drupal~displaceOffset}
+   * @return {object}
    *   An object whose keys are the for sides an element -- top, right, bottom
    *   and left. The value of each key is the viewport displacement distance for
    *   that edge.
-   *
-   * @fires event:drupalViewportOffsetChange
    */
   function displace(broadcast) {
     offsets = Drupal.displace.offsets = calculateOffsets();
@@ -86,7 +53,7 @@ function displace(broadcast) {
   /**
    * Determines the viewport offsets.
    *
-   * @return {Drupal~displaceOffset}
+   * @return {object}
    *   An object whose keys are the for sides an element -- top, right, bottom
    *   and left. The value of each key is the viewport displacement distance for
    *   that edge.
@@ -108,8 +75,6 @@ function calculateOffsets() {
    * numeric value, that value will be used. If no value is provided, one will
    * be calculated using the element's dimensions and placement.
    *
-   * @function Drupal.displace.calculateOffset
-   *
    * @param {string} edge
    *   The name of the edge to calculate. Can be 'top', 'right',
    *   'bottom' or 'left'.
@@ -146,7 +111,7 @@ function calculateOffset(edge) {
   /**
    * Calculates displacement for element based on its dimensions and placement.
    *
-   * @param {HTMLElement} el
+   * @param {jQuery} $el
    *   The jQuery element whose dimensions and placement will be measured.
    *
    * @param {string} edge
@@ -198,23 +163,15 @@ function getRawOffset(el, edge) {
 
   /**
    * Assign the displace function to a property of the Drupal global object.
-   *
-   * @ignore
    */
   Drupal.displace = displace;
   $.extend(Drupal.displace, {
-
     /**
-     * Expose offsets to other scripts to avoid having to recalculate offsets.
-     *
-     * @ignore
+     * Expose offsets to other scripts to avoid having to recalculate offsets
      */
     offsets: offsets,
-
     /**
      * Expose method to compute a single edge offsets.
-     *
-     * @ignore
      */
     calculateOffset: calculateOffset
   });
diff --git a/core/misc/dropbutton/dropbutton.js b/core/misc/dropbutton/dropbutton.js
index 787cc56..eebf354 100644
--- a/core/misc/dropbutton/dropbutton.js
+++ b/core/misc/dropbutton/dropbutton.js
@@ -1,16 +1,9 @@
-/**
- * @file
- * Dropbutton feature.
- */
-
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Process elements with the .dropbutton class on page load.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.dropButton = {
     attach: function (context, settings) {
@@ -32,10 +25,6 @@
 
   /**
    * Delegated callback for opening and closing dropbutton secondary actions.
-   *
-   * @function Drupal.DropButton~dropbuttonClickHandler
-   *
-   * @param {jQuery.Event} e
    */
   function dropbuttonClickHandler(e) {
     e.preventDefault();
@@ -48,36 +37,21 @@ function dropbuttonClickHandler(e) {
    * All secondary actions beyond the first in the list are presented in a
    * dropdown list accessible through a toggle arrow associated with the button.
    *
-   * @constructor Drupal.DropButton
+   * @param {jQuery} $dropbutton
+   *   A jQuery element.
    *
-   * @param {HTMLElement} dropbutton
-   *   A DOM element.
-   * @param {object} settings
+   * @param {Object} settings
    *   A list of options including:
-   * @param {string} settings.title
-   *   The text inside the toggle link element. This text is hidden
-   *   from visual UAs.
+   *    - {String} title: The text inside the toggle link element. This text is
+   *      hidden from visual UAs.
    */
   function DropButton(dropbutton, settings) {
     // Merge defaults with settings.
     var options = $.extend({'title': Drupal.t('List additional actions')}, settings);
     var $dropbutton = $(dropbutton);
-
-    /**
-     * @type {jQuery}
-     */
     this.$dropbutton = $dropbutton;
-
-    /**
-     * @type {jQuery}
-     */
     this.$list = $dropbutton.find('.dropbutton');
-
-    /**
-     * Find actions and mark them.
-     *
-     * @type {jQuery}
-     */
+    // Find actions and mark them.
     this.$actions = this.$list.find('li').addClass('dropbutton-action');
 
     // Add the special dropdown only if there are hidden actions.
@@ -93,31 +67,18 @@ function DropButton(dropbutton, settings) {
       this.$dropbutton
         .addClass('dropbutton-multiple')
         .on({
-
           /**
            * Adds a timeout to close the dropdown on mouseleave.
-           *
-           * @ignore
            */
           'mouseleave.dropbutton': $.proxy(this.hoverOut, this),
-
           /**
            * Clears timeout when mouseout of the dropdown.
-           *
-           * @ignore
            */
           'mouseenter.dropbutton': $.proxy(this.hoverIn, this),
-
           /**
            * Similar to mouseleave/mouseenter, but for keyboard navigation.
-           *
-           * @ignore
            */
           'focusout.dropbutton': $.proxy(this.focusOut, this),
-
-          /**
-           * @ignore
-           */
           'focusin.dropbutton': $.proxy(this.focusIn, this)
         });
     }
@@ -129,11 +90,11 @@ function DropButton(dropbutton, settings) {
   /**
    * Extend the DropButton constructor.
    */
-  $.extend(DropButton, /** @lends Drupal.DropButton */{
+  $.extend(DropButton, {
     /**
      * Store all processed DropButtons.
      *
-     * @type {Array.<Drupal.DropButton>}
+     * @type {Array}
      */
     dropbuttons: []
   });
@@ -141,13 +102,12 @@ function DropButton(dropbutton, settings) {
   /**
    * Extend the DropButton prototype.
    */
-  $.extend(DropButton.prototype, /** @lends Drupal.DropButton# */{
-
+  $.extend(DropButton.prototype, {
     /**
      * Toggle the dropbutton open and closed.
      *
-     * @param {bool} [show]
-     *   Force the dropbutton to open by passing true or to close by
+     * @param {Boolean} show
+     *   (optional) Force the dropbutton to open by passing true or to close by
      *   passing false.
      */
     toggle: function (show) {
@@ -156,9 +116,6 @@ function DropButton(dropbutton, settings) {
       this.$dropbutton.toggleClass('open', show);
     },
 
-    /**
-     * @method
-     */
     hoverIn: function () {
       // Clear any previous timer we were using.
       if (this.timerID) {
@@ -166,53 +123,37 @@ function DropButton(dropbutton, settings) {
       }
     },
 
-    /**
-     * @method
-     */
     hoverOut: function () {
       // Wait half a second before closing.
       this.timerID = window.setTimeout($.proxy(this, 'close'), 500);
     },
 
-    /**
-     * @method
-     */
     open: function () {
       this.toggle(true);
     },
 
-    /**
-     * @method
-     */
     close: function () {
       this.toggle(false);
     },
 
-    /**
-     * @param {jQuery.Event} e
-     */
     focusOut: function (e) {
       this.hoverOut.call(this, e);
     },
 
-    /**
-     * @param {jQuery.Event} e
-     */
     focusIn: function (e) {
       this.hoverIn.call(this, e);
     }
   });
 
-  $.extend(Drupal.theme, /** @lends Drupal.theme */{
-
+  $.extend(Drupal.theme, {
     /**
      * A toggle is an interactive element often bound to a click handler.
      *
-     * @param {object} options
-     * @param {string} [options.title]
-     *   The HTML anchor title attribute and text for the inner span element.
+     * @param {Object} options
+     *   - {String} title: (optional) The HTML anchor title attribute and
+     *     text for the inner span element.
      *
-     * @return {string}
+     * @return {String}
      *   A string representing a DOM fragment.
      */
     dropbuttonToggle: function (options) {
diff --git a/core/misc/drupal.js b/core/misc/drupal.js
index 75f85bb..9e9d24e 100644
--- a/core/misc/drupal.js
+++ b/core/misc/drupal.js
@@ -1,40 +1,7 @@
 /**
- * @file
- * Defines the Drupal JS API.
+ * Base framework for Drupal-specific JavaScript, behaviors, and settings.
  */
-
-/**
- * A jQuery object.
- *
- * @typedef {object} jQuery
- *
- * @prop {number} length=0
- */
-
-/**
- * Variable generated by Drupal with all the configuration created from PHP.
- *
- * @global
- *
- * @var {object} drupalSettings
- */
-
-/**
- * Variable generated by Drupal that holds all translated strings from PHP.
- *
- * @global
- *
- * @var {object} drupalTranslations
- */
-
-/**
- * Global Drupal object.
- *
- * @global
- *
- * @namespace
- */
-window.Drupal = {behaviors: {}, locale: {}};
+window.Drupal = {behaviors: {}};
 
 // Class indicating that JS is enabled; used for styling purpose.
 document.documentElement.className += ' js';
@@ -51,43 +18,16 @@
   "use strict";
 
   /**
-   * Custom error type thrown after attach/detach if one or more behaviors
-   * failed.
+   * Custom error type thrown after attach/detach if one or more behaviors failed.
    *
-   * @memberof Drupal
-   *
-   * @constructor
-   *
-   * @augments Error
-   *
-   * @param {Array} list
+   * @param list
    *   An array of errors thrown during attach/detach.
-   * @param {string} event
+   * @param event
    *   A string containing either 'attach' or 'detach'.
-   *
-   * @inner
    */
   function DrupalBehaviorError(list, event) {
-
-    /**
-     * Setting name helps debuggers.
-     *
-     * @type {string}
-     */
     this.name = 'DrupalBehaviorError';
-
-    /**
-     * Execution phase errors were triggered.
-     *
-     * @type {string}
-     */
     this.event = event || 'attach';
-
-    /**
-     * All thrown errors.
-     *
-     * @type {Array.<Error>}
-     */
     this.list = list;
     // Makes the list of errors readable.
     var messageList = [];
@@ -96,100 +36,48 @@ function DrupalBehaviorError(list, event) {
     for (var i = 0; i < il; i++) {
       messageList.push(this.list[i].behavior + ': ' + this.list[i].error.message);
     }
-
-    /**
-     * Final message to send to debuggers.
-     *
-     * @type {string}
-     */
     this.message = messageList.join(' ; ');
   }
 
   DrupalBehaviorError.prototype = new Error();
 
   /**
-   * Callback function initializing code run on page load and Ajax requests.
-   *
-   * @callback Drupal~behaviorAttach
-   *
-   * @param {HTMLElement} context
-   * @param {object} settings
-   *
-   * @see Drupal.attachBehaviors
-   */
-
-  /**
-   * Callback function for reverting and cleaning up behavior initialization.
-   *
-   * @callback Drupal~behaviorDetach
-   *
-   * @param {HTMLElement} context
-   * @param {object} settings
-   * @param {string} trigger
-   *   One of 'unload', 'serialize' or 'move'.
-   *
-   * @see Drupal.detachBehaviors
-   */
-
-  /**
-   * @typedef {object} Drupal~behavior
-   *
-   * @prop {Drupal~behaviorAttach} attach
-   *   Function run on page load and after an AJAX call.
-   * @prop {Drupal~behaviorDetach} detach
-   *   Function run when content is serialized or removed from the page.
-   */
-
-  /**
-   * Holds all initialization methods.
-   *
-   * @namespace Drupal.behaviors
-   *
-   * @type {Object.<string, Drupal~behavior>}
-   */
-
-  /**
    * Attach all registered behaviors to a page element.
    *
-   * Behaviors are event-triggered actions that attach to page elements,
-   * enhancing default non-JavaScript UIs. Behaviors are registered in the
-   * {@link Drupal.behaviors} object using the method 'attach' and optionally
-   * also 'detach' as follows:
+   * Behaviors are event-triggered actions that attach to page elements, enhancing
+   * default non-JavaScript UIs. Behaviors are registered in the Drupal.behaviors
+   * object using the method 'attach' and optionally also 'detach' as follows:
+   * @code
+   *    Drupal.behaviors.behaviorName = {
+   *      attach: function (context, settings) {
+   *        ...
+   *      },
+   *      detach: function (context, settings, trigger) {
+   *        ...
+   *      }
+   *    };
+   * @endcode
    *
-   * {@link Drupal.attachBehaviors} is added below to the jQuery.ready event and
-   * therefore runs on initial page load. Developers implementing Ajax in their
-   * solutions should also call this function after new page content has been
-   * loaded, feeding in an element to be processed, in order to attach all
-   * behaviors to the new content.
+   * Drupal.attachBehaviors is added below to the jQuery.ready event and therefore
+   * runs on initial page load. Developers implementing Ajax in their solutions
+   * should also call this function after new page content has been loaded,
+   * feeding in an element to be processed, in order to attach all behaviors to
+   * the new content.
    *
    * Behaviors should use
-   *     `var elements = $(context).find(selector).once('behavior-name');`
+   * @code
+   *   var elements = $(context).find(selector).once('behavior-name');
+   * @endcode
    * to ensure the behavior is attached only once to a given element. (Doing so
-   * enables the reprocessing of given elements, which may be needed on
-   * occasion despite the ability to limit behavior attachment to a particular
-   * element.)
+   * enables the reprocessing of given elements, which may be needed on occasion
+   * despite the ability to limit behavior attachment to a particular element.)
    *
-   * @example
-   * Drupal.behaviors.behaviorName = {
-   *   attach: function (context, settings) {
-   *     ...
-   *   },
-   *   detach: function (context, settings, trigger) {
-   *     ...
-   *   }
-   * };
-   *
-   * @param {Element} context
-   *   An element to attach behaviors to. If none is given, the document
-   *   element is used.
-   * @param {object} settings
+   * @param context
+   *   An element to attach behaviors to. If none is given, the document element
+   *   is used.
+   * @param settings
    *   An object containing settings for the current context. If none is given,
    *   the global drupalSettings object is used.
-   *
-   * @see Drupal~behaviorAttach
-   * @see Drupal.detachBehaviors
-   *
-   * @throws {Drupal~DrupalBehaviorError}
    */
   Drupal.attachBehaviors = function (context, settings) {
     context = context || document;
@@ -227,22 +115,22 @@ function DrupalBehaviorError(list, event) {
    *
    * Such implementations should use .findOnce() and .removeOnce() to find
    * elements with their corresponding Drupal.behaviors.behaviorName.attach
-   * implementation, i.e. .removeOnce('behaviorName'), to ensure the behavior
-   * is detached only from previously processed elements.
+   * implementation, i.e. .removeOnce('behaviorName'), to ensure the behavior is
+   * detached only from previously processed elements.
    *
-   * @param {Element} context
-   *   An element to detach behaviors from. If none is given, the document
-   *   element is used.
-   * @param {object} settings
-   *   An object containing settings for the current context. If none given,
-   *   the global drupalSettings object is used.
-   * @param {string} trigger
+   * @param context
+   *   An element to detach behaviors from. If none is given, the document element
+   *   is used.
+   * @param settings
+   *   An object containing settings for the current context. If none given, the
+   *   global drupalSettings object is used.
+   * @param trigger
    *   A string containing what's causing the behaviors to be detached. The
    *   possible triggers are:
    *   - unload: (default) The context element is being removed from the DOM.
    *   - move: The element is about to be moved within the DOM (for example,
    *     during a tabledrag row swap). After the move is completed,
-   *     {@link Drupal.attachBehaviors} is called, so that the behavior can undo
+   *     Drupal.attachBehaviors() is called, so that the behavior can undo
    *     whatever it did in response to the move. Many behaviors won't need to
    *     do anything simply in response to the element being moved, but because
    *     IFRAME elements reload their "src" when being moved within the DOM,
@@ -255,9 +143,6 @@ function DrupalBehaviorError(list, event) {
    *     that WYSIWYG editors can update the hidden textarea to which they are
    *     bound.
    *
-   * @throws {Drupal~DrupalBehaviorError}
-   *
-   * @see Drupal~behaviorDetach
    * @see Drupal.attachBehaviors
    */
   Drupal.detachBehaviors = function (context, settings, trigger) {
@@ -286,12 +171,7 @@ function DrupalBehaviorError(list, event) {
 
   /**
    * Helper to test document width for mobile configurations.
-   *
-   * @param {number} [width=640]
-   *
-   * @return {bool}
-   *
-   * @deprecated Temporary solution for the mobile initiative.
+   * @todo Temporary solution for the mobile initiative.
    */
   Drupal.checkWidthBreakpoint = function (width) {
     width = width || drupalSettings.widthBreakpoint || 640;
@@ -301,12 +181,10 @@ function DrupalBehaviorError(list, event) {
   /**
    * Encode special characters in a plain-text string for display as HTML.
    *
-   * @param {string} str
+   * @param str
    *   The string to be encoded.
-   *
-   * @return {string}
+   * @return
    *   The encoded string.
-   *
    * @ingroup sanitization
    */
   Drupal.checkPlain = function (str) {
@@ -321,21 +199,22 @@ function DrupalBehaviorError(list, event) {
   /**
    * Replace placeholders with sanitized values in a string.
    *
-   * @param {string} str
+   * @param {String} str
    *   A string with placeholders.
-   * @param {object} args
+   * @param {Object} args
    *   An object of replacements pairs to make. Incidences of any key in this
    *   array are replaced with the corresponding value. Based on the first
    *   character of the key, the value is escaped and/or themed:
    *    - !variable: inserted as is
-   *    - @variable: escape plain text to HTML ({@link Drupal.checkPlain})
+   *    - @variable: escape plain text to HTML (Drupal.checkPlain)
    *    - %variable: escape text and theme as a placeholder for user-submitted
-   *      content ({@link Drupal.checkPlain} +
-   *      {@link Drupal.theme}('placeholder'))
+   *      content (checkPlain + Drupal.theme('placeholder'))
    *
-   * @return {string}
+   * @return {String}
+   *   Returns the replaced string.
    *
-   * @see Drupal.t
+   * @see Drupal.t()
+   * @ingroup sanitization
    */
   Drupal.formatString = function (str, args) {
     // Keep args intact.
@@ -348,12 +227,10 @@ function DrupalBehaviorError(list, event) {
           case '@':
             processedArgs[key] = Drupal.checkPlain(args[key]);
             break;
-
           // Pass-through.
           case '!':
             processedArgs[key] = args[key];
             break;
-
           // Escaped and placeholder.
           default:
             processedArgs[key] = Drupal.theme('placeholder', args[key]);
@@ -371,14 +248,14 @@ function DrupalBehaviorError(list, event) {
    * The longest keys will be tried first. Once a substring has been replaced,
    * its new value will not be searched again.
    *
-   * @param {string} str
+   * @param {String} str
    *   A string with placeholders.
-   * @param {object} args
+   * @param {Object} args
    *   Key-value pairs.
    * @param {Array|null} keys
    *   Array of keys from the "args".  Internal use only.
    *
-   * @return {string}
+   * @return {String}
    *   Returns the replaced string.
    */
   Drupal.stringReplace = function (str, args, keys) {
@@ -422,17 +299,18 @@ function DrupalBehaviorError(list, event) {
    *
    * See the documentation of the server-side t() function for further details.
    *
-   * @param {string} str
+   * @param str
    *   A string containing the English string to translate.
-   * @param {Object.<string, string>} [args]
+   * @param args
    *   An object of replacements pairs to make after translation. Incidences
    *   of any key in this array are replaced with the corresponding value.
-   *   See {@link Drupal.formatString}.
-   * @param {object} [options]
-   * @param {string} [options.context='']
-   *   The context the source string belongs to.
+   *   See Drupal.formatString().
    *
-   * @return {string}
+   * @param options
+   *   - 'context' (defaults to the empty context): The context the source string
+   *     belongs to.
+   *
+   * @return
    *   The translated string.
    */
   Drupal.t = function (str, args, options) {
@@ -452,11 +330,6 @@ function DrupalBehaviorError(list, event) {
 
   /**
    * Returns the URL to a Drupal page.
-   *
-   * @param {string} path
-   *   Drupal path to transform to URL.
-   *
-   * @return {string}
    */
   Drupal.url = function (path) {
     return drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + path;
@@ -466,33 +339,33 @@ function DrupalBehaviorError(list, event) {
    * Format a string containing a count of items.
    *
    * This function ensures that the string is pluralized correctly. Since
-   * {@link Drupal.t} is called by this function, make sure not to pass
+   * Drupal.t() is called by this function, make sure not to pass
    * already-localized strings to it.
    *
    * See the documentation of the server-side
    * \Drupal\Core\StringTranslation\TranslationInterface::formatPlural()
    * function for more details.
    *
-   * @param {number} count
+   * @param {Number} count
    *   The item count to display.
-   * @param {string} singular
+   * @param {String} singular
    *   The string for the singular case. Please make sure it is clear this is
    *   singular, to ease translation (e.g. use "1 new comment" instead of "1
    *   new"). Do not use @count in the singular string.
-   * @param {string} plural
+   * @param {String} plural
    *   The string for the plural case. Please make sure it is clear this is
    *   plural, to ease translation. Use @count in place of the item count, as in
    *   "@count new comments".
-   * @param {object} [args]
+   * @param {Object} args
    *   An object of replacements pairs to make after translation. Incidences
    *   of any key in this array are replaced with the corresponding value.
-   *   See {@link Drupal.formatString}.
+   *   See Drupal.formatString().
    *   Note that you do not need to include @count in this array.
    *   This replacement is done automatically for the plural case.
-   * @param {object} [options]
-   *   The options to pass to the {@link Drupal.t} function.
+   * @param {Object} options
+   *   The options to pass to the Drupal.t() function.
    *
-   * @return {string}
+   * @return {String}
    *   A translated string.
    */
   Drupal.formatPlural = function (count, singular, plural, args, options) {
@@ -518,11 +391,6 @@ else if (args['@count'] !== 1) {
    * Encodes a Drupal path for use in a URL.
    *
    * For aesthetic reasons slashes are not escaped.
-   *
-   * @param {string} item
-   *   Unencoded path.
-   *
-   * @return {string}
    */
   Drupal.encodePath = function (item) {
     return window.encodeURIComponent(item).replace(/%2F/g, '/');
@@ -538,16 +406,13 @@ else if (args['@count'] !== 1) {
    *
    * For example, to retrieve the HTML for text that should be emphasized and
    * displayed as a placeholder inside a sentence, call
-   * `Drupal.theme('placeholder', text)`.
+   * Drupal.theme('placeholder', text).
    *
-   * @namespace
-   *
-   * @param {function} func
+   * @param func
    *   The name of the theme function to call.
-   * @param {...args}
+   * @param ...
    *   Additional arguments to pass along to the theme function.
-   *
-   * @return {string|object|HTMLElement|jQuery}
+   * @return
    *   Any data the theme function returns. This could be a plain HTML string,
    *   but also a complex object.
    */
@@ -561,10 +426,9 @@ else if (args['@count'] !== 1) {
   /**
    * Formats text for emphasized display in a placeholder inside a sentence.
    *
-   * @param {string} str
+   * @param str
    *   The text to format (plain-text).
-   *
-   * @return {string}
+   * @return
    *   The formatted text (html).
    */
   Drupal.theme.placeholder = function (str) {
diff --git a/core/misc/form.js b/core/misc/form.js
index 7210be5..68b4e9e 100644
--- a/core/misc/form.js
+++ b/core/misc/form.js
@@ -1,25 +1,9 @@
-/**
- * @file
- * Form features.
- */
-
-/**
- * Triggers when a value in the form changed.
- *
- * The event triggers when content is typed or pasted in a text field, before
- * the change event triggers.
- *
- * @event formUpdated
- */
-
 (function ($, Drupal, debounce) {
 
   "use strict";
 
   /**
    * Retrieves the summary for the first element.
-   *
-   * @return {string}
    */
   $.fn.drupalGetSummary = function () {
     var callback = this.data('summaryCallback');
@@ -29,15 +13,9 @@
   /**
    * Sets the summary for all matched elements.
    *
-   * @param {function} callback
+   * @param callback
    *   Either a function that will be called each time the summary is
    *   retrieved or a string (which is returned each time).
-   *
-   * @return {jQuery}
-   *
-   * @fires event:summaryUpdated
-   *
-   * @listens event:formUpdated
    */
   $.fn.drupalSetSummary = function (callback) {
     var self = this;
@@ -65,13 +43,13 @@
   /**
    * Prevents consecutive form submissions of identical form values.
    *
-   * Repetitive form submissions that would submit the identical form values
-   * are prevented, unless the form values are different to the previously
-   * submitted values.
+   * Repetitive form submissions that would submit the identical form values are
+   * prevented, unless the form values are different to the previously submitted
+   * values.
    *
-   * This is a simplified re-implementation of a user-agent behavior that
-   * should be natively supported by major web browsers, but at this time, only
-   * Firefox has a built-in protection.
+   * This is a simplified re-implementation of a user-agent behavior that should
+   * be natively supported by major web browsers, but at this time, only Firefox
+   * has a built-in protection.
    *
    * A form value-based approach ensures that the constraint is triggered for
    * consecutive, identical form submissions only. Compared to that, a form
@@ -79,28 +57,26 @@
    * technically not required and (2) require more complex state management if
    * there are multiple buttons in a form.
    *
-   * This implementation is based on form-level submit events only and relies
-   * on jQuery's serialize() method to determine submitted form values. As such,
-   * the following limitations exist:
+   * This implementation is based on form-level submit events only and relies on
+   * jQuery's serialize() method to determine submitted form values. As such, the
+   * following limitations exist:
    *
    * - Event handlers on form buttons that preventDefault() do not receive a
    *   double-submit protection. That is deemed to be fine, since such button
-   *   events typically trigger reversible client-side or server-side
-   *   operations that are local to the context of a form only.
-   * - Changed values in advanced form controls, such as file inputs, are not
-   *   part of the form values being compared between consecutive form submits
-   *   (due to limitations of jQuery.serialize()). That is deemed to be
-   *   acceptable, because if the user forgot to attach a file, then the size of
-   *   HTTP payload will most likely be small enough to be fully passed to the
-   *   server endpoint within (milli)seconds. If a user mistakenly attached a
-   *   wrong file and is technically versed enough to cancel the form submission
-   *   (and HTTP payload) in order to attach a different file, then that
-   *   edge-case is not supported here.
+   *   events typically trigger reversible client-side or server-side operations
+   *   that are local to the context of a form only.
+   * - Changed values in advanced form controls, such as file inputs, are not part
+   *   of the form values being compared between consecutive form submits (due to
+   *   limitations of jQuery.serialize()). That is deemed to be acceptable,
+   *   because if the user forgot to attach a file, then the size of HTTP payload
+   *   will most likely be small enough to be fully passed to the server endpoint
+   *   within (milli)seconds. If a user mistakenly attached a wrong file and is
+   *   technically versed enough to cancel the form submission (and HTTP payload)
+   *   in order to attach a different file, then that edge-case is not supported
+   *   here.
    *
-   * Lastly, all forms submitted via HTTP GET are idempotent by definition of
-   * HTTP standards, so excluded in this implementation.
-   *
-   * @type {Drupal~behavior}
+   * Lastly, all forms submitted via HTTP GET are idempotent by definition of HTTP
+   * standards, so excluded in this implementation.
    */
   Drupal.behaviors.formSingleSubmit = {
     attach: function () {
@@ -123,10 +99,6 @@ function onFormSubmit(e) {
 
   /**
    * Sends a 'formUpdated' event each time a form element is modified.
-   *
-   * @param {HTMLElement} element
-   *
-   * @fires event:formUpdated
    */
   function triggerFormUpdated(element) {
     $(element).trigger('formUpdated');
@@ -136,7 +108,6 @@ function triggerFormUpdated(element) {
    * Collects the IDs of all form fields in the given form.
    *
    * @param {HTMLFormElement} form
-   *
    * @return {Array}
    */
   function fieldsList(form) {
@@ -151,10 +122,6 @@ function fieldsList(form) {
 
   /**
    * Triggers the 'formUpdated' event on form elements when they are modified.
-   *
-   * @type {Drupal~behavior}
-   *
-   * @fires event:formUpdated
    */
   Drupal.behaviors.formUpdated = {
     attach: function (context) {
@@ -165,8 +132,7 @@ function fieldsList(form) {
 
       if ($forms.length) {
         // Initialize form behaviors, use $.makeArray to be able to use native
-        // forEach array method and have the callback parameters in the right
-        // order.
+        // forEach array method and have the callback parameters in the right order.
         $.makeArray($forms).forEach(function (form) {
           var events = 'change.formUpdated input.formUpdated ';
           var eventHandler = debounce(function (event) { triggerFormUpdated(event.target); }, 300);
@@ -181,7 +147,7 @@ function fieldsList(form) {
         formFields = fieldsList(context).join(',');
         // @todo replace with form.getAttribute() when #1979468 is in.
         var currentFields = $(context).attr('data-drupal-form-fields');
-        // If there has been a change in the fields or their order, trigger
+        // if there has been a change in the fields or their order, trigger
         // formUpdated.
         if (formFields !== currentFields) {
           triggerFormUpdated(context);
@@ -206,8 +172,6 @@ function fieldsList(form) {
 
   /**
    * Prepopulate form fields with information from the visitor browser.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.fillUserInfoFromBrowser = {
     attach: function (context, settings) {
diff --git a/core/misc/machine-name.js b/core/misc/machine-name.js
index 2b304bf..13e0034 100644
--- a/core/misc/machine-name.js
+++ b/core/misc/machine-name.js
@@ -1,39 +1,28 @@
-/**
- * @file
- * Machine name functionality.
- */
-
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Attach the machine-readable name form element behavior.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.machineName = {
-
     /**
      * Attaches the behavior.
      *
-     * @param {Element} context
-     * @param {object} settings
-     * @param {object} settings.machineName
-     *   A list of elements to process, keyed by the HTML ID of the form
-     *   element containing the human-readable value. Each element is an object
-     *   defining the following properties:
+     * @param settings.machineName
+     *   A list of elements to process, keyed by the HTML ID of the form element
+     *   containing the human-readable value. Each element is an object defining
+     *   the following properties:
      *   - target: The HTML ID of the machine name form element.
-     *   - suffix: The HTML ID of a container to show the machine name preview
-     *     in (usually a field suffix after the human-readable name
-     *     form element).
+     *   - suffix: The HTML ID of a container to show the machine name preview in
+     *     (usually a field suffix after the human-readable name form element).
      *   - label: The label to show for the machine name preview.
      *   - replace_pattern: A regular expression (without modifiers) matching
      *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
-     *   - replace: A character to replace disallowed characters with; e.g.,
-     *     '_' or '-'.
-     *   - standalone: Whether the preview should stay in its own element
-     *     rather than the suffix of the source element.
+     *   - replace: A character to replace disallowed characters with; e.g., '_'
+     *     or '-'.
+     *   - standalone: Whether the preview should stay in its own element rather
+     *     than the suffix of the source element.
      *   - field_prefix: The #field_prefix of the form element.
      *   - field_suffix: The #field_suffix of the form element.
      */
@@ -105,9 +94,9 @@ function machineNameHandler(e) {
         options.maxlength = $target.attr('maxlength');
         // Hide the form item container of the machine name form element.
         $wrapper.addClass('visually-hidden');
-        // Determine the initial machine name value. Unless the machine name
-        // form element is disabled or not empty, the initial default value is
-        // based on the human-readable form element value.
+        // Determine the initial machine name value. Unless the machine name form
+        // element is disabled or not empty, the initial default value is based on
+        // the human-readable form element value.
         if ($target.is(':disabled') || $target.val() !== '') {
           machine = $target.val();
         }
@@ -174,19 +163,17 @@ else if ($source.val() !== '') {
     /**
      * Transliterate a human-readable name to a machine name.
      *
-     * @param {string} source
+     * @param source
      *   A string to transliterate.
-     * @param {object} settings
-     *   The machine name settings for the corresponding field.
-     * @param {string} settings.replace_pattern
-     *   A regular expression (without modifiers) matching disallowed characters
-     *   in the machine name; e.g., '[^a-z0-9]+'.
-     * @param {string} settings.replace
-     *   A character to replace disallowed characters with; e.g., '_' or '-'.
-     * @param {number} settings.maxlength
-     *   The maximum length of the machine name.
+     * @param settings
+     *   The machine name settings for the corresponding field, containing:
+     *   - replace_pattern: A regular expression (without modifiers) matching
+     *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
+     *   - replace: A character to replace disallowed characters with; e.g., '_'
+     *     or '-'.
+     *   - maxlength: The maximum length of the machine name.
      *
-     * @return {jQuery}
+     * @return
      *   The transliterated source string.
      */
     transliterate: function (source, settings) {
diff --git a/core/misc/progress.js b/core/misc/progress.js
index fdfd3b6..7305d24 100644
--- a/core/misc/progress.js
+++ b/core/misc/progress.js
@@ -1,8 +1,3 @@
-/**
- * @file
- * Progress bar.
- */
-
 (function ($, Drupal) {
 
   "use strict";
@@ -10,9 +5,7 @@
   /**
    * Theme function for the progress bar.
    *
-   * @param {string} id
-   *
-   * @return {string}
+   * @return
    *   The HTML for the progress bar.
    */
   Drupal.theme.progressBar = function (id) {
@@ -28,19 +21,11 @@
    * A progressbar object. Initialized with the given id. Must be inserted into
    * the DOM afterwards through progressBar.element.
    *
-   * Method is the function which will perform the HTTP request to get the
+   * method is the function which will perform the HTTP request to get the
    * progress bar state. Either "GET" or "POST".
    *
-   * @example
-   * pb = new Drupal.ProgressBar('myProgressBar');
-   * some_element.appendChild(pb.element);
-   *
-   * @constructor
-   *
-   * @param {string} id
-   * @param {function} updateCallback
-   * @param {string} method
-   * @param {function} errorCallback
+   * e.g. pb = new Drupal.ProgressBar('myProgressBar');
+   *      some_element.appendChild(pb.element);
    */
   Drupal.ProgressBar = function (id, updateCallback, method, errorCallback) {
     this.id = id;
@@ -48,21 +33,14 @@
     this.updateCallback = updateCallback;
     this.errorCallback = errorCallback;
 
-    // The WAI-ARIA setting aria-live="polite" will announce changes after
-    // users
-    // have completed their current activity and not interrupt the screen
-    // reader.
+    // The WAI-ARIA setting aria-live="polite" will announce changes after users
+    // have completed their current activity and not interrupt the screen reader.
     this.element = $(Drupal.theme('progressBar', id));
   };
 
-  $.extend(Drupal.ProgressBar.prototype, /** @lends Drupal.ProgressBar# */{
-
+  $.extend(Drupal.ProgressBar.prototype, {
     /**
      * Set the percentage and status message for the progressbar.
-     *
-     * @param {number} percentage
-     * @param {string} message
-     * @param {string} label
      */
     setProgress: function (percentage, message, label) {
       if (percentage >= 0 && percentage <= 100) {
@@ -78,9 +56,6 @@
 
     /**
      * Start monitoring progress via Ajax.
-     *
-     * @param {string} uri
-     * @param {number} delay
      */
     startMonitoring: function (uri, delay) {
       this.delay = delay;
@@ -108,18 +83,11 @@
         var pb = this;
         // When doing a post request, you need non-null data. Otherwise a
         // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
-        var uri = this.uri;
-        if (uri.indexOf('?') === -1) {
-          uri += '?';
-        }
-        else {
-          uri += '&';
-        }
-        uri += '_format=json';
         $.ajax({
           type: this.method,
-          url: uri,
+          url: this.uri,
           data: '',
+          dataType: 'json',
           success: function (progress) {
             // Display errors.
             if (progress.status === 0) {
@@ -141,8 +109,6 @@
 
     /**
      * Display errors on the page.
-     *
-     * @param {string} string
      */
     displayError: function (string) {
       var error = $('<div class="messages messages--error"></div>').html(string);
diff --git a/core/misc/states.js b/core/misc/states.js
index 3a67aea..b969da7 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -1,8 +1,6 @@
 /**
- * @file
  * Drupal's states library.
  */
-
 (function ($) {
 
   "use strict";
@@ -12,21 +10,14 @@
    *
    * Having the local states variable allows us to use the States namespace
    * without having to always declare "Drupal.states".
-   *
-   * @namespace Drupal.states
    */
   var states = Drupal.states = {
-
-    /**
-     * An array of functions that should be postponed.
-     */
+    // An array of functions that should be postponed.
     postponed: []
   };
 
   /**
    * Attaches the states.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.states = {
     attach: function (context, settings) {
@@ -57,18 +48,13 @@
   /**
    * Object representing an element that depends on other elements.
    *
-   * @constructor Drupal.states.Dependent
-   *
-   * @param {object} args
-   *   Object with the following keys (all of which are required)
-   * @param {jQuery} args.element
-   *   A jQuery object of the dependent element
-   * @param {Drupal.states.State} args.state
-   *   A State object describing the state that is dependent
-   * @param {object} args.constraints
-   *   An object with dependency specifications. Lists all elements that this
-   *   element depends on. It can be nested and can contain
-   *   arbitrary AND and OR clauses.
+   * @param args
+   *   Object with the following keys (all of which are required):
+   *   - element: A jQuery object of the dependent element
+   *   - state: A State object describing the state that is dependent
+   *   - constraints: An object with dependency specifications. Lists all elements
+   *     that this element depends on. It can be nested and can contain arbitrary
+   *     AND and OR clauses.
    */
   states.Dependent = function (args) {
     $.extend(this, {values: {}, oldValue: null}, args);
@@ -85,12 +71,6 @@
    * Comparison functions for comparing the value of an element with the
    * specification from the dependency settings. If the object type can't be
    * found in this list, the === operator is used by default.
-   *
-   * @name Drupal.states.Dependent.comparisons
-   *
-   * @prop {function} RegExp
-   * @prop {function} Function
-   * @prop {function} Number
    */
   states.Dependent.comparisons = {
     'RegExp': function (reference, value) {
@@ -101,25 +81,21 @@
       return reference(value);
     },
     'Number': function (reference, value) {
-      // If "reference" is a number and "value" is a string, then cast
-      // reference as a string before applying the strict comparison in
-      // compare().
-      // Otherwise numeric keys in the form's #states array fail to match
-      // string values returned from jQuery's val().
+      // If "reference" is a number and "value" is a string, then cast reference
+      // as a string before applying the strict comparison in compare(). Otherwise
+      // numeric keys in the form's #states array fail to match string values
+      // returned from jQuery's val().
       return (typeof value === 'string') ? compare(reference.toString(), value) : compare(reference, value);
     }
   };
 
   states.Dependent.prototype = {
-
     /**
      * Initializes one of the elements this dependent depends on.
      *
-     * @memberof Drupal.states.Dependent#
-     *
-     * @param {string} selector
+     * @param selector
      *   The CSS selector describing the dependee.
-     * @param {object} dependeeStates
+     * @param dependeeStates
      *   The list of states that have to be monitored for tracking the
      *   dependee's compliance status.
      */
@@ -137,8 +113,7 @@ function stateEventHandler(e) {
       for (var i in dependeeStates) {
         if (dependeeStates.hasOwnProperty(i)) {
           state = dependeeStates[i];
-          // Make sure we're not initializing this selector/state combination
-          // twice.
+          // Make sure we're not initializing this selector/state combination twice.
           if ($.inArray(state, dependeeStates) === -1) {
             continue;
           }
@@ -160,16 +135,14 @@ function stateEventHandler(e) {
     /**
      * Compares a value with a reference value.
      *
-     * @memberof Drupal.states.Dependent#
-     *
-     * @param {object} reference
+     * @param reference
      *   The value used for reference.
-     * @param {string} selector
+     * @param selector
      *   CSS selector describing the dependee.
-     * @param {Drupal.states.State} state
+     * @param state
      *   A State object describing the dependee's updated state.
      *
-     * @return {bool}
+     * @return
      *   true or false.
      */
     compare: function (reference, selector, state) {
@@ -187,13 +160,11 @@ function stateEventHandler(e) {
     /**
      * Update the value of a dependee's state.
      *
-     * @memberof Drupal.states.Dependent#
-     *
-     * @param {string} selector
+     * @param selector
      *   CSS selector describing the dependee.
-     * @param {Drupal.states.state} state
+     * @param state
      *   A State object describing the dependee's updated state.
-     * @param {string} value
+     * @param value
      *   The new value for the dependee's updated state.
      */
     update: function (selector, state, value) {
@@ -206,8 +177,6 @@ function stateEventHandler(e) {
 
     /**
      * Triggers change events in case a state changed.
-     *
-     * @memberof Drupal.states.Dependent#
      */
     reevaluate: function () {
       // Check whether any constraint for this dependent state is satisfied.
@@ -231,16 +200,14 @@ function stateEventHandler(e) {
     /**
      * Evaluates child constraints to determine if a constraint is satisfied.
      *
-     * @memberof Drupal.states.Dependent#
-     *
-     * @param {object|Array} constraints
+     * @param constraints
      *   A constraint object or an array of constraints.
-     * @param {string} selector
+     * @param selector
      *   The selector for these constraints. If undefined, there isn't yet a
      *   selector that these constraints apply to. In that case, the keys of the
      *   object are interpreted as the selector if encountered.
      *
-     * @return {bool}
+     * @return
      *   true or false, depending on whether these constraints are satisfied.
      */
     verifyConstraints: function (constraints, selector) {
@@ -252,8 +219,8 @@ function stateEventHandler(e) {
         for (var i = 0; i < len; i++) {
           if (constraints[i] !== 'xor') {
             var constraint = this.checkConstraints(constraints[i], selector, i);
-            // Return if this is OR and we have a satisfied constraint or if
-            // this is XOR and we have a second satisfied constraint.
+            // Return if this is OR and we have a satisfied constraint or if this
+            // is XOR and we have a second satisfied constraint.
             if (constraint && (hasXor || result)) {
               return hasXor;
             }
@@ -262,15 +229,15 @@ function stateEventHandler(e) {
         }
       }
       // Make sure we don't try to iterate over things other than objects. This
-      // shouldn't normally occur, but in case the condition definition is
-      // bogus, we don't want to end up with an infinite loop.
+      // shouldn't normally occur, but in case the condition definition is bogus,
+      // we don't want to end up with an infinite loop.
       else if ($.isPlainObject(constraints)) {
         // This constraint is an object (AND).
         for (var n in constraints) {
           if (constraints.hasOwnProperty(n)) {
             result = ternary(result, this.checkConstraints(constraints[n], selector, n));
-            // False and anything else will evaluate to false, so return when
-            // any false condition is found.
+            // False and anything else will evaluate to false, so return when any
+            // false condition is found.
             if (result === false) { return false; }
           }
         }
@@ -281,28 +248,27 @@ else if ($.isPlainObject(constraints)) {
     /**
      * Checks whether the value matches the requirements for this constraint.
      *
-     * @memberof Drupal.states.Dependent#
-     *
-     * @param {string|Array|object} value
+     * @param value
      *   Either the value of a state or an array/object of constraints. In the
      *   latter case, resolving the constraint continues.
-     * @param {string} [selector]
+     * @param selector
      *   The selector for this constraint. If undefined, there isn't yet a
-     *   selector that this constraint applies to. In that case, the state key
-     *   is propagates to a selector and resolving continues.
-     * @param {Drupal.states.State} [state]
+     *   selector that this constraint applies to. In that case, the state key is
+     *   propagates to a selector and resolving continues.
+     * @param state
      *   The state to check for this constraint. If undefined, resolving
-     *   continues. If both selector and state aren't undefined and valid
-     *   non-numeric strings, a lookup for the actual value of that selector's
-     *   state is performed. This parameter is not a State object but a pristine
-     *   state string.
+     *   continues.
+     *   If both selector and state aren't undefined and valid non-numeric
+     *   strings, a lookup for the actual value of that selector's state is
+     *   performed. This parameter is not a State object but a pristine state
+     *   string.
      *
-     * @return {bool}
+     * @return
      *   true or false, depending on whether this constraint is satisfied.
      */
     checkConstraints: function (value, selector, state) {
-      // Normalize the last parameter. If it's non-numeric, we treat it either
-      // as a selector (in case there isn't one yet) or as a trigger/state.
+      // Normalize the last parameter. If it's non-numeric, we treat it either as
+      // a selector (in case there isn't one yet) or as a trigger/state.
       if (typeof state !== 'string' || (/[0-9]/).test(state[0])) {
         state = null;
       }
@@ -313,7 +279,7 @@ else if (typeof selector === 'undefined') {
       }
 
       if (state !== null) {
-        // Constraints is the actual constraints of an element to check for.
+        // constraints is the actual constraints of an element to check for.
         state = states.State.sanitize(state);
         return invert(this.compare(value, selector, state), state.invert);
       }
@@ -325,15 +291,11 @@ else if (typeof selector === 'undefined') {
 
     /**
      * Gathers information about all required triggers.
-     *
-     * @memberof Drupal.states.Dependent#
-     *
-     * @return {object}
      */
     getDependees: function () {
       var cache = {};
-      // Swivel the lookup function so that we can record all available
-      // selector- state combinations for initialization.
+      // Swivel the lookup function so that we can record all available selector-
+      // state combinations for initialization.
       var _compare = this.compare;
       this.compare = function (reference, selector, state) {
         (cache[selector] || (cache[selector] = [])).push(state.name);
@@ -355,11 +317,6 @@ else if (typeof selector === 'undefined') {
     }
   };
 
-  /**
-   * @constructor Drupal.states.Trigger
-   *
-   * @param {object} args
-   */
   states.Trigger = function (args) {
     $.extend(this, args);
 
@@ -375,10 +332,6 @@ else if (typeof selector === 'undefined') {
   };
 
   states.Trigger.prototype = {
-
-    /**
-     * @memberof Drupal.states.Trigger#
-     */
     initialize: function () {
       var trigger = states.Trigger.states[this.state];
 
@@ -398,12 +351,6 @@ else if (typeof selector === 'undefined') {
       this.element.data('trigger:' + this.state, true);
     },
 
-    /**
-     * @memberof Drupal.states.Trigger#
-     *
-     * @param {jQuery.Event} event
-     * @param {function} valueFn
-     */
     defaultTrigger: function (event, valueFn) {
       var oldValue = valueFn.call(this.element);
 
@@ -429,16 +376,9 @@ else if (typeof selector === 'undefined') {
    * of an element. Whenever an element depends on the state of another element,
    * one of these trigger functions is added to the dependee so that the
    * dependent element can be updated.
-   *
-   * @name Drupal.states.Trigger.states
-   *
-   * @prop empty
-   * @prop checked
-   * @prop value
-   * @prop collapsed
    */
   states.Trigger.states = {
-    // 'empty' describes the state to be monitored.
+    // 'empty' describes the state to be monitored
     empty: {
       // 'keyup' is the (native DOM) event that we watch for.
       'keyup': function () {
@@ -450,9 +390,9 @@ else if (typeof selector === 'undefined') {
 
     checked: {
       'change': function () {
-        // prop() and attr() only takes the first element into account. To
-        // support selectors matching multiple checkboxes, iterate over all and
-        // return whether any is checked.
+        // prop() and attr() only takes the first element into account. To support
+        // selectors matching multiple checkboxes, iterate over all and return
+        // whether any is checked.
         var checked = false;
         this.each(function () {
           // Use prop() here as we want a boolean of the checkbox state.
@@ -494,16 +434,9 @@ else if (typeof selector === 'undefined') {
 
   /**
    * A state object is used for describing the state and performing aliasing.
-   *
-   * @constructor Drupal.states.State
-   *
-   * @param {string} state
    */
   states.State = function (state) {
-
-    /**
-     * Original unresolved name.
-     */
+    // We may need the original unresolved name later.
     this.pristine = this.name = state;
 
     // Normalize the state name.
@@ -527,12 +460,6 @@ else if (typeof selector === 'undefined') {
 
   /**
    * Creates a new State object by sanitizing the passed value.
-   *
-   * @name Drupal.states.State.sanitize
-   *
-   * @param {string|Drupal.states.State} state
-   *
-   * @return {Drupal.states.state}
    */
   states.State.sanitize = function (state) {
     if (state instanceof states.State) {
@@ -544,10 +471,8 @@ else if (typeof selector === 'undefined') {
   };
 
   /**
-   * This list of aliases is used to normalize states and associates negated
-   * names with their respective inverse state.
-   *
-   * @name Drupal.states.State.aliases
+   * This list of aliases is used to normalize states and associates negated names
+   * with their respective inverse state.
    */
   states.State.aliases = {
     'enabled': '!disabled',
@@ -565,18 +490,10 @@ else if (typeof selector === 'undefined') {
   };
 
   states.State.prototype = {
-
-    /**
-     * @memberof Drupal.states.State#
-     */
     invert: false,
 
     /**
      * Ensures that just using the state object returns the name.
-     *
-     * @memberof Drupal.states.State#
-     *
-     * @return {string}
      */
     toString: function () {
       return this.name;
@@ -646,13 +563,6 @@ else if (typeof selector === 'undefined') {
 
   /**
    * Bitwise AND with a third undefined state.
-   *
-   * @function Drupal.states~ternary
-   *
-   * @param {*} a
-   * @param {*} b
-   *
-   * @return {bool}
    */
   function ternary(a, b) {
     if (typeof a === 'undefined') {
@@ -668,13 +578,6 @@ else if (typeof b === 'undefined') {
 
   /**
    * Inverts a (if it's not undefined) when invertState is true.
-   *
-   * @function Drupal.states~invert
-   *
-   * @param {*} a
-   * @param {bool} invertState
-   *
-   * @return {bool}
    */
   function invert(a, invertState) {
     return (invertState && typeof a !== 'undefined') ? !a : a;
@@ -682,13 +585,6 @@ function invert(a, invertState) {
 
   /**
    * Compares two values while ignoring undefined values.
-   *
-   * @function Drupal.states~compare
-   *
-   * @param {*} a
-   * @param {*} b
-   *
-   * @return {bool}
    */
   function compare(a, b) {
     if (a === b) {
diff --git a/core/misc/tabbingmanager.js b/core/misc/tabbingmanager.js
index 4593ec4..dc21c02 100644
--- a/core/misc/tabbingmanager.js
+++ b/core/misc/tabbingmanager.js
@@ -3,76 +3,42 @@
  * Manages page tabbing modifications made by modules.
  */
 
-/**
- * Allow modules to respond to the constrain event.
- *
- * @event drupalTabbingConstrained
- */
-
-/**
- * Allow modules to respond to the tabbingContext release event.
- *
- * @event drupalTabbingContextReleased
- */
-
-/**
- * Allow modules to respond to the constrain event.
- *
- * @event drupalTabbingContextActivated
- */
-
-/**
- * Allow modules to respond to the constrain event.
- *
- * @event drupalTabbingContextDeactivated
- */
-
 (function ($, Drupal) {
 
   "use strict";
 
   /**
    * Provides an API for managing page tabbing order modifications.
-   *
-   * @constructor Drupal~TabbingManager
    */
   function TabbingManager() {
-
-    /**
-     * Tabbing sets are stored as a stack. The active set is at the top of the
-     * stack. We use a JavaScript array as if it were a stack; we consider the
-     * first element to be the bottom and the last element to be the top. This
-     * allows us to use JavaScript's built-in Array.push() and Array.pop()
-     * methods.
-     *
-     * @type {Array.<Drupal~TabbingContext>}
-     */
+    // Tabbing sets are stored as a stack. The active set is at the top of the
+    // stack. We use a JavaScript array as if it were a stack; we consider the
+    // first element to be the bottom and the last element to be the top. This
+    // allows us to use JavaScript's built-in Array.push() and Array.pop()
+    // methods.
     this.stack = [];
   }
 
   /**
    * Add public methods to the TabbingManager class.
    */
-  $.extend(TabbingManager.prototype, /** @lends Drupal~TabbingManager# */{
-
+  $.extend(TabbingManager.prototype, {
     /**
      * Constrain tabbing to the specified set of elements only.
      *
-     * Makes elements outside of the specified set of elements unreachable via
-     * the tab key.
+     * Makes elements outside of the specified set of elements unreachable via the
+     * tab key.
      *
-     * @param {jQuery} elements
-     *   The set of elements to which tabbing should be constrained. Can also
-     *   be a jQuery-compatible selector string.
+     * @param jQuery elements
+     *   The set of elements to which tabbing should be constrained. Can also be
+     *   a jQuery-compatible selector string.
      *
-     * @return {Drupal~TabbingContext}
-     *
-     * @fires event:drupalTabbingConstrained
+     * @return TabbingContext
      */
     constrain: function (elements) {
       // Deactivate all tabbingContexts to prepare for the new constraint. A
-      // tabbingContext instance will only be reactivated if the stack is
-      // unwound to it in the _unwindStack() method.
+      // tabbingContext instance will only be reactivated if the stack is unwound
+      // to it in the _unwindStack() method.
       var il = this.stack.length;
       for (var i = 0; i < il; i++) {
         this.stack[i].deactivate();
@@ -102,15 +68,14 @@ function TabbingManager() {
     },
 
     /**
-     * Restores a former tabbingContext when an active one is released.
+     * Restores a former tabbingContext when an active tabbingContext is released.
      *
-     * The TabbingManager stack of tabbingContext instances will be unwound
-     * from the top-most released tabbingContext down to the first non-released
+     * The TabbingManager stack of tabbingContext instances will be unwound from
+     * the top-most released tabbingContext down to the first non-released
      * tabbingContext instance. This non-released instance is then activated.
      */
     release: function () {
-      // Unwind as far as possible: find the topmost non-released
-      // tabbingContext.
+      // Unwind as far as possible: find the topmost non-released tabbingContext.
       var toActivate = this.stack.length - 1;
       while (toActivate >= 0 && this.stack[toActivate].released) {
         toActivate--;
@@ -129,11 +94,11 @@ function TabbingManager() {
     /**
      * Makes all elements outside the of the tabbingContext's set untabbable.
      *
-     * Elements made untabbable have their original tabindex and autofocus
-     * values stored so that they might be restored later when this
-     * tabbingContext is deactivated.
+     * Elements made untabbable have their original tabindex and autofocus values
+     * stored so that they might be restored later when this tabbingContext
+     * is deactivated.
      *
-     * @param {Drupal~TabbingContext} tabbingContext
+     * @param TabbingContext tabbingContext
      *   The TabbingContext instance that has been activated.
      */
     activate: function (tabbingContext) {
@@ -150,18 +115,17 @@ function TabbingManager() {
       for (var i = 0; i < il; i++) {
         this.recordTabindex($disabledSet.eq(i), level);
       }
-      // Make all tabbable elements outside of the active tabbing set
-      // unreachable.
+      // Make all tabbable elements outside of the active tabbing set unreachable.
       $disabledSet
         .prop('tabindex', -1)
         .prop('autofocus', false);
 
-      // Set focus on an element in the tabbingContext's set of tabbable
-      // elements. First, check if there is an element with an autofocus
-      // attribute. Select the last one from the DOM order.
+      // Set focus on an element in the tabbingContext's set of tabbable elements.
+      // First, check if there is an element with an autofocus attribute. Select
+      // the last one from the DOM order.
       var $hasFocus = $set.filter('[autofocus]').eq(-1);
-      // If no element in the tabbable set has an autofocus attribute, select
-      // the first element in the set.
+      // If no element in the tabbable set has an autofocus attribute, select the
+      // first element in the set.
       if ($hasFocus.length === 0) {
         $hasFocus = $set.eq(0);
       }
@@ -171,10 +135,10 @@ function TabbingManager() {
     /**
      * Restores that tabbable state of a tabbingContext's disabled elements.
      *
-     * Elements that were made untabbable have their original tabindex and
-     * autofocus values restored.
+     * Elements that were made untabbable have their original tabindex and autofocus
+     * values restored.
      *
-     * @param {Drupal~TabbingContext} tabbingContext
+     * @param TabbingContext tabbingContext
      *   The TabbingContext instance that has been deactivated.
      */
     deactivate: function (tabbingContext) {
@@ -189,9 +153,9 @@ function TabbingManager() {
     /**
      * Records the tabindex and autofocus values of an untabbable element.
      *
-     * @param {jQuery} $el
+     * @param jQuery $set
      *   The set of elements that have been disabled.
-     * @param {number} level
+     * @param Number level
      *   The stack level for which the tabindex attribute should be recorded.
      */
     recordTabindex: function ($el, level) {
@@ -206,9 +170,9 @@ function TabbingManager() {
     /**
      * Restores the tabindex and autofocus values of a reactivated element.
      *
-     * @param {jQuery} $el
+     * @param jQuery $el
      *   The element that is being reactivated.
-     * @param {number} level
+     * @param Number level
      *   The stack level for which the tabindex attribute should be restored.
      */
     restoreTabindex: function ($el, level) {
@@ -250,53 +214,26 @@ function TabbingManager() {
    *
    * This constraint can be removed with the release() method.
    *
-   * @constructor Drupal~TabbingContext
-   *
-   * @param {object} options
-   *   A set of initiating values
-   * @param {number} options.level
-   *   The level in the TabbingManager's stack of this tabbingContext.
-   * @param {jQuery} options.$tabbableElements
-   *   The DOM elements that should be reachable via the tab key when this
-   *   tabbingContext is active.
-   * @param {jQuery} options.$disabledElements
-   *   The DOM elements that should not be reachable via the tab key when this
-   *   tabbingContext is active.
-   * @param {bool} options.released
-   *   A released tabbingContext can never be activated again. It will be
-   *   cleaned up when the TabbingManager unwinds its stack.
-   * @param {bool} options.active
-   *   When true, the tabbable elements of this tabbingContext will be reachable
-   *   via the tab key and the disabled elements will not. Only one
-   *   tabbingContext can be active at a time.
+   * @param Object options
+   *   A set of initiating values that include:
+   *   - Number level: The level in the TabbingManager's stack of this
+   *   tabbingContext.
+   *   - jQuery $tabbableElements: The DOM elements that should be reachable via
+   *   the tab key when this tabbingContext is active.
+   *   - jQuery $disabledElements: The DOM elements that should not be reachable
+   *   via the tab key when this tabbingContext is active.
+   *   - Boolean released: A released tabbingContext can never be activated again.
+   *   It will be cleaned up when the TabbingManager unwinds its stack.
+   *   - Boolean active: When true, the tabbable elements of this tabbingContext
+   *   will be reachable via the tab key and the disabled elements will not. Only
+   *   one tabbingContext can be active at a time.
    */
   function TabbingContext(options) {
-
-    $.extend(this, /** @lends Drupal~TabbingContext# */{
-
-      /**
-       * @type {?number}
-       */
+    $.extend(this, {
       level: null,
-
-      /**
-       * @type {jQuery}
-       */
       $tabbableElements: $(),
-
-      /**
-       * @type {jQuery}
-       */
       $disabledElements: $(),
-
-      /**
-       * @type {bool}
-       */
       released: false,
-
-      /**
-       * @type {bool}
-       */
       active: false
     }, options);
   }
@@ -304,15 +241,11 @@ function TabbingContext(options) {
   /**
    * Add public methods to the TabbingContext class.
    */
-  $.extend(TabbingContext.prototype, /** @lends Drupal~TabbingContext# */{
-
+  $.extend(TabbingContext.prototype, {
     /**
      * Releases this TabbingContext.
      *
-     * Once a TabbingContext object is released, it can never be activated
-     * again.
-     *
-     * @fires event:drupalTabbingContextReleased
+     * Once a TabbingContext object is released, it can never be activated again.
      */
     release: function () {
       if (!this.released) {
@@ -326,8 +259,6 @@ function TabbingContext(options) {
 
     /**
      * Activates this TabbingContext.
-     *
-     * @fires event:drupalTabbingContextActivated
      */
     activate: function () {
       // A released TabbingContext object can never be activated again.
@@ -341,8 +272,6 @@ function TabbingContext(options) {
 
     /**
      * Deactivates this TabbingContext.
-     *
-     * @fires event:drupalTabbingContextDeactivated
      */
     deactivate: function () {
       if (this.active) {
@@ -359,10 +288,6 @@ function TabbingContext(options) {
   if (Drupal.tabbingManager) {
     return;
   }
-
-  /**
-   * @type {Drupal~TabbingManager}
-   */
   Drupal.tabbingManager = new TabbingManager();
 
 }(jQuery, Drupal));
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index c3a0f5a..faea38b 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -1,21 +1,9 @@
-/**
- * @file
- * Provide dragging capabilities to admin uis.
- */
-
-/**
- * Triggers when weights columns are toggled.
- *
- * @event columnschange
- */
-
 (function ($, Drupal, drupalSettings) {
 
   "use strict";
 
   /**
    * Store the state of weight columns display for all tables.
-   *
    * Default value is to hide weight columns.
    */
   var showWeight = JSON.parse(localStorage.getItem('Drupal.tableDrag.showWeight'));
@@ -24,15 +12,12 @@
    * Drag and drop table rows with field manipulation.
    *
    * Using the drupal_attach_tabledrag() function, any table with weights or
-   * parent relationships may be made into draggable tables. Columns containing
-   * a field may optionally be hidden, providing a better user experience.
+   * parent relationships may be made into draggable tables. Columns containing a
+   * field may optionally be hidden, providing a better user experience.
    *
    * Created tableDrag instances may be modified with custom behaviors by
    * overriding the .onDrag, .onDrop, .row.onSwap, and .row.onIndent methods.
-   * See blocks.js for an example of adding additional functionality to
-   * tableDrag.
-   *
-   * @type {Drupal~behavior}
+   * See blocks.js for an example of adding additional functionality to tableDrag.
    */
   Drupal.behaviors.tableDrag = {
     attach: function (context, settings) {
@@ -53,126 +38,39 @@ function initTableDrag(table, base) {
   };
 
   /**
-   * Provides table and field manipulation.
+   * Constructor for the tableDrag object. Provides table and field manipulation.
    *
-   * @constructor
-   *
-   * @param {HTMLElement} table
+   * @param table
    *   DOM object for the table to be made draggable.
-   * @param {object} tableSettings
+   * @param tableSettings
    *   Settings for the table added via drupal_add_dragtable().
    */
   Drupal.tableDrag = function (table, tableSettings) {
     var self = this;
     var $table = $(table);
 
-    /**
-     * @type {jQuery}
-     */
+    // Required object variables.
     this.$table = $(table);
-
-    /**
-     *
-     * @type {HTMLElement}
-     */
     this.table = table;
-
-    /**
-     * @type {object}
-     */
     this.tableSettings = tableSettings;
-
-    /**
-     * Used to hold information about a current drag operation.
-     *
-     * @type {?HTMLElement}
-     */
-    this.dragObject = null;
-
-    /**
-     * Provides operations for row manipulation.
-     *
-     * @type {?HTMLElement}
-     */
-    this.rowObject = null;
-
-    /**
-     * Remember the previous element.
-     *
-     * @type {?HTMLElement}
-     */
-    this.oldRowElement = null;
-
-    /**
-     * Used to determine up or down direction from last mouse move.
-     *
-     * @type {number}
-     */
-    this.oldY = 0;
-
-    /**
-     * Whether anything in the entire table has changed.
-     *
-     * @type {bool}
-     */
-    this.changed = false;
-
-    /**
-     * Maximum amount of allowed parenting.
-     *
-     * @type {number}
-     */
-    this.maxDepth = 0;
-
-    /**
-     * Direction of the table.
-     *
-     * @type {number}
-     */
-    this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1;
-
-    /**
-     *
-     * @type {bool}
-     */
+    this.dragObject = null; // Used to hold information about a current drag operation.
+    this.rowObject = null; // Provides operations for row manipulation.
+    this.oldRowElement = null; // Remember the previous element.
+    this.oldY = 0; // Used to determine up or down direction from last mouse move.
+    this.changed = false; // Whether anything in the entire table has changed.
+    this.maxDepth = 0; // Maximum amount of allowed parenting.
+    this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1; // Direction of the table.
     this.striping = $(this.table).data('striping') === 1;
 
-    /**
-     * Configure the scroll settings.
-     *
-     * @type {object}
-     *
-     * @prop {number} amount
-     * @prop {number} interval
-     * @prop {number} trigger
-     */
+    // Configure the scroll settings.
     this.scrollSettings = {amount: 4, interval: 50, trigger: 70};
-
-    /**
-     *
-     * @type {?number}
-     */
     this.scrollInterval = null;
-
-    /**
-     *
-     * @type {number}
-     */
     this.scrollY = 0;
-
-    /**
-     *
-     * @type {number}
-     */
     this.windowHeight = 0;
 
-    /**
-     * Check this table's settings to see if there are parent relationships in
-     * this table. For efficiency, large sections of code can be skipped if we
-     * don't need to track horizontal movement and indentations.
-     *
-     * @type {bool}
-     */
+    // Check this table's settings to see if there are parent relationships in
+    // this table. For efficiency, large sections of code can be skipped if we
+    // don't need to track horizontal movement and indentations.
     this.indentEnabled = false;
     for (var group in tableSettings) {
       if (tableSettings.hasOwnProperty(group)) {
@@ -189,13 +87,7 @@ function initTableDrag(table, base) {
       }
     }
     if (this.indentEnabled) {
-
-      /**
-       * Total width of indents, set in makeDraggable.
-       *
-       * @type {number}
-       */
-      this.indentCount = 1;
+      this.indentCount = 1; // Total width of indents, set in makeDraggable.
       // Find the width of indentations to measure mouse movements against.
       // Because the table doesn't need to start with any indentations, we
       // manually append 2 indentations in the first draggable row, measure
@@ -204,11 +96,6 @@ function initTableDrag(table, base) {
       var testRow = $('<tr/>').addClass('draggable').appendTo(table);
       var testCell = $('<td/>').appendTo(testRow).prepend(indent).prepend(indent);
       var $indentation = testCell.find('.js-indentation');
-
-      /**
-       *
-       * @type {number}
-       */
       this.indentAmount = $indentation.get(1).offsetLeft - $indentation.get(0).offsetLeft;
       testRow.remove();
     }
@@ -249,8 +136,7 @@ function initTableDrag(table, base) {
     $(window).on('storage', $.proxy(function (e) {
       // Only react to 'Drupal.tableDrag.showWeight' value change.
       if (e.originalEvent.key === 'Drupal.tableDrag.showWeight') {
-        // This was changed in another window, get the new value for this
-        // window.
+        // This was changed in another window, get the new value for this window.
         showWeight = JSON.parse(e.originalEvent.newValue);
         this.displayColumns(showWeight);
       }
@@ -258,7 +144,8 @@ function initTableDrag(table, base) {
   };
 
   /**
-   * Initialize columns containing form elements to be hidden by default.
+   * Initialize columns containing form elements to be hidden by default,
+   * according to the settings for this tableDrag instance.
    *
    * Identify and mark each cell with a CSS class so we can easily toggle
    * show/hide it. Finally, hide columns if user does not have a
@@ -270,9 +157,7 @@ function initTableDrag(table, base) {
     var cell;
     var columnIndex;
     for (var group in this.tableSettings) {
-      if (this.tableSettings.hasOwnProperty(group)) {
-
-        // Find the first field in this group.
+      if (this.tableSettings.hasOwnProperty(group)) { // Find the first field in this group.
         for (var d in this.tableSettings[group]) {
           if (this.tableSettings[group].hasOwnProperty(d)) {
             var field = $table.find('.' + this.tableSettings[group][d].target).eq(0);
@@ -286,9 +171,8 @@ function initTableDrag(table, base) {
 
         // Mark the column containing this field so it can be hidden.
         if (hidden && cell[0]) {
-          // Add 1 to our indexes. The nth-child selector is 1 based, not 0
-          // based. Match immediate children of the parent element to allow
-          // nesting.
+          // Add 1 to our indexes. The nth-child selector is 1 based, not 0 based.
+          // Match immediate children of the parent element to allow nesting.
           columnIndex = cell.parent().find('> td').index(cell.get(0)) + 1;
           $table.find('> thead > tr, > tbody > tr, > tr').each(this.addColspanClass(columnIndex));
         }
@@ -298,13 +182,8 @@ function initTableDrag(table, base) {
   };
 
   /**
-   * Mark cells that have colspan.
-   *
-   * In order to adjust the colspan instead of hiding them altogether.
-   *
-   * @param {number} columnIndex
-   *
-   * @return {function}
+   * Mark cells that have colspan so we can adjust the colspan
+   * instead of hiding them altogether.
    */
   Drupal.tableDrag.prototype.addColspanClass = function (columnIndex) {
     return function () {
@@ -335,9 +214,7 @@ function initTableDrag(table, base) {
   /**
    * Hide or display weight columns. Triggers an event on change.
    *
-   * @fires event:columnschange
-   *
-   * @param {bool} displayWeight
+   * @param bool displayWeight
    *   'true' will show weight columns.
    */
   Drupal.tableDrag.prototype.displayColumns = function (displayWeight) {
@@ -355,7 +232,6 @@ function initTableDrag(table, base) {
 
   /**
    * Toggle the weight column depending on 'showWeight' value.
-   *
    * Store only default override.
    */
   Drupal.tableDrag.prototype.toggleColumns = function () {
@@ -373,7 +249,6 @@ function initTableDrag(table, base) {
 
   /**
    * Hide the columns containing weight/parent form elements.
-   *
    * Undo showColumns().
    */
   Drupal.tableDrag.prototype.hideColumns = function () {
@@ -391,8 +266,7 @@ function initTableDrag(table, base) {
   };
 
   /**
-   * Show the columns containing weight/parent form elements.
-   *
+   * Show the columns containing weight/parent form elements
    * Undo hideColumns().
    */
   Drupal.tableDrag.prototype.showColumns = function () {
@@ -411,11 +285,6 @@ function initTableDrag(table, base) {
 
   /**
    * Find the target used within a particular row and group.
-   *
-   * @param {string} group
-   * @param {HTMLElement} row
-   *
-   * @return {object}
    */
   Drupal.tableDrag.prototype.rowSettings = function (group, row) {
     var field = $(row).find('.' + group);
@@ -439,8 +308,6 @@ function initTableDrag(table, base) {
 
   /**
    * Take an item and add event handlers to make it become draggable.
-   *
-   * @param {HTMLElement} item
    */
   Drupal.tableDrag.prototype.makeDraggable = function (item) {
     var self = this;
@@ -457,7 +324,7 @@ function initTableDrag(table, base) {
       self.indentCount = Math.max($item.find('.js-indentation').length, self.indentCount);
     }
     else {
-      $item.find('td').eq(0).prepend(handle);
+      $item.find('td:first-of-type').prepend(handle);
     }
 
     if (Modernizr.touch) {
@@ -502,18 +369,13 @@ function initTableDrag(table, base) {
       var keyChange = false;
       var groupHeight;
       switch (event.keyCode) {
-        // Left arrow.
-        case 37:
-        // Safari left arrow.
-        case 63234:
+        case 37: // Left arrow.
+        case 63234: // Safari left arrow.
           keyChange = true;
           self.rowObject.indent(-1 * self.rtl);
           break;
-
-        // Up arrow.
-        case 38:
-        // Safari up arrow.
-        case 63232:
+        case 38: // Up arrow.
+        case 63232: // Safari up arrow.
           var $previousRow = $(self.rowObject.element).prev('tr:first-of-type');
           var previousRow = $previousRow.get(0);
           while (previousRow && $previousRow.is(':hidden')) {
@@ -521,8 +383,7 @@ function initTableDrag(table, base) {
             previousRow = $previousRow.get(0);
           }
           if (previousRow) {
-            // Do not allow the onBlur cleanup.
-            self.safeBlur = false;
+            self.safeBlur = false; // Do not allow the onBlur cleanup.
             self.rowObject.direction = 'up';
             keyChange = true;
 
@@ -541,30 +402,23 @@ function initTableDrag(table, base) {
               }
             }
             else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.draggable')) {
-              // Swap with the previous row (unless previous row is the first
-              // one and undraggable).
+              // Swap with the previous row (unless previous row is the first one
+              // and undraggable).
               self.rowObject.swap('before', previousRow);
               self.rowObject.interval = null;
               self.rowObject.indent(0);
               window.scrollBy(0, -parseInt(item.offsetHeight, 10));
             }
-            // Regain focus after the DOM manipulation.
-            handle.trigger('focus');
+            handle.trigger('focus'); // Regain focus after the DOM manipulation.
           }
           break;
-
-        // Right arrow.
-        case 39:
-        // Safari right arrow.
-        case 63235:
+        case 39: // Right arrow.
+        case 63235: // Safari right arrow.
           keyChange = true;
           self.rowObject.indent(self.rtl);
           break;
-
-        // Down arrow.
-        case 40:
-        // Safari down arrow.
-        case 63233:
+        case 40: // Down arrow.
+        case 63233: // Safari down arrow.
           var $nextRow = $(self.rowObject.group).eq(-1).next('tr:first-of-type');
           var nextRow = $nextRow.get(0);
           while (nextRow && $nextRow.is(':hidden')) {
@@ -572,8 +426,7 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
             nextRow = $nextRow.get(0);
           }
           if (nextRow) {
-            // Do not allow the onBlur cleanup.
-            self.safeBlur = false;
+            self.safeBlur = false; // Do not allow the onBlur cleanup.
             self.rowObject.direction = 'down';
             keyChange = true;
 
@@ -598,8 +451,7 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
               self.rowObject.indent(0);
               window.scrollBy(0, parseInt(item.offsetHeight, 10));
             }
-            // Regain focus after the DOM manipulation.
-            handle.trigger('focus');
+            handle.trigger('focus'); // Regain focus after the DOM manipulation.
           }
           break;
       }
@@ -622,20 +474,15 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
       }
     });
 
-    // Compatibility addition, return false on keypress to prevent unwanted
-    // scrolling. IE and Safari will suppress scrolling on keydown, but all
-    // other browsers need to return false on keypress.
-    // http://www.quirksmode.org/js/keys.html
+    // Compatibility addition, return false on keypress to prevent unwanted scrolling.
+    // IE and Safari will suppress scrolling on keydown, but all other browsers
+    // need to return false on keypress. http://www.quirksmode.org/js/keys.html
     handle.on('keypress', function (event) {
       switch (event.keyCode) {
-        // Left arrow.
-        case 37:
-        // Up arrow.
-        case 38:
-        // Right arrow.
-        case 39:
-        // Down arrow.
-        case 40:
+        case 37: // Left arrow.
+        case 38: // Up arrow.
+        case 39: // Right arrow.
+        case 40: // Down arrow.
           return false;
       }
     });
@@ -644,11 +491,11 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
   /**
    * Pointer event initiator, creates drag object and information.
    *
-   * @param {jQuery.Event} event
+   * @param jQuery.Event event
    *   The event object that trigger the drag.
-   * @param {Drupal.tableDrag} self
+   * @param Drupal.tableDrag self
    *   The drag handle.
-   * @param {HTMLElement} item
+   * @param DOM item
    *   The item that that is being dragged.
    */
   Drupal.tableDrag.prototype.dragStart = function (event, self, item) {
@@ -684,11 +531,6 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
 
   /**
    * Pointer movement handler, bound to document.
-   *
-   * @param {jQuery.Event} event
-   * @param {Drupal.tableDrag} self
-   *
-   * @return {bool|undefined}
    */
   Drupal.tableDrag.prototype.dragRow = function (event, self) {
     if (self.dragObject) {
@@ -699,8 +541,8 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
       // Check for row swapping and vertical scrolling.
       if (y !== self.oldY) {
         self.rowObject.direction = y > self.oldY ? 'down' : 'up';
-        // Update the old value.
-        self.oldY = y;
+        self.oldY = y; // Update the old value.
+
         // Check if the window should be scrolled (and how fast).
         var scrollAmount = self.checkScroll(self.currentPointerCoords.y);
         // Stop any current scrolling.
@@ -728,8 +570,7 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
       // Similar to row swapping, handle indentations.
       if (self.indentEnabled) {
         var xDiff = self.currentPointerCoords.x - self.dragObject.indentPointerPos.x;
-        // Set the number of indentations the pointer has been moved left or
-        // right.
+        // Set the number of indentations the pointer has been moved left or right.
         var indentDiff = Math.round(xDiff / self.indentAmount);
         // Indent the row with our estimated diff, which may be further
         // restricted according to the rows around this row.
@@ -745,9 +586,6 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
 
   /**
    * Pointerup behavior.
-   *
-   * @param {jQuery.Event} event
-   * @param {Drupal.tableDrag} self
    */
   Drupal.tableDrag.prototype.dropRow = function (event, self) {
     var droppedRow;
@@ -806,10 +644,6 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
 
   /**
    * Get the coordinates from the event (allowing for browser differences).
-   *
-   * @param {jQuery.Event} event
-   *
-   * @return {{x: number, y: number}}
    */
   Drupal.tableDrag.prototype.pointerCoords = function (event) {
     if (event.pageX || event.pageY) {
@@ -822,15 +656,8 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
   };
 
   /**
-   * Get the event offset from the target element.
-   *
    * Given a target element and a pointer event, get the event offset from that
    * element. To do this we need the element's position and the target position.
-   *
-   * @param {HTMLElement} target
-   * @param {jQuery.Event} event
-   *
-   * @return {{x: number, y: number}}
    */
   Drupal.tableDrag.prototype.getPointerOffset = function (target, event) {
     var docPos = $(target).offset();
@@ -839,16 +666,13 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
   };
 
   /**
-   * Find the row the mouse is currently over.
+   * Find the row the mouse is currently over. This row is then taken and swapped
+   * with the one being dragged.
    *
-   * This row is then taken and swapped with the one being dragged.
-   *
-   * @param {number} x
+   * @param x
    *   The x coordinate of the mouse on the page (not the screen).
-   * @param {number} y
+   * @param y
    *   The y coordinate of the mouse on the page (not the screen).
-   *
-   * @return {*}
    */
   Drupal.tableDrag.prototype.findDropTargetRow = function (x, y) {
     var rows = $(this.table.tBodies[0].rows).not(':hidden');
@@ -891,8 +715,8 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
         }
 
         // We may have found the row the mouse just passed over, but it doesn't
-        // take into account hidden rows. Skip backwards until we find a
-        // draggable row.
+        // take into account hidden rows. Skip backwards until we find a draggable
+        // row.
         while ($row.is(':hidden') && $row.prev('tr').is(':hidden')) {
           $row = $row.prev('tr:first-of-type');
           row = $row.get(0);
@@ -904,9 +728,10 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
   };
 
   /**
-   * After the row is dropped, update the table fields.
+   * After the row is dropped, update the table fields according to the settings
+   * set for this table.
    *
-   * @param {HTMLElement} changedRow
+   * @param changedRow
    *   DOM object for the row that was just dropped.
    */
   Drupal.tableDrag.prototype.updateFields = function (changedRow) {
@@ -920,11 +745,12 @@ else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.drag
   };
 
   /**
-   * After the row is dropped, update a single table field.
+   * After the row is dropped, update a single table field according to specific
+   * settings.
    *
-   * @param {HTMLElement} changedRow
+   * @param changedRow
    *   DOM object for the row that was just dropped.
-   * @param {string} group
+   * @param group
    *   The settings group on which field updates will occur.
    */
   Drupal.tableDrag.prototype.updateField = function (changedRow, group) {
@@ -1017,12 +843,10 @@ else if (rowSettings.relationship === 'parent') {
           // Get the depth of the target row.
           targetElement.value = $(sourceElement).closest('tr').find('.js-indentation').length;
           break;
-
         case 'match':
           // Update the value.
           targetElement.value = sourceElement.value;
           break;
-
         case 'order':
           var siblings = this.rowObject.findSiblings(rowSettings);
           if ($(targetElement).is('select')) {
@@ -1034,8 +858,7 @@ else if (rowSettings.relationship === 'parent') {
             var maxVal = values[values.length - 1];
             // Populate the values in the siblings.
             $(siblings).find(targetClass).each(function () {
-              // If there are more items than possible values, assign the
-              // maximum value to the row.
+              // If there are more items than possible values, assign the maximum value to the row.
               if (values.length > 0) {
                 this.value = values.shift();
               }
@@ -1058,15 +881,9 @@ else if (rowSettings.relationship === 'parent') {
   };
 
   /**
-   * Copy all tableDrag related classes from one row to another.
-   *
    * Copy all special tableDrag classes from one row's form elements to a
    * different one, removing any special classes that the destination row
    * may have had.
-   *
-   * @param {HTMLElement} sourceRow
-   * @param {HTMLElement} targetRow
-   * @param {string} group
    */
   Drupal.tableDrag.prototype.copyDragClasses = function (sourceRow, targetRow, group) {
     var sourceElement = $(sourceRow).find('.' + group);
@@ -1076,10 +893,6 @@ else if (rowSettings.relationship === 'parent') {
     }
   };
 
-  /**
-   * @param {number} cursorY
-   * @return {number}
-   */
   Drupal.tableDrag.prototype.checkScroll = function (cursorY) {
     var de = document.documentElement;
     var b = document.body;
@@ -1108,9 +921,6 @@ else if (cursorY - scrollY < trigger) {
     }
   };
 
-  /**
-   * @param {number} scrollAmount
-   */
   Drupal.tableDrag.prototype.setScroll = function (scrollAmount) {
     var self = this;
 
@@ -1125,9 +935,6 @@ else if (cursorY - scrollY < trigger) {
     }, this.scrollSettings.interval);
   };
 
-  /**
-   * Command to restripe table properly.
-   */
   Drupal.tableDrag.prototype.restripeTable = function () {
     // :even and :odd are reversed because jQuery counts from 0 and
     // we count from 1, so we're out of sync.
@@ -1140,8 +947,6 @@ else if (cursorY - scrollY < trigger) {
 
   /**
    * Stub function. Allows a custom handler when a row begins dragging.
-   *
-   * @return {?bool}
    */
   Drupal.tableDrag.prototype.onDrag = function () {
     return null;
@@ -1149,8 +954,6 @@ else if (cursorY - scrollY < trigger) {
 
   /**
    * Stub function. Allows a custom handler when a row is dropped.
-   *
-   * @return {?bool}
    */
   Drupal.tableDrag.prototype.onDrop = function () {
     return null;
@@ -1159,18 +962,16 @@ else if (cursorY - scrollY < trigger) {
   /**
    * Constructor to make a new object to manipulate a table row.
    *
-   * @param {HTMLElement} tableRow
+   * @param tableRow
    *   The DOM element for the table row we will be manipulating.
-   * @param {string} method
-   *   The method in which this row is being moved. Either 'keyboard' or
-   *   'mouse'.
-   * @param {bool} indentEnabled
+   * @param method
+   *   The method in which this row is being moved. Either 'keyboard' or 'mouse'.
+   * @param indentEnabled
    *   Whether the containing table uses indentations. Used for optimizations.
-   * @param {number} maxDepth
+   * @param maxDepth
    *   The maximum amount of indentations this row may contain.
-   * @param {bool} addClasses
-   *   Whether we want to add classes to this row to indicate child
-   *   relationships.
+   * @param addClasses
+   *   Whether we want to add classes to this row to indicate child relationships.
    */
   Drupal.tableDrag.prototype.row = function (tableRow, method, indentEnabled, maxDepth, addClasses) {
     var $tableRow = $(tableRow);
@@ -1183,8 +984,8 @@ else if (cursorY - scrollY < trigger) {
     this.table = $tableRow.closest('table')[0];
     this.indentEnabled = indentEnabled;
     this.maxDepth = maxDepth;
-    // Direction the row is being moved.
-    this.direction = '';
+    this.direction = ''; // Direction the row is being moved.
+
     if (this.indentEnabled) {
       this.indents = $tableRow.find('.js-indentation').length;
       this.children = this.findChildren(addClasses);
@@ -1199,11 +1000,8 @@ else if (cursorY - scrollY < trigger) {
   /**
    * Find all children of rowObject by indentation.
    *
-   * @param {bool} addClasses
-   *   Whether we want to add classes to this row to indicate child
-   *   relationships.
-   *
-   * @return {Array}
+   * @param addClasses
+   *   Whether we want to add classes to this row to indicate child relationships.
    */
   Drupal.tableDrag.prototype.row.prototype.findChildren = function (addClasses) {
     var parentIndentation = this.indents;
@@ -1211,7 +1009,7 @@ else if (cursorY - scrollY < trigger) {
     var rows = [];
     var child = 0;
 
-    function rowIndentation(indentNum, el) {
+    function rowIndentation(el, indentNum) {
       var self = $(el);
       if (child === 1 && (indentNum === parentIndentation)) {
         self.addClass('tree-child-first');
@@ -1247,10 +1045,8 @@ else if (indentNum > parentIndentation) {
   /**
    * Ensure that two rows are allowed to be swapped.
    *
-   * @param {HTMLElement} row
+   * @param row
    *   DOM object for the row being considered for swapping.
-   *
-   * @return {bool}
    */
   Drupal.tableDrag.prototype.row.prototype.isValidSwap = function (row) {
     var $row = $(row);
@@ -1284,9 +1080,9 @@ else if (indentNum > parentIndentation) {
   /**
    * Perform the swap between two rows.
    *
-   * @param {string} position
+   * @param position
    *   Whether the swap will occur 'before' or 'after' the given row.
-   * @param {HTMLElement} row
+   * @param row
    *   DOM element what will be swapped with the row group.
    */
   Drupal.tableDrag.prototype.row.prototype.swap = function (position, row) {
@@ -1304,16 +1100,15 @@ else if (indentNum > parentIndentation) {
   };
 
   /**
-   * Determine the valid indentations interval for the row at a given position.
+   * Determine the valid indentations interval for the row at a given position
+   * in the table.
    *
-   * @param {?HTMLElement} prevRow
+   * @param prevRow
    *   DOM object for the row before the tested position
    *   (or null for first position in the table).
-   * @param {?HTMLElement} nextRow
+   * @param nextRow
    *   DOM object for the row after the tested position
    *   (or null for last position in the table).
-   *
-   * @return {{min: number, max: number}}
    */
   Drupal.tableDrag.prototype.row.prototype.validIndentInterval = function (prevRow, nextRow) {
     var $prevRow = $(prevRow);
@@ -1347,12 +1142,10 @@ else if (indentNum > parentIndentation) {
   /**
    * Indent a row within the legal bounds of the table.
    *
-   * @param {number} indentDiff
+   * @param indentDiff
    *   The number of additional indentations proposed for the row (can be
    *   positive or negative). This number will be adjusted to nearest valid
    *   indentation level for the row.
-   *
-   * @return {number}
    */
   Drupal.tableDrag.prototype.row.prototype.indent = function (indentDiff) {
     var $group = $(this.group);
@@ -1391,15 +1184,11 @@ else if (indentNum > parentIndentation) {
   };
 
   /**
-   * Find all siblings for a row.
+   * Find all siblings for a row, either according to its subgroup or indentation.
+   * Note that the passed-in row is included in the list of siblings.
    *
-   * According to its subgroup or indentation. Note that the passed-in row is
-   * included in the list of siblings.
-   *
-   * @param {object} rowSettings
+   * @param settings
    *   The field settings we're using to identify what constitutes a sibling.
-   *
-   * @return {Array}
    */
   Drupal.tableDrag.prototype.row.prototype.findSiblings = function (rowSettings) {
     var siblings = [];
@@ -1468,8 +1257,6 @@ else if (checkRowIndentation < rowIndentation) {
 
   /**
    * Stub function. Allows a custom handler when a row is indented.
-   *
-   * @return {?bool}
    */
   Drupal.tableDrag.prototype.row.prototype.onIndent = function () {
     return null;
@@ -1477,34 +1264,18 @@ else if (checkRowIndentation < rowIndentation) {
 
   /**
    * Stub function. Allows a custom handler when a row is swapped.
-   *
-   * @param {HTMLElement} swappedRow
-   *
-   * @return {?bool}
    */
   Drupal.tableDrag.prototype.row.prototype.onSwap = function (swappedRow) {
     return null;
   };
 
-  $.extend(Drupal.theme, /** @lends Drupal.theme */{
-
-    /**
-     * @return {string}
-     */
+  $.extend(Drupal.theme, {
     tableDragChangedMarker: function () {
       return '<abbr class="warning tabledrag-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
     },
-
-    /**
-     * @return {string}
-     */
     tableDragIndentation: function () {
       return '<div class="js-indentation indentation">&nbsp;</div>';
     },
-
-    /**
-     * @return {string}
-     */
     tableDragChangedWarning: function () {
       return '<div class="tabledrag-changed-warning messages messages--warning" role="alert">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('You have unsaved changes.') + '</div>';
     }
diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
index fbdb33c..2d6ce16 100644
--- a/core/misc/tableheader.js
+++ b/core/misc/tableheader.js
@@ -1,16 +1,9 @@
-/**
- * @file
- * Sticky table headers.
- */
-
 (function ($, Drupal, displace) {
 
   "use strict";
 
   /**
    * Attaches sticky table headers.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.tableHeader = {
     attach: function (context) {
@@ -55,36 +48,26 @@ function tableHeaderOffsetChangeHandler(e, offsets) {
 
   // Bind event that need to change all tables.
   $(window).on({
-
     /**
      * When resizing table width can change, recalculate everything.
-     *
-     * @ignore
      */
     'resize.TableHeader': tableHeaderResizeHandler,
 
     /**
      * Bind only one event to take care of calling all scroll callbacks.
-     *
-     * @ignore
      */
     'scroll.TableHeader': tableHeaderOnScrollHandler
   });
   // Bind to custom Drupal events.
   $(document).on({
-
     /**
      * Recalculate columns width when window is resized and when show/hide
      * weight is triggered.
-     *
-     * @ignore
      */
     'columnschange.TableHeader': tableHeaderResizeHandler,
 
     /**
-     * Recalculate TableHeader.topOffset when viewport is resized.
-     *
-     * @ignore
+     * Recalculate TableHeader.topOffset when viewport is resized
      */
     'drupalViewportOffsetChange.TableHeader': tableHeaderOffsetChangeHandler
   });
@@ -95,37 +78,19 @@ function tableHeaderOffsetChangeHandler(e, offsets) {
    * TableHeader will make the current table header stick to the top of the page
    * if the table is very long.
    *
-   * @constructor Drupal.TableHeader
-   *
-   * @param {HTMLElement} table
+   * @param table
    *   DOM object for the table to add a sticky header to.
    *
-   * @listens event:columnschange
+   * @constructor
    */
   function TableHeader(table) {
     var $table = $(table);
 
-    /**
-     * @name Drupal.TableHeader#$originalTable
-     *
-     * @type {HTMLElement}
-     */
     this.$originalTable = $table;
-
-    /**
-     * @type {jQuery}
-     */
     this.$originalHeader = $table.children('thead');
-
-    /**
-     * @type {jQuery}
-     */
     this.$originalHeaderCells = this.$originalHeader.find('> tr > th');
-
-    /**
-     * @type {null|bool}
-     */
     this.displayWeight = null;
+
     this.$originalTable.addClass('sticky-table');
     this.tableHeight = $table[0].clientHeight;
     this.tableOffset = this.$originalTable.offset();
@@ -146,12 +111,11 @@ function TableHeader(table) {
   /**
    * Store the state of TableHeader.
    */
-  $.extend(TableHeader, /** @lends Drupal.TableHeader */{
-
+  $.extend(TableHeader, {
     /**
      * This will store the state of all processed tables.
      *
-     * @type {Array.<Drupal.TableHeader>}
+     * @type {Array}
      */
     tables: []
   });
@@ -159,33 +123,24 @@ function TableHeader(table) {
   /**
    * Extend TableHeader prototype.
    */
-  $.extend(TableHeader.prototype, /** @lends Drupal.TableHeader# */{
-
+  $.extend(TableHeader.prototype, {
     /**
      * Minimum height in pixels for the table to have a sticky header.
-     *
-     * @type {number}
      */
     minHeight: 100,
 
     /**
      * Absolute position of the table on the page.
-     *
-     * @type {?Drupal~displaceOffset}
      */
     tableOffset: null,
 
     /**
      * Absolute position of the table on the page.
-     *
-     * @type {?number}
      */
     tableHeight: null,
 
     /**
      * Boolean storing the sticky header visibility state.
-     *
-     * @type {bool}
      */
     stickyVisible: false,
 
@@ -214,10 +169,8 @@ function TableHeader(table) {
     /**
      * Set absolute position of sticky.
      *
-     * @param {number} offsetTop
-     * @param {number} offsetLeft
-     *
-     * @return {jQuery}
+     * @param offsetTop
+     * @param offsetLeft
      */
     stickyPosition: function (offsetTop, offsetLeft) {
       var css = {};
@@ -232,8 +185,6 @@ function TableHeader(table) {
 
     /**
      * Returns true if sticky is currently visible.
-     *
-     * @return {bool}
      */
     checkStickyVisible: function () {
       var scrollTop = scrollValue('scrollTop');
@@ -252,10 +203,9 @@ function TableHeader(table) {
     /**
      * Check if sticky header should be displayed.
      *
-     * This function is throttled to once every 250ms to avoid unnecessary
-     * calls.
+     * This function is throttled to once every 250ms to avoid unnecessary calls.
      *
-     * @param {jQuery.Event} e
+     * @param event
      */
     onScroll: function (e) {
       this.checkStickyVisible();
@@ -267,7 +217,7 @@ function TableHeader(table) {
     /**
      * Event handler: recalculates position of the sticky table header.
      *
-     * @param {jQuery.Event} event
+     * @param event
      *   Event being triggered.
      */
     recalculateSticky: function (event) {
diff --git a/core/misc/tableresponsive.js b/core/misc/tableresponsive.js
index f2ebd18..b4eab62 100644
--- a/core/misc/tableresponsive.js
+++ b/core/misc/tableresponsive.js
@@ -1,16 +1,9 @@
-/**
- * @file
- * Responsive table functionality.
- */
-
 (function ($, Drupal, window) {
 
   "use strict";
 
   /**
-   * Attach the tableResponsive function to {@link Drupal.behaviors}.
-   *
-   * @type {Drupal~behavior}
+   * Attach the tableResponsive function to Drupal.behaviors.
    */
   Drupal.behaviors.tableResponsive = {
     attach: function (context, settings) {
@@ -25,18 +18,14 @@
   };
 
   /**
-   * The TableResponsive object optimizes table presentation for screen size.
+   * The TableResponsive object optimizes table presentation for all screen sizes.
    *
    * A responsive table hides columns at small screen sizes, leaving the most
-   * important columns visible to the end user. Users should not be prevented
-   * from accessing all columns, however. This class adds a toggle to a table
-   * with hidden columns that exposes the columns. Exposing the columns will
-   * likely break layouts, but it provides the user with a means to access
-   * data, which is a guiding principle of responsive design.
-   *
-   * @constructor Drupal.TableResponsive
-   *
-   * @param {HTMLElement} table
+   * important columns visible to the end user. Users should not be prevented from
+   * accessing all columns, however. This class adds a toggle to a table with
+   * hidden columns that exposes the columns. Exposing the columns will likely
+   * break layouts, but it provides the user with a means to access data, which
+   * is a guiding principle of responsive design.
    */
   function TableResponsive(table) {
     this.table = table;
@@ -62,13 +51,7 @@ function TableResponsive(table) {
   /**
    * Extend the TableResponsive function with a list of managed tables.
    */
-  $.extend(TableResponsive, /** @lends Drupal.TableResponsive */{
-
-    /**
-     * Store all created instances.
-     *
-     * @type {Array.<Drupal.TableResponsive>}
-     */
+  $.extend(TableResponsive, {
     tables: []
   });
 
@@ -78,34 +61,24 @@ function TableResponsive(table) {
    * Columns are assumed to be hidden if their header has the class priority-low
    * or priority-medium.
    */
-  $.extend(TableResponsive.prototype, /** @lends Drupal.TableResponsive# */{
-
-    /**
-     * @param {jQuery.Event} e
-     */
+  $.extend(TableResponsive.prototype, {
     eventhandlerEvaluateColumnVisibility: function (e) {
       var pegged = parseInt(this.$link.data('pegged'), 10);
       var hiddenLength = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden').length;
-      // If the table has hidden columns, associate an action link with the
-      // table to show the columns.
+      // If the table has hidden columns, associate an action link with the table
+      // to show the columns.
       if (hiddenLength > 0) {
         this.$link.show().text(this.showText);
       }
       // When the toggle is pegged, its presence is maintained because the user
-      // has interacted with it. This is necessary to keep the link visible if
-      // the user adjusts screen size and changes the visibility of columns.
+      // has interacted with it. This is necessary to keep the link visible if the
+      // user adjusts screen size and changes the visibility of columns.
       if (!pegged && hiddenLength === 0) {
         this.$link.hide().text(this.hideText);
       }
     },
-
-    /**
-     * Toggle the visibility of columns based on their priority.
-     *
-     * Columns are classed with either 'priority-low' or 'priority-medium'.
-     *
-     * @param {jQuery.Event} e
-     */
+    // Toggle the visibility of columns classed with either 'priority-low' or
+    // 'priority-medium'.
     eventhandlerToggleColumns: function (e) {
       e.preventDefault();
       var self = this;
@@ -137,10 +110,10 @@ function TableResponsive(table) {
           var $cell = $(this);
           var properties = $cell.attr('style').split(';');
           var newProps = [];
-          // The hide method adds display none to the element. The element
-          // should be returned to the same state it was in before the columns
-          // were revealed, so it is necessary to remove the display none value
-          // from the style attribute.
+          // The hide method adds display none to the element. The element should
+          // be returned to the same state it was in before the columns were
+          // revealed, so it is necessary to remove the display none
+          // value from the style attribute.
           var match = /^display\s*\:\s*none$/;
           for (var i = 0; i < properties.length; i++) {
             var prop = properties[i];
@@ -161,7 +134,6 @@ function TableResponsive(table) {
       }
     }
   });
-
   // Make the TableResponsive object available in the Drupal namespace.
   Drupal.TableResponsive = TableResponsive;
 
diff --git a/core/misc/tableselect.js b/core/misc/tableselect.js
index fc8e9f2..78e8c90 100644
--- a/core/misc/tableselect.js
+++ b/core/misc/tableselect.js
@@ -1,17 +1,7 @@
-/**
- * @file
- * Table select functionality.
- */
-
 (function ($, Drupal) {
 
   "use strict";
 
-  /**
-   * Initialize tableSelects.
-   *
-   * @type {Drupal~behavior}
-   */
   Drupal.behaviors.tableSelect = {
     attach: function (context, settings) {
       // Select the inner-most table in case of nested tables.
@@ -19,18 +9,13 @@
     }
   };
 
-  /**
-   * Callback used in {@link Drupal.behaviors.tableSelect}.
-   */
   Drupal.tableSelect = function () {
-    // Do not add a "Select all" checkbox if there are no rows with checkboxes
-    // in the table.
+    // Do not add a "Select all" checkbox if there are no rows with checkboxes in the table
     if ($(this).find('td input[type="checkbox"]').length === 0) {
       return;
     }
 
-    // Keep track of the table, which checkbox is checked and alias the
-    // settings.
+    // Keep track of the table, which checkbox is checked and alias the settings.
     var table = this;
     var checkboxes;
     var lastChecked;
@@ -40,10 +25,6 @@
       // Update table's select-all checkbox (and sticky header's if available).
       $table.prev('table.sticky-header').addBack().find('th.select-all input[type="checkbox"]').each(function () {
         $(this).attr('title', state ? strings.selectNone : strings.selectAll);
-
-        /**
-         * @this {HTMLElement}
-         */
         this.checked = state;
       });
     };
@@ -51,20 +32,10 @@
     // Find all <th> with class select-all, and insert the check all checkbox.
     $table.find('th.select-all').prepend($('<input type="checkbox" class="form-checkbox" />').attr('title', strings.selectAll)).on('click', function (event) {
       if ($(event.target).is('input[type="checkbox"]')) {
-        // Loop through all checkboxes and set their state to the select all
-        // checkbox' state.
+        // Loop through all checkboxes and set their state to the select all checkbox' state.
         checkboxes.each(function () {
-
-          /**
-           * @this {HTMLElement}
-           */
           this.checked = event.target.checked;
-          // Either add or remove the selected class based on the state of the
-          // check all checkbox.
-
-          /**
-           * @this {HTMLElement}
-           */
+          // Either add or remove the selected class based on the state of the check all checkbox.
           $(this).closest('tr').toggleClass('selected', this.checked);
         });
         // Update the title and the state of the check all box.
@@ -74,24 +45,18 @@
 
     // For each of the checkboxes within the table that are not disabled.
     checkboxes = $table.find('td input[type="checkbox"]:enabled').on('click', function (e) {
-      // Either add or remove the selected class based on the state of the
-      // check all checkbox.
-
-      /**
-       * @this {HTMLElement}
-       */
+      // Either add or remove the selected class based on the state of the check all checkbox.
       $(this).closest('tr').toggleClass('selected', this.checked);
 
-      // If this is a shift click, we need to highlight everything in the
-      // range. Also make sure that we are actually checking checkboxes
-      // over a range and that a checkbox has been checked or unchecked before.
+      // If this is a shift click, we need to highlight everything in the range.
+      // Also make sure that we are actually checking checkboxes over a range and
+      // that a checkbox has been checked or unchecked before.
       if (e.shiftKey && lastChecked && lastChecked !== e.target) {
         // We use the checkbox's parent TR to do our range searching.
         Drupal.tableSelectRange($(e.target).closest('tr')[0], $(lastChecked).closest('tr')[0], e.target.checked);
       }
 
-      // If all checkboxes are checked, make sure the select-all one is checked
-      // too, otherwise keep unchecked.
+      // If all checkboxes are checked, make sure the select-all one is checked too, otherwise keep unchecked.
       updateSelectAll((checkboxes.length === checkboxes.filter(':checked').length));
 
       // Keep track of the last checked checkbox.
@@ -103,11 +68,6 @@
     updateSelectAll((checkboxes.length === checkboxes.filter(':checked').length));
   };
 
-  /**
-   * @param {HTMLElement} from
-   * @param {HTMLElement} to
-   * @param {bool} state
-   */
   Drupal.tableSelectRange = function (from, to, state) {
     // We determine the looping mode based on the order of from and to.
     var mode = from.rowIndex > to.rowIndex ? 'previousSibling' : 'nextSibling';
@@ -120,8 +80,7 @@
         continue;
       }
       $i = $(i);
-      // Either add or remove the selected class based on the state of the
-      // target checkbox.
+      // Either add or remove the selected class based on the state of the target checkbox.
       $i.toggleClass('selected', state);
       $i.find('input[type="checkbox"]').prop('checked', state);
 
diff --git a/core/misc/timezone.js b/core/misc/timezone.js
index 801d728..e7667b8 100644
--- a/core/misc/timezone.js
+++ b/core/misc/timezone.js
@@ -1,16 +1,9 @@
-/**
- * @file
- * Timezone detection.
- */
-
 (function ($) {
 
   "use strict";
 
   /**
    * Set the client's system time zone as default values of form fields.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.setTimezone = {
     attach: function (context, settings) {
@@ -52,11 +45,10 @@ else if (Math.max(offsetJan, offsetJul) === offsetNow) {
           isDaylightSavingTime = 0;
         }
 
-        // Submit request to the system/timezone callback and set the form
-        // field to the response time zone. The client date is passed to the
-        // callback for debugging purposes. Submit a synchronous request to
-        // avoid database errors associated with concurrent requests
-        // during install.
+        // Submit request to the system/timezone callback and set the form field
+        // to the response time zone. The client date is passed to the callback
+        // for debugging purposes. Submit a synchronous request to avoid database
+        // errors associated with concurrent requests during install.
         var path = 'system/timezone/' + abbreviation + '/' + offsetNow + '/' + isDaylightSavingTime;
         $.ajax({
           async: false,
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index a381bdc..e7f64dc 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -1,31 +1,17 @@
-/**
- * @file
- * Define vertical tabs functionality.
- */
-
-/**
- * Triggers when form values inside a vertical tab changes.
- *
- * This is used to update the summary in vertical tabs in order to know what
- * are the important fields' values.
- *
- * @event summaryUpdated
- */
-
 (function ($) {
 
   "use strict";
 
   /**
-   * This script transforms a set of details into a stack of vertical tabs.
+   * This script transforms a set of details into a stack of vertical
+   * tabs. Another tab pane can be selected by clicking on the respective
+   * tab.
    *
    * Each tab may have a summary which can be updated by another
    * script. For that to work, each details element has an associated
    * 'verticalTabCallback' (with jQuery.data() attached to the details),
    * which is called every time the user performs an update to a form
    * element inside the tab pane.
-   *
-   * @type {Drupal~behavior}
    */
   Drupal.behaviors.verticalTabs = {
     attach: function (context) {
@@ -39,8 +25,7 @@
         var focusID = $this.find(':hidden.vertical-tabs__active-tab').val();
         var tab_focus;
 
-        // Check if there are some details that can be converted to
-        // vertical-tabs.
+        // Check if there are some details that can be converted to vertical-tabs
         var $details = $this.find('> details');
         if ($details.length === 0) {
           return;
@@ -94,17 +79,10 @@
   /**
    * The vertical tab object represents a single tab within a tab group.
    *
-   * @constructor
-   *
-   * @param {object} settings
-   * @param {string} settings.title
-   *   The name of the tab.
-   * @param {jQuery} settings.details
-   *   The jQuery object of the details element that is the tab pane.
-   *
-   * @fires event:summaryUpdated
-   *
-   * @listens event:summaryUpdated
+   * @param settings
+   *   An object with the following keys:
+   *   - title: The name of the tab.
+   *   - details: The jQuery object of the details element that is the tab pane.
    */
   Drupal.verticalTab = function (settings) {
     var self = this;
@@ -136,7 +114,6 @@
   };
 
   Drupal.verticalTab.prototype = {
-
     /**
      * Displays the tab's content pane.
      */
@@ -167,17 +144,15 @@
 
     /**
      * Shows a vertical tab pane.
-     *
-     * @return {Drupal.verticalTab}
      */
     tabShow: function () {
       // Display the tab.
       this.item.show();
       // Show the vertical tabs.
       this.item.closest('.js-form-type-vertical-tabs').show();
-      // Update .first marker for items. We need recurse from parent to retain
-      // the actual DOM element order as jQuery implements sortOrder, but not
-      // as public method.
+      // Update .first marker for items. We need recurse from parent to retain the
+      // actual DOM element order as jQuery implements sortOrder, but not as public
+      // method.
       this.item.parent().children('.vertical-tabs__menu-item').removeClass('first')
         .filter(':visible').eq(0).addClass('first');
       // Display the details element.
@@ -189,15 +164,13 @@
 
     /**
      * Hides a vertical tab pane.
-     *
-     * @return {Drupal.verticalTab}
      */
     tabHide: function () {
       // Hide this tab.
       this.item.hide();
-      // Update .first marker for items. We need recurse from parent to retain
-      // the actual DOM element order as jQuery implements sortOrder, but not
-      // as public method.
+      // Update .first marker for items. We need recurse from parent to retain the
+      // actual DOM element order as jQuery implements sortOrder, but not as public
+      // method.
       this.item.parent().children('.vertical-tabs__menu-item').removeClass('first')
         .filter(':visible').eq(0).addClass('first');
       // Hide the details element.
@@ -218,12 +191,10 @@
   /**
    * Theme function for a vertical tab.
    *
-   * @param {object} settings
+   * @param settings
    *   An object with the following keys:
-   * @param {string} settings.title
-   *   The name of the tab.
-   *
-   * @return {object}
+   *   - title: The name of the tab.
+   * @return
    *   This function has to return an object with at least these keys:
    *   - item: The root tab jQuery element
    *   - link: The anchor tag that acts as the clickable area of the tab
diff --git a/core/modules/action/tests/action_bulk_test/config/install/views.view.test_bulk_form.yml b/core/modules/action/tests/action_bulk_test/config/install/views.view.test_bulk_form.yml
index 8ea6534..6727525 100644
--- a/core/modules/action/tests/action_bulk_test/config/install/views.view.test_bulk_form.yml
+++ b/core/modules/action/tests/action_bulk_test/config/install/views.view.test_bulk_form.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/aggregator/config/optional/views.view.aggregator_rss_feed.yml b/core/modules/aggregator/config/optional/views.view.aggregator_rss_feed.yml
index a3c0b71..bfc7abf 100644
--- a/core/modules/aggregator/config/optional/views.view.aggregator_rss_feed.yml
+++ b/core/modules/aggregator/config/optional/views.view.aggregator_rss_feed.yml
@@ -23,7 +23,7 @@ display:
         options:
           perm: 'access news feeds'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/aggregator/config/optional/views.view.aggregator_sources.yml b/core/modules/aggregator/config/optional/views.view.aggregator_sources.yml
index cccd45b..bacfa46 100644
--- a/core/modules/aggregator/config/optional/views.view.aggregator_sources.yml
+++ b/core/modules/aggregator/config/optional/views.view.aggregator_sources.yml
@@ -27,7 +27,7 @@ display:
         options:
           perm: 'access news feeds'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/aggregator/src/Controller/AggregatorController.php b/core/modules/aggregator/src/Controller/AggregatorController.php
index eaa82e5..303b43c 100644
--- a/core/modules/aggregator/src/Controller/AggregatorController.php
+++ b/core/modules/aggregator/src/Controller/AggregatorController.php
@@ -127,8 +127,8 @@ public function adminOverview() {
       $row[] = $this->formatPlural($entity_manager->getStorage('aggregator_item')->getItemCount($feed), '1 item', '@count items');
       $last_checked = $feed->getLastCheckedTime();
       $refresh_rate = $feed->getRefreshRate();
-      $row[] = ($last_checked ? $this->t('@time ago', array('@time' => $this->dateFormatter->formatTimeDiffSince($last_checked))) : $this->t('never'));
-      $row[] = ($last_checked && $refresh_rate ? $this->t('@time left', array('@time' => $this->dateFormatter->formatTimeDiffUntil($last_checked + $refresh_rate))) : $this->t('never'));
+      $row[] = ($last_checked ? $this->t('@time ago', array('@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $last_checked))) : $this->t('never'));
+      $row[] = ($last_checked && $refresh_rate ? $this->t('%time left', array('%time' => $this->dateFormatter->formatInterval($last_checked + $refresh_rate - REQUEST_TIME))) : $this->t('never'));
       $links['edit'] = [
         'title' => $this->t('Edit'),
         'url' => Url::fromRoute('entity.aggregator_feed.edit_form', ['aggregator_feed' => $feed->id()]),
diff --git a/core/modules/aggregator/src/Plugin/views/row/Rss.php b/core/modules/aggregator/src/Plugin/views/row/Rss.php
index b34bb8f..72410e5 100644
--- a/core/modules/aggregator/src/Plugin/views/row/Rss.php
+++ b/core/modules/aggregator/src/Plugin/views/row/Rss.php
@@ -79,7 +79,7 @@ public function render($row) {
       '#options' => $this->options,
       '#row' => $item,
     );
-    return $build;
+    return drupal_render_root($build);
   }
 
 }
diff --git a/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml b/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml
index 281cdde..690a03a 100644
--- a/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml
+++ b/core/modules/aggregator/tests/modules/aggregator_test_views/test_views/views.view.test_aggregator_items.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php
index ac9406a..1aefa68 100644
--- a/core/modules/block/src/BlockForm.php
+++ b/core/modules/block/src/BlockForm.php
@@ -385,7 +385,7 @@ public function getUniqueMachineName(BlockInterface $block) {
     }, $block_ids);
 
     // Iterate through potential IDs until we get a new one. E.g.
-    // 'plugin', 'plugin_2', 'plugin_3', etc.
+    // 'plugin', 'plugin_2', 'plugin_3'...
     $count = 1;
     $machine_default = $suggestion;
     while (in_array($machine_default, $block_ids)) {
diff --git a/core/modules/block/src/BlockRepository.php b/core/modules/block/src/BlockRepository.php
index 980e0ad..485a66f 100644
--- a/core/modules/block/src/BlockRepository.php
+++ b/core/modules/block/src/BlockRepository.php
@@ -47,15 +47,34 @@ public function __construct(EntityManagerInterface $entity_manager, ThemeManager
   }
 
   /**
+   * Returns the human-readable list of regions keyed by machine name.
+   *
+   * @return array
+   *   An array of human-readable region names keyed by machine name.
+   */
+  protected function getRegionNames() {
+    return system_region_list($this->getTheme());
+  }
+
+  /**
+   * Gets the current theme for this page.
+   *
+   * @return string
+   *   The current theme.
+   */
+  protected function getTheme() {
+    return $this->themeManager->getActiveTheme()->getName();
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getVisibleBlocksPerRegion(array $contexts) {
-    $active_theme = $this->themeManager->getActiveTheme();
     // Build an array of the region names in the right order.
-    $empty = array_fill_keys($active_theme->getRegions(), array());
+    $empty = array_fill_keys(array_keys($this->getRegionNames()), array());
 
     $full = array();
-    foreach ($this->blockStorage->loadByProperties(array('theme' => $active_theme->getName())) as $block_id => $block) {
+    foreach ($this->blockStorage->loadByProperties(array('theme' => $this->getTheme())) as $block_id => $block) {
       /** @var \Drupal\block\BlockInterface $block */
       // Set the contexts on the block before checking access.
       if ($block->setContexts($contexts)->access('view')) {
diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
index 3f96ab1..56e7354 100644
--- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
@@ -285,7 +285,7 @@ public function testBlockContextualLinks() {
     // Get server-rendered contextual links.
     // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks()
     $post = array('ids[0]' => $id, 'ids[1]' => $cached_id);
-    $response = $this->drupalPostWithFormat('contextual/render', 'json', $post, array('query' => array('destination' => 'test-page')));
+    $response = $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => 'test-page')));
     $this->assertResponse(200);
     $json = Json::decode($response);
     $this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
diff --git a/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block.yml b/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block.yml
index d540aee..d0e4771 100644
--- a/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block.yml
+++ b/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block2.yml b/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block2.yml
index 97ed6fb..1a79010 100644
--- a/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block2.yml
+++ b/core/modules/block/tests/modules/block_test_views/test_views/views.view.test_view_block2.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php
index 56b90ca..f589e82 100644
--- a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php
+++ b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Tests\block\Unit;
 
-use Drupal\block\BlockRepository;
 use Drupal\Core\Block\BlockPluginInterface;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
 use Drupal\Tests\UnitTestCase;
@@ -50,13 +49,6 @@ protected function setUp() {
     $active_theme->expects($this->atLeastOnce())
       ->method('getName')
       ->willReturn($this->theme);
-    $active_theme->expects($this->atLeastOnce())
-      ->method('getRegions')
-      ->willReturn([
-        'top',
-        'center',
-        'bottom',
-      ]);
 
     $theme_manager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
     $theme_manager->expects($this->once())
@@ -70,7 +62,17 @@ protected function setUp() {
       ->method('getStorage')
       ->willReturn($this->blockStorage);
 
-    $this->blockRepository = new BlockRepository($entity_manager, $theme_manager, $this->contextHandler);
+    $this->blockRepository = $this->getMockBuilder('Drupal\block\BlockRepository')
+      ->setConstructorArgs([$entity_manager, $theme_manager, $this->contextHandler])
+      ->setMethods(['getRegionNames'])
+      ->getMock();
+    $this->blockRepository->expects($this->once())
+      ->method('getRegionNames')
+      ->willReturn([
+        'top' => 'Top',
+        'center' => 'Center',
+        'bottom' => 'Bottom',
+      ]);
   }
 
   /**
diff --git a/core/modules/block_content/config/optional/views.view.block_content.yml b/core/modules/block_content/config/optional/views.view.block_content.yml
index ad5e1f9..7c2bba8 100644
--- a/core/modules/block_content/config/optional/views.view.block_content.yml
+++ b/core/modules/block_content/config/optional/views.view.block_content.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'administer blocks'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml
index e5c2d9b..cbd4511 100644
--- a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml
+++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml
index 45eb3af..52c52a5 100644
--- a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index f7ee374..c8a43c7 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -19,6 +19,7 @@
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Template\Attribute;
+use Drupal\Core\Extension\Extension;
 
 /**
  * Implements hook_help().
@@ -62,7 +63,11 @@ function book_theme() {
       'variables' => array('book_link' => NULL),
     ),
     'book_tree' => array(
-      'variables' => array('items' => array(), 'attributes' => array()),
+      'render element' => 'tree',
+    ),
+    'book_link' => array(
+      'render element' => 'element',
+      'function' => 'theme_book_link',
     ),
     'book_export_html' => array(
       'variables' => array('title' => NULL, 'contents' => NULL, 'depth' => NULL),
@@ -495,6 +500,37 @@ function template_preprocess_book_node_export_html(&$variables) {
 }
 
 /**
+ * Implements template_preprocess_HOOK() for book-tree.html.twig.
+ */
+function template_preprocess_book_tree(&$variables) {
+  $variables['tree'] = $variables['tree']['#children'];
+}
+
+/**
+ * Returns HTML for a book link and subtree.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - element: Structured array data for a book link.
+ *
+ * @ingroup themeable
+ */
+function theme_book_link(array $variables) {
+  $element = $variables['element'];
+  $sub_menu = '';
+
+  if ($element['#below']) {
+    $sub_menu = drupal_render($element['#below']);
+  }
+  $element['#localized_options']['set_active_class'] = TRUE;
+  /** @var \Drupal\Core\Url $url */
+  $url = $element['#url'];
+  $url->setOptions($element['#localized_options'] + $url->getOptions());
+  $output = \Drupal::l($element['#title'], $url);
+  return '<li' . new Attribute($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
+}
+
+/**
  * Determines if a given node type is in the list of types allowed for books.
  *
  * @param string $type
@@ -535,3 +571,33 @@ function book_node_type_update(NodeTypeInterface $type) {
     $config->save();
   }
 }
+
+/**
+ * Implements hook_system_info_alter().
+ *
+ * Prevents book module from being uninstalled whilst any book nodes exist or
+ * there are any book outline stored.
+ */
+function book_system_info_alter(&$info, Extension $file, $type) {
+  // It is not safe use the entity query service during maintenance mode.
+  if ($type == 'module' && !defined('MAINTENANCE_MODE') && $file->getName() == 'book') {
+    if (\Drupal::service('book.outline_storage')->hasBooks()) {
+      $info['required'] = TRUE;
+      $info['explanation'] = t('To uninstall Book, delete all content that is part of a book.');
+    }
+    else {
+      // The book node type is provided by the Book module. Prevent uninstall if
+      // there are any nodes of that type.
+      $factory = \Drupal::service('entity.query');
+      $nodes = $factory->get('node')
+        ->condition('type', 'book')
+        ->accessCheck(FALSE)
+        ->range(0, 1)
+        ->execute();
+      if (!empty($nodes)) {
+        $info['required'] = TRUE;
+        $info['explanation'] = t('To uninstall Book, delete all content that has the Book content type.');
+      }
+    }
+  }
+}
diff --git a/core/modules/book/book.services.yml b/core/modules/book/book.services.yml
index 3b45dae..6d024f7 100644
--- a/core/modules/book/book.services.yml
+++ b/core/modules/book/book.services.yml
@@ -28,10 +28,3 @@ services:
     arguments: ['@request_stack']
     tags:
       - { name: cache.context}
-
-  book.uninstall_validator:
-    class: Drupal\book\BookUninstallValidator
-    tags:
-      - { name: module_install.uninstall_validator }
-    arguments: ['@book.outline_storage', '@entity.query', '@string_translation']
-    lazy: true
diff --git a/core/modules/book/src/BookManager.php b/core/modules/book/src/BookManager.php
index 711976a..aab9611 100644
--- a/core/modules/book/src/BookManager.php
+++ b/core/modules/book/src/BookManager.php
@@ -16,7 +16,6 @@
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Template\Attribute;
 use Drupal\node\NodeInterface;
 
 /**
@@ -502,46 +501,20 @@ public function getActiveTrailIds($bid, $link) {
    * {@inheritdoc}
    */
   public function bookTreeOutput(array $tree) {
-    $items = $this->buildItems($tree);
+    $build = array();
+    $items = array();
 
-    $build = [];
-
-    if ($items) {
-      // Make sure drupal_render() does not re-order the links.
-      $build['#sorted'] = TRUE;
-      // Get the book id from the last link.
-      $item = end($items);
-      // Add the theme wrapper for outer markup.
-      // Allow menu-specific theme overrides.
-      $build['#theme'] = 'book_tree__book_toc_' . $item['original_link']['bid'];
-      $build['#items'] = $items;
-      // Set cache tag.
-      $build['#cache']['tags'][] = 'config:system.book.' . $item['original_link']['bid'];
+    // Pull out just the book links we are going to render so that we
+    // get an accurate count for the first/last classes.
+    foreach ($tree as $data) {
+      if ($data['link']['access']) {
+        $items[] = $data;
+      }
     }
 
-    return $build;
-  }
-
-  /**
-   * Builds the #items property for a book tree's renderable array.
-   *
-   * Helper function for ::bookTreeOutput().
-   *
-   * @param array $tree
-   *   A data structure representing the tree.
-   *
-   * @return array
-   *   The value to use for the #items property of a renderable menu.
-   */
-  protected function buildItems(array $tree) {
-    $items = [];
-
-    foreach ($tree as $data) {
+    $num_items = count($items);
+    foreach ($items as $i => $data) {
       $class = ['menu-item'];
-      // Generally we only deal with visible links, but just in case.
-      if (!$data['link']['access']) {
-        continue;
-      }
       // Set a class for the <li>-tag. Since $data['below'] may contain local
       // tasks, only set 'expanded' class if the link also has children within
       // the current book.
@@ -555,24 +528,30 @@ protected function buildItems(array $tree) {
       // Set a class if the link is in the active trail.
       if ($data['link']['in_active_trail']) {
         $class[] = 'menu-item--active-trail';
+        $data['link']['localized_options']['attributes']['class'][] = 'menu-item--active-trail';
       }
 
       // Allow book-specific theme overrides.
-      $element = [];
-      $element['attributes'] = new Attribute();
-      $element['attributes']['class'] = $class;
-      $element['title'] = $data['link']['title'];
+      $element['#theme'] = 'book_link__book_toc_' . $data['link']['bid'];
+      $element['#attributes']['class'] = $class;
+      $element['#title'] = $data['link']['title'];
       $node = $this->entityManager->getStorage('node')->load($data['link']['nid']);
-      $element['url'] = $node->urlInfo();
-      $element['localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : [];
-      $element['localized_options']['set_active_class'] = TRUE;
-      $element['below'] = $data['below'] ? $this->buildItems($data['below']) : [];
-      $element['original_link'] = $data['link'];
+      $element['#url'] = $node->urlInfo();
+      $element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array();
+      $element['#below'] = $data['below'] ? $this->bookTreeOutput($data['below']) : $data['below'];
+      $element['#original_link'] = $data['link'];
       // Index using the link's unique nid.
-      $items[$data['link']['nid']] = $element;
+      $build[$data['link']['nid']] = $element;
+    }
+    if ($build) {
+      // Make sure drupal_render() does not re-order the links.
+      $build['#sorted'] = TRUE;
+      // Add the theme wrapper for outer markup.
+      // Allow book-specific theme overrides.
+      $build['#theme_wrappers'][] = 'book_tree__book_toc_' . $data['link']['bid'];
     }
 
-    return $items;
+    return $build;
   }
 
   /**
diff --git a/core/modules/book/src/BookManagerInterface.php b/core/modules/book/src/BookManagerInterface.php
index 2e9cbe3..db3d1dd 100644
--- a/core/modules/book/src/BookManagerInterface.php
+++ b/core/modules/book/src/BookManagerInterface.php
@@ -255,7 +255,8 @@ public function deleteFromBook($nid);
    * @return array
    *   A structured array to be rendered by drupal_render().
    *
-   * @see \Drupal\Core\Menu\MenuLinkTree::build
+   * @todo This was copied from menu_tree_output() but with some changes that
+   *   may be obsolete. Attempt to resolve the differences.
    */
   public function bookTreeOutput(array $tree);
 
diff --git a/core/modules/book/src/BookUninstallValidator.php b/core/modules/book/src/BookUninstallValidator.php
deleted file mode 100644
index 84de96d..0000000
--- a/core/modules/book/src/BookUninstallValidator.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\book\BookUninstallValidator.
- */
-
-namespace Drupal\book;
-
-use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-
-/**
- * Prevents book module from being uninstalled whilst any book nodes exist or
- * there are any book outline stored.
- */
-class BookUninstallValidator implements ModuleUninstallValidatorInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The book outline storage.
-   *
-   * @var \Drupal\book\BookOutlineStorageInterface
-   */
-  protected $bookOutlineStorage;
-
-  /**
-   * The entity query for node.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryInterface
-   */
-  protected $entityQuery;
-
-  /**
-   * Constructs a new BookUninstallValidator.
-   *
-   * @param \Drupal\book\BookOutlineStorageInterface $book_outline_storage
-   *   The book outline storage.
-   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
-   *   The entity query factory.
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   */
-  public function __construct(BookOutlineStorageInterface $book_outline_storage, QueryFactory $query_factory, TranslationInterface $string_translation) {
-    $this->bookOutlineStorage = $book_outline_storage;
-    $this->entityQuery = $query_factory->get('node');
-    $this->stringTranslation = $string_translation;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($module) {
-    $reasons = [];
-    if ($module == 'book') {
-      if ($this->hasBookOutlines()) {
-        $reasons[] = $this->t('To uninstall Book, delete all content that is part of a book');
-      }
-      else {
-        // The book node type is provided by the Book module. Prevent uninstall
-        // if there are any nodes of that type.
-        if ($this->hasBookNodes()) {
-          $reasons[] = $this->t('To uninstall Book, delete all content that has the Book content type');
-        }
-      }
-    }
-    return $reasons;
-  }
-
-  /**
-   * Checks if there are any books in an outline.
-   *
-   * @return bool
-   *   TRUE if there are books, FALSE if not.
-   */
-  protected function hasBookOutlines() {
-    return $this->bookOutlineStorage->hasBooks();
-  }
-
-  /**
-   * Determines if there is any book nodes or not.
-   *
-   * @return bool
-   *   TRUE if there are book nodes, FALSE otherwise.
-   */
-  protected function hasBookNodes() {
-    $nodes = $this->entityQuery
-      ->condition('type', 'book')
-      ->accessCheck(FALSE)
-      ->range(0, 1)
-      ->execute();
-    return !empty($nodes);
-  }
-
-}
diff --git a/core/modules/book/src/Tests/BookUninstallTest.php b/core/modules/book/src/Tests/BookUninstallTest.php
index bafaab7..317a16a 100644
--- a/core/modules/book/src/Tests/BookUninstallTest.php
+++ b/core/modules/book/src/Tests/BookUninstallTest.php
@@ -44,8 +44,8 @@ protected function setUp() {
    */
   public function testBookUninstall() {
     // No nodes exist.
-    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
-    $this->assertEqual([], $validation_reasons, 'The book module is not required.');
+    $module_data = _system_rebuild_module_data();
+    $this->assertFalse(isset($module_data['book']->info['required']), 'The book module is not required.');
 
     $content_type = NodeType::create(array(
       'type' => $this->randomMachineName(),
@@ -62,8 +62,9 @@ public function testBookUninstall() {
     $node->save();
 
     // One node in a book but not of type book.
-    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
-    $this->assertEqual(['To uninstall Book, delete all content that is part of a book'], $validation_reasons['book']);
+    $module_data = _system_rebuild_module_data();
+    $this->assertTrue($module_data['book']->info['required'], 'The book module is required.');
+    $this->assertEqual($module_data['book']->info['explanation'], t('To uninstall Book, delete all content that is part of a book.'));
 
     $book_node = Node::create(array('type' => 'book'));
     $book_node->book['bid'] = FALSE;
@@ -71,13 +72,15 @@ public function testBookUninstall() {
 
     // Two nodes, one in a book but not of type book and one book node (which is
     // not in a book).
-    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
-    $this->assertEqual(['To uninstall Book, delete all content that is part of a book'], $validation_reasons['book']);
+    $module_data = _system_rebuild_module_data();
+    $this->assertTrue($module_data['book']->info['required'], 'The book module is required.');
+    $this->assertEqual($module_data['book']->info['explanation'], t('To uninstall Book, delete all content that is part of a book.'));
 
     $node->delete();
     // One node of type book but not actually part of a book.
-    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
-    $this->assertEqual(['To uninstall Book, delete all content that has the Book content type'], $validation_reasons['book']);
+    $module_data = _system_rebuild_module_data();
+    $this->assertTrue($module_data['book']->info['required'], 'The book module is required.');
+    $this->assertEqual($module_data['book']->info['explanation'], t('To uninstall Book, delete all content that has the Book content type.'));
 
     $book_node->delete();
     // No nodes exist therefore the book module is not required.
@@ -88,8 +91,8 @@ public function testBookUninstall() {
     $node->save();
     // One node exists but is not part of a book therefore the book module is
     // not required.
-    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
-    $this->assertEqual([], $validation_reasons, 'The book module is not required.');
+    $module_data = _system_rebuild_module_data();
+    $this->assertFalse(isset($module_data['book']->info['required']), 'The book module is not required.');
 
     // Uninstall the Book module and check the node type is deleted.
     \Drupal::service('module_installer')->uninstall(array('book'));
diff --git a/core/modules/book/templates/book-tree.html.twig b/core/modules/book/templates/book-tree.html.twig
index a4edb37..46068c7 100644
--- a/core/modules/book/templates/book-tree.html.twig
+++ b/core/modules/book/templates/book-tree.html.twig
@@ -1,44 +1,16 @@
 {#
 /**
  * @file
- * Default theme implementation to display a book tree.
+ * Default theme implementation for a book tree.
  *
  * Returns HTML for a wrapper for a book sub-tree.
  *
  * Available variables:
- * - items: A nested list of book items. Each book item contains:
- *   - attributes: HTML attributes for the book item.
- *   - below: The book item child items.
- *   - title: The book link title.
- *   - url: The book link URL, instance of \Drupal\Core\Url.
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @see template_preprocess_book_tree()
  *
  * @ingroup themeable
  */
 #}
-{% import _self as book_tree %}
-
-{#
-  We call a macro which calls itself to render the full tree.
-  @see http://twig.sensiolabs.org/doc/tags/macro.html
-#}
-{{ book_tree.book_links(items, attributes, 0) }}
-
-{% macro book_links(items, attributes, menu_level) %}
-  {% import _self as book_tree %}
-  {% if items %}
-    {% if menu_level == 0 %}
-      <ul{{ attributes }}>
-    {% else %}
-      <ul>
-    {% endif %}
-      {% for item in items %}
-        <li{{ item.attributes }}>
-          {{ link(item.title, item.url) }}
-          {% if item.below %}
-            {{ book_tree.book_links(item.below, attributes, menu_level + 1) }}
-          {% endif %}
-        </li>
-      {% endfor %}
-    </ul>
-  {% endif %}
-{% endmacro %}
+<ul>{{ tree }}</ul>
diff --git a/core/modules/book/tests/src/Unit/BookUninstallValidatorTest.php b/core/modules/book/tests/src/Unit/BookUninstallValidatorTest.php
deleted file mode 100644
index d3748c2..0000000
--- a/core/modules/book/tests/src/Unit/BookUninstallValidatorTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\book\Unit\BookUninstallValidatorTest.
- */
-
-namespace Drupal\Tests\book\Unit;
-
-use Drupal\Tests\UnitTestCase;
-
-/**
- * @coversDefaultClass \Drupal\book\BookUninstallValidator
- * @group book
- */
-class BookUninstallValidatorTest extends UnitTestCase {
-
-  /**
-   * @var \Drupal\book\BookUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $bookUninstallValidator;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->bookUninstallValidator = $this->getMockBuilder('Drupal\book\BookUninstallValidator')
-      ->disableOriginalConstructor()
-      ->setMethods(['hasBookOutlines', 'hasBookNodes'])
-      ->getMock();
-    $this->bookUninstallValidator->setStringTranslation($this->getStringTranslationStub());
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNotBook() {
-    $this->bookUninstallValidator->expects($this->never())
-      ->method('hasBookOutlines');
-    $this->bookUninstallValidator->expects($this->never())
-      ->method('hasBookNodes');
-
-    $module = 'not_book';
-    $expected = [];
-    $reasons = $this->bookUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateEntityQueryWithoutResults() {
-    $this->bookUninstallValidator->expects($this->once())
-      ->method('hasBookOutlines')
-      ->willReturn(FALSE);
-    $this->bookUninstallValidator->expects($this->once())
-      ->method('hasBookNodes')
-      ->willReturn(FALSE);
-
-    $module = 'book';
-    $expected = [];
-    $reasons = $this->bookUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateEntityQueryWithResults() {
-    $this->bookUninstallValidator->expects($this->once())
-      ->method('hasBookOutlines')
-      ->willReturn(FALSE);
-    $this->bookUninstallValidator->expects($this->once())
-      ->method('hasBookNodes')
-      ->willReturn(TRUE);
-
-    $module = 'book';
-    $expected = ['To uninstall Book, delete all content that has the Book content type'];
-    $reasons = $this->bookUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateOutlineStorage() {
-    $this->bookUninstallValidator->expects($this->once())
-      ->method('hasBookOutlines')
-      ->willReturn(TRUE);
-    $this->bookUninstallValidator->expects($this->never())
-      ->method('hasBookNodes');
-
-    $module = 'book';
-    $expected = ['To uninstall Book, delete all content that is part of a book'];
-    $reasons = $this->bookUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-}
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 319067d..c2a2ae6 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -211,31 +211,6 @@ function comment_node_links_alter(array &$node_links, NodeInterface $node, array
 }
 
 /**
- * Implements hook_entity_view().
- */
-function comment_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode, $langcode) {
-  if ($entity instanceof FieldableEntityInterface && $view_mode == 'rss' && $display->getComponent('links')) {
-    /** @var \Drupal\comment\CommentManagerInterface $comment_manager */
-    $comment_manager = \Drupal::service('comment.manager');
-    $fields = $comment_manager->getFields($entity->getEntityTypeId());
-    foreach ($fields as $field_name => $detail) {
-      if ($entity->hasField($field_name) && $entity->get($field_name)->status != CommentItemInterface::HIDDEN) {
-        // Add a comments RSS element which is a URL to the comments of this
-        // entity.
-        $options = array(
-          'fragment' => 'comments',
-          'absolute' => TRUE,
-        );
-        $entity->rss_elements[] = array(
-          'key' => 'comments',
-          'value' => $entity->url('canonical', $options),
-        );
-      }
-    }
-  }
-}
-
-/**
  * Implements hook_ENTITY_TYPE_view_alter() for node entities.
  */
 function comment_node_view_alter(array &$build, EntityInterface $node, EntityViewDisplayInterface $display) {
@@ -250,7 +225,7 @@ function comment_node_view_alter(array &$build, EntityInterface $node, EntityVie
  * @param \Drupal\comment\CommentInterface $comment
  *   The comment object.
  * @param $view_mode
- *   (optional) View mode; e.g., 'full', 'teaser', etc. Defaults to 'full'.
+ *   (optional) View mode, e.g. 'full', 'teaser'... Defaults to 'full'.
  * @param $langcode
  *   (optional) A language code to use for rendering. Defaults to the global
  *   content language of the current request.
@@ -268,7 +243,7 @@ function comment_view(CommentInterface $comment, $view_mode = 'full', $langcode
  * @param $comments
  *   An array of comments as returned by entity_load_multiple().
  * @param $view_mode
- *   View mode; e.g., 'full', 'teaser', etc.
+ *   View mode, e.g. 'full', 'teaser'...
  * @param $langcode
  *   (optional) A string indicating the language field values are to be shown
  *   in. If no language is provided the current content language is used.
diff --git a/core/modules/comment/config/optional/views.view.comments_recent.yml b/core/modules/comment/config/optional/views.view.comments_recent.yml
index 6f9c5cd..a15ecd1 100644
--- a/core/modules/comment/config/optional/views.view.comments_recent.yml
+++ b/core/modules/comment/config/optional/views.view.comments_recent.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access comments'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/comment/src/CommentLinkBuilder.php b/core/modules/comment/src/CommentLinkBuilder.php
index 7ce175c..5d4d8fe 100644
--- a/core/modules/comment/src/CommentLinkBuilder.php
+++ b/core/modules/comment/src/CommentLinkBuilder.php
@@ -82,12 +82,11 @@ public function __construct(AccountInterface $current_user, CommentManagerInterf
   public function buildCommentedEntityLinks(FieldableEntityInterface $entity, array &$context) {
     $entity_links = array();
     $view_mode = $context['view_mode'];
-    if ($view_mode == 'search_index' || $view_mode == 'search_result' || $view_mode == 'print' || $view_mode == 'rss') {
+    if ($view_mode == 'search_index' || $view_mode == 'search_result' || $view_mode == 'print') {
       // Do not add any links if the entity is displayed for:
       // - search indexing.
       // - constructing a search result excerpt.
       // - print.
-      // - rss.
       return array();
     }
 
@@ -102,7 +101,19 @@ public function buildCommentedEntityLinks(FieldableEntityInterface $entity, arra
       if ($commenting_status != CommentItemInterface::HIDDEN) {
         // Entity has commenting status open or closed.
         $field_definition = $entity->getFieldDefinition($field_name);
-        if ($view_mode == 'teaser') {
+        if ($view_mode == 'rss') {
+          // Add a comments RSS element which is a URL to the comments of this
+          // entity.
+          $options = array(
+            'fragment' => 'comments',
+            'absolute' => TRUE,
+          );
+          $entity->rss_elements[] = array(
+            'key' => 'comments',
+            'value' => $entity->url('canonical', $options),
+          );
+        }
+        elseif ($view_mode == 'teaser') {
           // Teaser view: display the number of comments that have been posted,
           // or a link to add new comments if the user has permission, the
           // entity is open to new comments, and there currently are none.
diff --git a/core/modules/comment/src/Plugin/views/row/Rss.php b/core/modules/comment/src/Plugin/views/row/Rss.php
index 3002765..1d8c341 100644
--- a/core/modules/comment/src/Plugin/views/row/Rss.php
+++ b/core/modules/comment/src/Plugin/views/row/Rss.php
@@ -84,7 +84,7 @@ public function render($row) {
       return;
     }
 
-    $description_build = [];
+    $item_text = '';
 
     $comment->link = $comment->url('canonical', array('absolute' => TRUE));
     $comment->rss_namespaces = array();
@@ -115,16 +115,14 @@ public function render($row) {
 
     if ($view_mode != 'title') {
       // We render comment contents.
-      $description_build = $build;
+      $item_text .= drupal_render_root($build);
     }
 
     $item = new \stdClass();
-    $item->description = $description_build;
+    $item->description = $item_text;
     $item->title = $comment->label();
     $item->link = $comment->link;
-    // Provide a reference so that the render call in
-    // template_preprocess_views_view_row_rss() can still access it.
-    $item->elements = &$comment->rss_elements;
+    $item->elements = $comment->rss_elements;
     $item->cid = $comment->id();
 
     $build = array(
@@ -133,7 +131,7 @@ public function render($row) {
       '#options' => $this->options,
       '#row' => $item,
     );
-    return $build;
+    return drupal_render_root($build);
   }
 
 }
diff --git a/core/modules/comment/src/Tests/CommentRssTest.php b/core/modules/comment/src/Tests/CommentRssTest.php
index e7072fa..ca3acda 100644
--- a/core/modules/comment/src/Tests/CommentRssTest.php
+++ b/core/modules/comment/src/Tests/CommentRssTest.php
@@ -8,8 +8,6 @@
 namespace Drupal\comment\Tests;
 
 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
-use Drupal\Core\Entity\Entity\EntityViewDisplay;
-use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 
 /**
  * Tests comments as part of an RSS feed.
@@ -18,8 +16,6 @@
  */
 class CommentRssTest extends CommentTestBase {
 
-  use AssertPageCacheContextsAndTagsTrait;
-
   /**
    * Modules to install.
    *
@@ -28,22 +24,6 @@ class CommentRssTest extends CommentTestBase {
   public static $modules = array('views');
 
   /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    // Setup the rss view display.
-    EntityViewDisplay::create([
-      'status' => TRUE,
-      'targetEntityType' => 'node',
-      'bundle' => 'article',
-      'mode' => 'rss',
-      'content' => ['links' => ['weight' => 100]],
-    ])->save();
-  }
-
-  /**
    * Tests comments as part of an RSS feed.
    */
   function testCommentRss() {
@@ -51,18 +31,6 @@ function testCommentRss() {
     $this->drupalLogin($this->webUser);
     $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName());
     $this->drupalGet('rss.xml');
-
-    $this->assertCacheTags([
-      'config:views.view.frontpage', 'node:1', 'node_list', 'node_view', 'user:3',
-    ]);
-    $this->assertCacheContexts([
-      'languages:language_interface',
-      'theme',
-      'user.node_grants:view',
-      'user.permissions',
-      'timezone',
-    ]);
-
     $raw = '<comments>' . $this->node->url('canonical', array('fragment' => 'comments', 'absolute' => TRUE)) . '</comments>';
     $this->assertRaw($raw, 'Comments as part of RSS feed.');
 
diff --git a/core/modules/comment/src/Tests/CommentTokenReplaceTest.php b/core/modules/comment/src/Tests/CommentTokenReplaceTest.php
index c3808e6..c45c0f7 100644
--- a/core/modules/comment/src/Tests/CommentTokenReplaceTest.php
+++ b/core/modules/comment/src/Tests/CommentTokenReplaceTest.php
@@ -60,8 +60,8 @@ function testCommentTokenReplacement() {
     $tests['[comment:langcode]'] = SafeMarkup::checkPlain($comment->language()->getId());
     $tests['[comment:url]'] = $comment->url('canonical', $url_options + array('fragment' => 'comment-' . $comment->id()));
     $tests['[comment:edit-url]'] = $comment->url('edit-form', $url_options);
-    $tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getCreatedTime(), array('langcode' => $language_interface->getId()));
-    $tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getChangedTimeAcrossTranslations(), array('langcode' => $language_interface->getId()));
+    $tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getCreatedTime(), 2, $language_interface->getId());
+    $tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getChangedTimeAcrossTranslations(), 2, $language_interface->getId());
     $tests['[comment:parent:cid]'] = $comment->hasParentComment() ? $comment->getParentComment()->id() : NULL;
     $tests['[comment:parent:title]'] = SafeMarkup::checkPlain($parent_comment->getSubject());
     $tests['[comment:entity]'] = SafeMarkup::checkPlain($node->getTitle());
diff --git a/core/modules/comment/src/Tests/CommentUninstallTest.php b/core/modules/comment/src/Tests/CommentUninstallTest.php
index fa97f74..1cca31a 100644
--- a/core/modules/comment/src/Tests/CommentUninstallTest.php
+++ b/core/modules/comment/src/Tests/CommentUninstallTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\comment\Tests;
 
 use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\Core\Extension\ModuleUninstallValidatorException;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -37,23 +36,19 @@ protected function setUp() {
   }
 
   /**
-   * Tests if comment module uninstallation fails if the field exists.
-   *
-   * @throws \Drupal\Core\Extension\ModuleUninstallValidatorException
+   * Tests if comment module uninstallation properly deletes the field.
    */
   function testCommentUninstallWithField() {
     // Ensure that the field exists before uninstallation.
     $field_storage = FieldStorageConfig::loadByName('comment', 'comment_body');
     $this->assertNotNull($field_storage, 'The comment_body field exists.');
 
-    // Uninstall the comment module which should trigger an exception.
-    try {
-      $this->container->get('module_installer')->uninstall(array('comment'));
-      $this->fail("Expected an exception when uninstall was attempted.");
-    }
-    catch (ModuleUninstallValidatorException $e) {
-      $this->pass("Caught an exception when uninstall was attempted.");
-    }
+    // Uninstall the comment module which should trigger field deletion.
+    $this->container->get('module_installer')->uninstall(array('comment'));
+
+    // Check that the field is now deleted.
+    $field_storage = FieldStorageConfig::loadByName('comment', 'comment_body');
+    $this->assertNull($field_storage, 'The comment_body field has been deleted.');
   }
 
 
@@ -70,16 +65,6 @@ function testCommentUninstallWithoutField() {
     $field_storage = FieldStorageConfig::loadByName('comment', 'comment_body');
     $this->assertNull($field_storage, 'The comment_body field has been deleted.');
 
-    // Manually delete the comment field on the node before module uninstallation.
-    $field_storage = FieldStorageConfig::loadByName('node', 'comment');
-    $this->assertNotNull($field_storage, 'The comment field exists.');
-    $field_storage->delete();
-
-    // Check that the field is now deleted.
-    $field_storage = FieldStorageConfig::loadByName('node', 'comment');
-    $this->assertNull($field_storage, 'The comment field has been deleted.');
-
-    field_purge_batch(10);
     // Ensure that uninstallation succeeds even if the field has already been
     // deleted manually beforehand.
     $this->container->get('module_installer')->uninstall(array('comment'));
diff --git a/core/modules/comment/src/Tests/Views/CommentRestExportTest.php b/core/modules/comment/src/Tests/Views/CommentRestExportTest.php
index 9737b4f..ecf1a54 100644
--- a/core/modules/comment/src/Tests/Views/CommentRestExportTest.php
+++ b/core/modules/comment/src/Tests/Views/CommentRestExportTest.php
@@ -55,7 +55,7 @@ protected function setUp() {
    * Test comment row.
    */
   public function testCommentRestExport() {
-    $this->drupalGetWithFormat(sprintf('node/%d/comments', $this->nodeUserCommented->id()), 'hal_json');
+    $this->drupalGet(sprintf('node/%d/comments', $this->nodeUserCommented->id()), [], ['Accept' => 'application/hal+json']);
     $this->assertResponse(200);
     $contents = Json::decode($this->getRawContent());
     $this->assertEqual($contents[0]['subject'], 'How much wood would a woodchuck chuck');
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_field_name.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_field_name.yml
index 9938a65..a4ad1c1 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_field_name.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_field_name.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access comments'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml
index 0c74efa..2de8cdb 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml
@@ -29,7 +29,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
@@ -386,7 +386,6 @@ display:
           uses_fields: false
           formats:
             json: json
-            hal_json: hal_json
       row:
         type: data_field
         options:
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_row.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_row.yml
index d7b1b3d..f6588b8 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_row.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_row.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rss.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rss.yml
index be6210a..7fb1644 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rss.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rss.yml
@@ -23,7 +23,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml
index 030b4a7..2104d70 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml
@@ -34,7 +34,7 @@ display:
           plugin_id: argument_comment_user_uid
           entity_type: node
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml
index 76c67c6..60f6554 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php b/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
index 26edb8e..436fe70 100644
--- a/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
+++ b/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
@@ -154,6 +154,18 @@ public function testCommentLinkBuilder(NodeInterface $node, $context, $has_acces
     else {
       $this->assertSame($links, $expected);
     }
+    if ($context['view_mode'] == 'rss' && $node->get('comment')->status) {
+      $found = FALSE;
+      if ($node->get('comment')->status) {
+        foreach ($node->rss_elements as $element) {
+          if ($element['key'] == 'comments') {
+            $found = TRUE;
+            break;
+          }
+        }
+      }
+      $this->assertTrue($found);
+    }
   }
 
   /**
diff --git a/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php b/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php
index e2e21ec..6439fec 100644
--- a/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php
+++ b/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php
@@ -55,7 +55,7 @@ class CommentStatisticsUnitTest extends UnitTestCase {
    * Sets up required mocks and the CommentStatistics service under test.
    */
   protected function setUp() {
-    $this->statement = $this->getMockBuilder('Drupal\Core\Database\Driver\sqlite\Statement')
+    $this->statement = $this->getMockBuilder('Drupal\Core\Database\Driver\fake\FakeStatement')
       ->disableOriginalConstructor()
       ->getMock();
 
diff --git a/core/modules/config/src/Tests/ConfigImportAllTest.php b/core/modules/config/src/Tests/ConfigImportAllTest.php
index 6e1aaea..7645847 100644
--- a/core/modules/config/src/Tests/ConfigImportAllTest.php
+++ b/core/modules/config/src/Tests/ConfigImportAllTest.php
@@ -8,10 +8,8 @@
 namespace Drupal\config\Tests;
 
 use Drupal\Core\Config\StorageComparer;
-use Drupal\filter\Entity\FilterFormat;
 use Drupal\system\Tests\Module\ModuleTestBase;
 use Drupal\shortcut\Entity\Shortcut;
-use Drupal\taxonomy\Entity\Term;
 
 /**
  * Tests the largest configuration import possible with all available modules.
@@ -85,13 +83,12 @@ public function testInstallUninstall() {
     // Purge the data.
     field_purge_batch(1000);
 
-    // Delete all terms.
-    $terms = Term::loadMultiple();
-    entity_delete_multiple('taxonomy_term', array_keys($terms));
-
-    // Delete all filter formats.
-    $filters = FilterFormat::loadMultiple();
-    entity_delete_multiple('filter_format', array_keys($filters));
+    // Delete any forum terms so it can be uninstalled.
+    $vid = $this->config('forum.settings')->get('vocabulary');
+    $terms = entity_load_multiple_by_properties('taxonomy_term', ['vid' => $vid]);
+    foreach ($terms as $term) {
+      $term->delete();
+    }
 
     // Delete any shortcuts so the shortcut module can be uninstalled.
     $shortcuts = Shortcut::loadMultiple();
@@ -100,11 +97,7 @@ public function testInstallUninstall() {
     system_list_reset();
     $all_modules = system_rebuild_module_data();
 
-    // Ensure that only core required modules and the install profile can not be uninstalled.
-    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(array_keys($all_modules));
-    $this->assertEqual(['standard', 'system', 'user'], array_keys($validation_reasons));
-
-    $modules_to_uninstall = array_filter($all_modules, function ($module) use ($validation_reasons) {
+    $modules_to_uninstall = array_filter($all_modules, function ($module) {
       // Filter required and not enabled modules.
       if (!empty($module->info['required']) || $module->status == FALSE) {
         return FALSE;
@@ -116,8 +109,6 @@ public function testInstallUninstall() {
     unset($modules_to_uninstall['config']);
 
     $this->assertTrue(isset($modules_to_uninstall['comment']), 'The comment module will be disabled');
-    $this->assertTrue(isset($modules_to_uninstall['file']), 'The File module will be disabled');
-    $this->assertTrue(isset($modules_to_uninstall['editor']), 'The Editor module will be disabled');
 
     // Uninstall all modules that can be uninstalled.
     \Drupal::service('module_installer')->uninstall(array_keys($modules_to_uninstall));
diff --git a/core/modules/config_translation/css/config_translation.admin.css b/core/modules/config_translation/css/config_translation.admin.css
index 8e862fb..e6e90c3 100644
--- a/core/modules/config_translation/css/config_translation.admin.css
+++ b/core/modules/config_translation/css/config_translation.admin.css
@@ -7,18 +7,38 @@
  * Hide the label, in an accessible way, for responsive screens which show the
  * form in one column.
  */
-.translation-set__translated label {
+.config-translation-form .translation-element-wrapper .translation label {
+  position: absolute !important;
   clip: rect(1px, 1px, 1px, 1px);
-  height: 1px;
   overflow: hidden;
-  position: absolute;
+  height: 1px;
   width: 1px;
 }
 
-@media screen and (min-width: 38em) {
-  .translation-set__translated label {
+/**
+ * For wider screens, show the label and display source and translation side by
+ * side.
+ */
+@media all and (min-width: 851px) {
+  .config-translation-form .translation-element-wrapper .source {
+    width: 48%;
+    float: left; /* LTR */
+  }
+  [dir="rtl"] .config-translation-form .translation-element-wrapper .source {
+    float: right;
+  }
+  .config-translation-form .translation-element-wrapper .translation {
+    width: 48%;
+    float: right; /* LTR */
+  }
+  [dir="rtl"] .config-translation-form .translation-element-wrapper .translation {
+    float: left;
+  }
+  .config-translation-form .translation-element-wrapper .translation label {
+    position: static !important;
+    clip: auto;
+    overflow: visible;
     height: auto;
-    position: inherit;
     width: auto;
   }
 }
diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php
index c7218df..00b36c5 100644
--- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php
+++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php
@@ -904,7 +904,7 @@ protected function renderContextualLinks($ids, $current_path) {
     for ($i = 0; $i < count($ids); $i++) {
       $post['ids[' . $i . ']'] = $ids[$i];
     }
-    return $this->drupalPostWithFormat('contextual/render', 'json', $post, array('query' => array('destination' => $current_path)));
+    return $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => $current_path)));
   }
 
   /**
diff --git a/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig b/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig
index 672f567..d20d19c 100644
--- a/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig
+++ b/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig
@@ -14,11 +14,11 @@
  * @ingroup themeable
  */
 #}
-<div class="translation-set clearfix">
-  <div class="layout-column half translation-set__source">
+<div class="clearfix translation-element-wrapper">
+  <div class="source">
     {{ element.source }}
   </div>
-  <div class="layout-column half translation-set__translated">
+  <div class="translation">
     {{ element.translation }}
   </div>
 </div>
diff --git a/core/modules/contact/src/Tests/ContactSitewideTest.php b/core/modules/contact/src/Tests/ContactSitewideTest.php
index c815d35..ff8d115 100644
--- a/core/modules/contact/src/Tests/ContactSitewideTest.php
+++ b/core/modules/contact/src/Tests/ContactSitewideTest.php
@@ -231,7 +231,7 @@ function testSiteWideContact() {
     }
     // Submit contact form one over limit.
     $this->submitContact($this->randomMachineName(16), $recipients[0], $this->randomMachineName(16), $id, $this->randomMachineName(64));
-    $this->assertRaw(t('You cannot send more than %number messages in 10 min. Try again later.', array('%number' => $this->config('contact.settings')->get('flood.limit'))));
+    $this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => $this->config('contact.settings')->get('flood.limit'), '@interval' => \Drupal::service('date.formatter')->formatInterval(600))));
 
     // Test listing controller.
     $this->drupalLogin($admin_user);
diff --git a/core/modules/contact/tests/modules/contact_test_views/test_views/views.view.test_contact_link.yml b/core/modules/contact/tests/modules/contact_test_views/test_views/views.view.test_contact_link.yml
index 84b2a2b..339f4ff 100644
--- a/core/modules/contact/tests/modules/contact_test_views/test_views/views.view.test_contact_link.yml
+++ b/core/modules/contact/tests/modules/contact_test_views/test_views/views.view.test_contact_link.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/content_translation/tests/modules/content_translation_test_views/test_views/views.view.test_entity_translations_link.yml b/core/modules/content_translation/tests/modules/content_translation_test_views/test_views/views.view.test_entity_translations_link.yml
index d7a21c3..87da0bb 100644
--- a/core/modules/content_translation/tests/modules/content_translation_test_views/test_views/views.view.test_entity_translations_link.yml
+++ b/core/modules/content_translation/tests/modules/content_translation_test_views/test_views/views.view.test_entity_translations_link.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php b/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php
index 8846ab9..01eb4f5 100644
--- a/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php
+++ b/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php
@@ -181,6 +181,6 @@ protected function renderContextualLinks($ids, $current_path) {
     for ($i = 0; $i < count($ids); $i++) {
       $post['ids[' . $i . ']'] = $ids[$i];
     }
-    return $this->drupalPostWithFormat('contextual/render', 'json', $post, array('query' => array('destination' => $current_path)));
+    return $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => $current_path)));
   }
 }
diff --git a/core/modules/datetime/datetime.views.inc b/core/modules/datetime/datetime.views.inc
new file mode 100644
index 0000000..8b26bd5
--- /dev/null
+++ b/core/modules/datetime/datetime.views.inc
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Provides views data for the datetime module.
+ */
+
+use Drupal\field\FieldStorageConfigInterface;
+
+/**
+ * Implements hook_field_views_data().
+ */
+function datetime_field_views_data(FieldStorageConfigInterface $field_storage) {
+  // @todo This code only covers configurable fields, handle base table fields
+  //   in https://www.drupal.org/node/2489476.
+  $data = views_field_default_views_data($field_storage);
+  foreach ($data as $table_name => $table_data) {
+    // Set the 'datetime' filter type.
+    $data[$table_name][$field_storage->getName() . '_value']['filter']['id'] = 'datetime';
+
+    // Set the 'datetime' argument type.
+    $data[$table_name][$field_storage->getName() . '_value']['argument']['id'] = 'datetime';
+
+    // Create year, month, and day arguments.
+    $group = $data[$table_name][$field_storage->getName() . '_value']['group'];
+    $arguments = array(
+      // Argument type => help text.
+      'year' => t('Date in the form of YYYY.'),
+      'month' => t('Date in the form of MM.'),
+      'day' => t('Date in the form of DD.'),
+    );
+    foreach ($arguments as $argument_type => $help_text) {
+      $data[$table_name][$field_storage->getName() . '_value_' . $argument_type] = array(
+        'title' => $field_storage->getLabel() . ' (' . $argument_type . ')',
+        'help' => $help_text,
+        'argument' => array(
+          'field' => $field_storage->getName() . '_value',
+          'id' => 'datetime_' . $argument_type,
+        ),
+        'group' => $group,
+      );
+    }
+
+    // Set the 'datetime' sort handler.
+    $data[$table_name][$field_storage->getName() . '_value']['sort']['id'] = 'datetime';
+  }
+
+  return $data;
+}
diff --git a/core/modules/datetime/src/Plugin/views/argument/Date.php b/core/modules/datetime/src/Plugin/views/argument/Date.php
new file mode 100644
index 0000000..7bd5cdf
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/views/argument/Date.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Plugin\views\Argument\Date.
+ */
+
+namespace Drupal\datetime\Plugin\views\Argument;
+
+use Drupal\views\Plugin\views\argument\Date as NumericDate;
+
+/**
+ * Abstract argument handler for dates.
+ *
+ * Adds an option to set a default argument based on the current date.
+ *
+ * Definitions terms:
+ * - many to one: If true, the "many to one" helper will be used.
+ * - invalid input: A string to give to the user for obviously invalid input.
+ *                  This is deprecated in favor of argument validators.
+ *
+ * @see \Drupal\views\ManyTonOneHelper
+ *
+ * @ingroup views_argument_handlers
+ *
+ * @ViewsArgument("datetime")
+ */
+class Date extends NumericDate {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDateField() {
+    // Return the real field, since it is already in string format.
+    return "$this->tableAlias.$this->realField";
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDateFormat($format) {
+    // Pass in the string-field option.
+    return $this->query->getDateFormat($this->getDateField(), $format, TRUE);
+  }
+}
diff --git a/core/modules/datetime/src/Plugin/views/argument/DayDate.php b/core/modules/datetime/src/Plugin/views/argument/DayDate.php
new file mode 100644
index 0000000..f100db0
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/views/argument/DayDate.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Plugin\views\argument\DayDate.
+ */
+
+namespace Drupal\datetime\Plugin\views\argument;
+
+/**
+ * Argument handler for a day.
+ *
+ * @ViewsArgument("datetime_day")
+ */
+class DayDate extends Date {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $argFormat = 'd';
+
+}
diff --git a/core/modules/datetime/src/Plugin/views/argument/MonthDate.php b/core/modules/datetime/src/Plugin/views/argument/MonthDate.php
new file mode 100644
index 0000000..2aac64d
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/views/argument/MonthDate.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Plugin\views\argument\MonthDate.
+ */
+
+namespace Drupal\datetime\Plugin\views\argument;
+
+/**
+ * Argument handler for a month.
+ *
+ * @ViewsArgument("datetime_month")
+ */
+class MonthDate extends Date {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $argFormat = 'm';
+
+}
diff --git a/core/modules/datetime/src/Plugin/views/argument/YearDate.php b/core/modules/datetime/src/Plugin/views/argument/YearDate.php
new file mode 100644
index 0000000..c34dde3
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/views/argument/YearDate.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Plugin\views\argument\YearDate.
+ */
+
+namespace Drupal\datetime\Plugin\views\argument;
+
+/**
+ * Argument handler for a year.
+ *
+ * @ViewsArgument("datetime_year")
+ */
+class YearDate extends Date {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $argFormat = 'Y';
+
+}
diff --git a/core/modules/datetime/src/Plugin/views/filter/Date.php b/core/modules/datetime/src/Plugin/views/filter/Date.php
new file mode 100644
index 0000000..6fe2c30
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/views/filter/Date.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Plugin\views\filter\String.
+ */
+
+namespace Drupal\datetime\Plugin\views\filter;
+
+use Drupal\Core\Datetime\DateFormatter;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\views\Plugin\views\filter\Date as NumericDate;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Date/time views filter.
+ *
+ * Even thought dates are stored as strings, the numeric filter is extended
+ * because it provides more sensible operators.
+ *
+ * @ingroup views_filter_handlers
+ *
+ * @ViewsFilter("datetime")
+ */
+class Date extends NumericDate implements ContainerFactoryPluginInterface {
+
+  /**
+   * The date formatter service.
+   *
+   * @var \Drupal\Core\Datetime\DateFormatter
+   */
+  protected $dateFormatter;
+
+  /**
+   * Constructs a new Date handler.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin ID for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Datetime\DateFormatter $date_formatter
+   *   The date formatter service.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, DateFormatter $date_formatter) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->dateFormatter = $date_formatter;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('date.formatter')
+    );
+  }
+
+  /**
+   * Date format for SQL conversion.
+   *
+   * @var string
+   *
+   * @see \Drupal\views\Plugin\views\query\Sql::getDateFormat()
+   */
+  protected static $dateFormat = 'Y-m-d H:i:s';
+
+  /**
+   * Override parent method, which deals with dates as integers.
+   */
+  protected function opBetween($field) {
+    $origin = ($this->value['type'] == 'offset') ? REQUEST_TIME : 0;
+    $a = intval(strtotime($this->value['min'], $origin));
+    $b = intval(strtotime($this->value['max'], $origin));
+
+    // Convert to ISO format and format for query. UTC timezone is used since
+    // dates are stored in UTC.
+    $a = $this->query->getDateFormat("'" . $this->dateFormatter->format($a, 'custom', DATETIME_DATETIME_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE) . "'", static::$dateFormat, TRUE);
+    $b = $this->query->getDateFormat("'" . $this->dateFormatter->format($b, 'custom', DATETIME_DATETIME_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE) . "'", static::$dateFormat, TRUE);
+
+    // This is safe because we are manually scrubbing the values.
+    $operator = strtoupper($this->operator);
+    $field = $this->query->getDateFormat($field, static::$dateFormat, TRUE);
+    $this->query->addWhereExpression($this->options['group'], "$field $operator $a AND $b");
+  }
+
+  /**
+   * Override parent method, which deals with dates as integers.
+   */
+  protected function opSimple($field) {
+    $origin =  (!empty($this->value['type']) && $this->value['type'] == 'offset') ? REQUEST_TIME : 0;
+    $value = intval(strtotime($this->value['value'], $origin));
+
+    // Convert to ISO. UTC is used since dates are stored in UTC.
+    $value = $this->query->getDateFormat("'" . $this->dateFormatter->format($value, 'custom', DATETIME_DATETIME_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE) . "'", static::$dateFormat, TRUE);
+
+    // This is safe because we are manually scrubbing the value.
+    $field = $this->query->getDateFormat($field, static::$dateFormat, TRUE);
+    $this->query->addWhereExpression($this->options['group'], "$field $this->operator $value");
+  }
+
+}
diff --git a/core/modules/datetime/src/Plugin/views/sort/Date.php b/core/modules/datetime/src/Plugin/views/sort/Date.php
new file mode 100644
index 0000000..b86d424
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/views/sort/Date.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Plugin\views\sort\Date.
+ */
+
+namespace Drupal\datetime\Plugin\views\sort;
+
+use Drupal\views\Plugin\views\sort\Date as NumericDate;
+
+/**
+ * Basic sort handler for datetime fields.
+ *
+ * This handler enables granularity, which is the ability to make dates
+ * equivalent based upon nearness.
+ *
+ * @ViewsSort("datetime")
+ */
+class Date extends NumericDate {
+
+  /**
+   * Override to account for dates stored as strings.
+   */
+  public function getDateField() {
+    // Return the real field, since it is already in string format.
+    return "$this->tableAlias.$this->realField";
+  }
+
+  /**
+   * Override query to provide 'second' granularity.
+   */
+  public function query() {
+    $this->ensureMyTable();
+    switch ($this->options['granularity']) {
+      case 'second':
+        $formula = $this->getDateFormat('YmdHis');
+        $this->query->addOrderBy(NULL, $formula, $this->options['order'], $this->tableAlias . '_' . $this->field . '_' . $this->options['granularity']);
+        return;
+    }
+
+    // All other granularities are handled by the numeric sort handler.
+    parent::query();
+  }
+
+}
diff --git a/core/modules/datetime/src/Tests/Views/ArgumentDateTimeTest.php b/core/modules/datetime/src/Tests/Views/ArgumentDateTimeTest.php
new file mode 100644
index 0000000..a7d9e92
--- /dev/null
+++ b/core/modules/datetime/src/Tests/Views/ArgumentDateTimeTest.php
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Tests\Views\ArgumentDateTimeTest.
+ */
+
+namespace Drupal\datetime\Tests\Views;
+
+use Drupal\views\Views;
+
+/**
+ * Tests the Drupal\datetime\Plugin\views\filter\Date handler.
+ *
+ * @group datetime
+ */
+class ArgumentDateTimeTest extends DateTimeHandlerTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = array('test_argument_datetime');
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    // Add some basic test nodes.
+    $dates = array(
+      '2000-10-10',
+      '2001-10-10',
+      '2002-01-01',
+    );
+    foreach ($dates as $date) {
+      $this->nodes[] = $this->drupalCreateNode(array(
+        'field_date' => array(
+          'value' => $date,
+        )
+      ));
+    }
+  }
+
+  /**
+   * Test year argument.
+   *
+   * @see \Drupal\datetime\Plugin\views\argument\YearDate
+   */
+  public function testDatetimeArgumentYear() {
+    $view = Views::getView('test_argument_datetime');
+
+    // The 'default' display has the 'year' argument.
+    $view->setDisplay('default');
+    $this->executeView($view, array('2000'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[0]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+
+    $view->setDisplay('default');
+    $this->executeView($view, array('2002'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[2]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+  }
+
+  /**
+   * Test month argument.
+   *
+   * @see \Drupal\datetime\Plugin\views\argument\MonthDate
+   */
+  public function testDatetimeArgumentMonth() {
+    $view = Views::getView('test_argument_datetime');
+    // The 'embed_1' display has the 'month' argument.
+    $view->setDisplay('embed_1');
+
+    $this->executeView($view, array('10'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[0]->id());
+    $expected[] = array('nid' => $this->nodes[1]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+
+    $view->setDisplay('embed_1');
+    $this->executeView($view, array('01'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[2]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+  }
+
+  /**
+   * Test day argument.
+   *
+   * @see \Drupal\datetime\Plugin\views\argument\DayDate
+   */
+  public function testDatetimeArgumentDay() {
+    $view = Views::getView('test_argument_datetime');
+
+    // The 'embed_2' display has the 'day' argument.
+    $view->setDisplay('embed_2');
+    $this->executeView($view, array('10'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[0]->id());
+    $expected[] = array('nid' => $this->nodes[1]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+
+    $view->setDisplay('embed_2');
+    $this->executeView($view, array('01'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[2]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+  }
+
+  /**
+   * Test year, month, and day arguments combined.
+   */
+  public function testDatetimeArgumentAll() {
+    $view = Views::getView('test_argument_datetime');
+    // The 'embed_3' display has year, month, and day arguments.
+    $view->setDisplay('embed_3');
+
+    $this->executeView($view, array('2000', '10', '10'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[0]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+
+    $view->setDisplay('embed_3');
+    $this->executeView($view, array('2002', '01', '01'));
+    $expected = array();
+    $expected[] = array('nid' => $this->nodes[2]->id());
+    $this->assertIdenticalResultset($view, $expected, $this->map);
+    $view->destroy();
+  }
+
+}
diff --git a/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php b/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php
new file mode 100644
index 0000000..4678be9
--- /dev/null
+++ b/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Tests\Views\DateTimeHandlerTestBase.
+ */
+
+namespace Drupal\datetime\Tests\Views;
+
+use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
+use Drupal\views\Tests\Handler\HandlerTestBase;
+use Drupal\views\Tests\ViewTestData;
+
+/**
+ * Base class for testing datetime handlers.
+ */
+abstract class DateTimeHandlerTestBase extends HandlerTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = array('datetime_test', 'node', 'datetime');
+
+  /**
+   * Name of the field.
+   *
+   * Note, this is used in the default test view.
+   *
+   * @var string
+   */
+  protected static $field_name = 'field_date';
+
+  /**
+   * Nodes to test.
+   *
+   * @var \Drupal\node\NodeInterface[]
+   */
+  protected $nodes = array();
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    // Add a date field to page nodes.
+    $node_type = entity_create('node_type', array(
+        'type' => 'page',
+        'name' => 'page'
+      ));
+    $node_type->save();
+    $fieldStorage = entity_create('field_storage_config', array(
+      'field_name' => static::$field_name,
+      'entity_type' => 'node',
+      'type' => 'datetime',
+      'settings' => array('datetime_type' => DateTimeItem::DATETIME_TYPE_DATETIME),
+    ));
+    $fieldStorage->save();
+    $field = entity_create('field_config', array(
+      'field_storage' => $fieldStorage,
+      'bundle' => 'page',
+      'required' => TRUE,
+    ));
+    $field->save();
+
+    // Views needs to be aware of the new field.
+    $this->container->get('views.views_data')->clear();
+
+    // Set column map.
+    $this->map = array(
+      'nid' => 'nid',
+    );
+
+    // Load test views.
+    ViewTestData::createTestViews(get_class($this), array('datetime_test'));
+  }
+
+}
diff --git a/core/modules/datetime/src/Tests/Views/FilterDateTimeTest.php b/core/modules/datetime/src/Tests/Views/FilterDateTimeTest.php
new file mode 100644
index 0000000..068c88e
--- /dev/null
+++ b/core/modules/datetime/src/Tests/Views/FilterDateTimeTest.php
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Tests\Views\FilterDateTimeTest.
+ */
+
+namespace Drupal\datetime\Tests\Views;
+
+use Drupal\Core\Datetime\Element\Datetime;
+use Drupal\views\Views;
+
+/**
+ * Tests the Drupal\datetime\Plugin\views\filter\Date handler.
+ *
+ * @group datetime
+ */
+class FilterDateTimeTest extends DateTimeHandlerTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = array('test_filter_datetime');
+
+  /**
+   * For offset tests, set a date 1 day in the future.
+   */
+  protected static $date;
+
+  /**
+   * Use a non-UTC timezone.
+   */
+  protected static $timezone = 'America/Vancouver';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    static::$date = REQUEST_TIME + 86400;
+
+    // Set the timezone.
+    date_default_timezone_set(static::$timezone);
+
+    // Add some basic test nodes.
+    $dates = array(
+      '2000-10-10',
+      '2001-10-10',
+      '2002-10-10',
+      // The date storage timezone is used (this mimics the steps taken in the
+      // widget: \Drupal\datetime\Plugin\Field\FieldWidget::messageFormValues().
+      \Drupal::service('date.formatter')->format(static::$date, 'custom', DATETIME_DATETIME_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE),
+    );
+    foreach ($dates as $date) {
+      $this->nodes[] = $this->drupalCreateNode(array(
+        'field_date' => array(
+          'value' => $date,
+        )
+      ));
+    }
+  }
+
+  /**
+   * Test filter operations.
+   */
+  public function testDatetimeFilter() {
+    $this->_testOffset();
+    $this->_testBetween();
+    $this->_testExact();
+  }
+
+  /**
+   * Test offset operations.
+   */
+  protected function _testOffset() {
+    $view = Views::getView('test_filter_datetime');
+    $field = static::$field_name . '_value';
+
+    // Test simple operations.
+    $view->initHandlers();
+
+    $view->filter[$field]->operator = '>';
+    $view->filter[$field]->value['type'] = 'offset';
+    $view->filter[$field]->value['value'] = '+1 hour';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[3]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+    // Test offset for between operator.
+    $view->initHandlers();
+    $view->filter[$field]->operator = 'between';
+    $view->filter[$field]->value['type'] = 'offset';
+    $view->filter[$field]->value['max'] = '+2 days';
+    $view->filter[$field]->value['min'] = '+1 hour';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[3]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+  }
+
+  /**
+   *  Test between operations.
+   */
+  protected function _testBetween() {
+    $view = Views::getView('test_filter_datetime');
+    $field = static::$field_name . '_value';
+
+    // Test between with min and max.
+    $view->initHandlers();
+    $view->filter[$field]->operator = 'between';
+    $view->filter[$field]->value['min'] = '2001-01-01';
+    $view->filter[$field]->value['max'] = '2002-01-01';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[1]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+    // Test between with just max.
+    $view->initHandlers();
+    $view->filter[$field]->operator = 'between';
+    $view->filter[$field]->value['max'] = '2002-01-01';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[0]->id()),
+      array('nid' => $this->nodes[1]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+    // Test not between with min and max.
+    $view->initHandlers();
+    $view->filter[$field]->operator = 'not between';
+    $view->filter[$field]->value['min'] = '2001-01-01';
+    $view->filter[$field]->value['max'] = '2002-01-01';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[0]->id()),
+      array('nid' => $this->nodes[2]->id()),
+      array('nid' => $this->nodes[3]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+    // Test not between with just max.
+    $view->initHandlers();
+    $view->filter[$field]->operator = 'not between';
+    $view->filter[$field]->value['max'] = '2001-01-01';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[1]->id()),
+      array('nid' => $this->nodes[2]->id()),
+      array('nid' => $this->nodes[3]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+  }
+
+  /**
+   * Test exact date matching.
+   */
+  protected function _testExact() {
+    $view = Views::getView('test_filter_datetime');
+    $field = static::$field_name . '_value';
+
+    // Test between with min and max.
+    $view->initHandlers();
+    $view->filter[$field]->operator = '=';
+    $view->filter[$field]->value['min'] = '';
+    $view->filter[$field]->value['max'] = '';
+    // Use the date from node 3. Use the site timezone (mimics a value entered
+    // through the UI).
+    $view->filter[$field]->value['value'] = \Drupal::service('date.formatter')->format(static::$date, 'custom', DATETIME_DATETIME_STORAGE_FORMAT, static::$timezone);
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[3]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+  }
+
+}
diff --git a/core/modules/datetime/src/Tests/Views/SortDateTimeTest.php b/core/modules/datetime/src/Tests/Views/SortDateTimeTest.php
new file mode 100644
index 0000000..9c9ddcb
--- /dev/null
+++ b/core/modules/datetime/src/Tests/Views/SortDateTimeTest.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\datetime\Tests\Views\SortDateTimeTest.
+ */
+
+namespace Drupal\datetime\Tests\Views;
+
+use Drupal\views\Views;
+
+/**
+ * Tests for core Drupal\datetime\Plugin\views\sort\Date handler.
+ *
+ * @group datetime
+ */
+class SortDateTimeTest extends DateTimeHandlerTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = array('test_sort_datetime');
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    // Add some basic test nodes.
+    $dates = array(
+      '2014-10-10T00:03:00',
+      '2000-10-10T00:01:00',
+      '2000-10-10T00:02:00',
+      '2000-10-10T00:03:00',
+    );
+    foreach ($dates as $date) {
+      $this->nodes[] = $this->drupalCreateNode(array(
+        'field_date' => array(
+          'value' => $date,
+        )
+      ));
+    }
+  }
+
+  /**
+   * Tests the datetime sort handler.
+   */
+  public function testDateTimeSort() {
+    $field = static::$field_name . '_value';
+    $view = Views::getView('test_sort_datetime');
+
+    // Sort order is DESC.
+    $view->initHandlers();
+    $view->sort[$field]->options['granularity'] = 'minute';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[0]->id()),
+      array('nid' => $this->nodes[3]->id()),
+      array('nid' => $this->nodes[2]->id()),
+      array('nid' => $this->nodes[1]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+    // Check ASC.
+    $view->initHandlers();
+    $field = static::$field_name . '_value';
+    $view->sort[$field]->options['order'] = 'ASC';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[1]->id()),
+      array('nid' => $this->nodes[2]->id()),
+      array('nid' => $this->nodes[3]->id()),
+      array('nid' => $this->nodes[0]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+
+    // Change granularity to 'year', and the secondary node ID order should
+    // define the order of nodes with the same year.
+    $view->initHandlers();
+    $view->sort[$field]->options['granularity'] = 'year';
+    $view->sort[$field]->options['order'] = 'DESC';
+    $view->setDisplay('default');
+    $this->executeView($view);
+    $expected_result = array(
+      array('nid' => $this->nodes[0]->id()),
+      array('nid' => $this->nodes[1]->id()),
+      array('nid' => $this->nodes[2]->id()),
+      array('nid' => $this->nodes[3]->id()),
+    );
+    $this->assertIdenticalResultset($view, $expected_result, $this->map);
+    $view->destroy();
+  }
+
+}
diff --git a/core/modules/datetime/tests/modules/datetime_test/datetime_test.info.yml b/core/modules/datetime/tests/modules/datetime_test/datetime_test.info.yml
new file mode 100644
index 0000000..84ba9e4
--- /dev/null
+++ b/core/modules/datetime/tests/modules/datetime_test/datetime_test.info.yml
@@ -0,0 +1,8 @@
+name: 'Datetime test'
+type: module
+description: 'Provides default views for tests.'
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - views
diff --git a/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_argument_datetime.yml b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_argument_datetime.yml
new file mode 100644
index 0000000..e22ad30
--- /dev/null
+++ b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_argument_datetime.yml
@@ -0,0 +1,99 @@
+langcode: und
+status: true
+dependencies: {  }
+id: test_argument_datetime
+label: ''
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+core: '8'
+display:
+  default:
+    display_options:
+      defaults:
+        fields: false
+        pager: false
+        sorts: false
+      arguments:
+        field_date_value_year:
+          field: field_date_value_year
+          id: field_date_value
+          table: node__field_date
+          plugin_id: datetime_year
+      fields:
+        id:
+          field: nid
+          id: nid
+          relationship: none
+          table: node
+          plugin_id: numeric
+      pager:
+        options:
+          offset: 0
+        type: none
+      sorts:
+        id:
+          field: nid
+          id: nid
+          order: ASC
+          relationship: none
+          table: node
+          plugin_id: numeric
+    display_plugin: default
+    display_title: Master
+    id: default
+    position: 0
+  embed_1:
+    display_options:
+      defaults:
+        arguments: false
+      arguments:
+        field_date_value_month:
+          field: field_date_value_month
+          id: field_date_value
+          table: node__field_date
+          plugin_id: datetime_month
+    display_plugin: embed
+    id: embed_1
+    display_title: ''
+    position: null
+  embed_2:
+    display_options:
+      defaults:
+        arguments: false
+      arguments:
+        field_date_value_day:
+          field: field_date_value_day
+          id: field_date_value
+          table: node__field_date
+          plugin_id: datetime_day
+    display_plugin: embed
+    id: embed_2
+    display_title: ''
+    position: null
+  embed_3:
+    display_options:
+      defaults:
+        arguments: false
+      arguments:
+        field_date_value_year:
+          field: field_date_value_year
+          id: field_date_value
+          table: node__field_date
+          plugin_id: datetime_year
+        field_date_value_month:
+          field: field_date_value_month
+          id: field_date_value
+          table: node__field_date
+          plugin_id: datetime_month
+        field_date_value_day:
+          field: field_date_value_day
+          id: field_date_value
+          table: node__field_date
+          plugin_id: datetime_day
+    display_plugin: embed
+    id: embed_2
+    display_title: ''
+    position: null
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_filter_datetime.yml
similarity index 62%
copy from core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
copy to core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_filter_datetime.yml
index 47556800..c9b23de 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
+++ b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_filter_datetime.yml
@@ -1,9 +1,9 @@
-langcode: en
+langcode: und
 status: true
 dependencies:
   module:
     - node
-id: test_filter_date_between
+id: test_filter_datetime
 label: ''
 module: views
 description: ''
@@ -17,25 +17,29 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
         nid:
           field: nid
           id: nid
-          table: node_field_data
+          table: node
           plugin_id: node
-          entity_type: node
-          entity_field: nid
       filters:
-        created:
-          field: created
-          id: created
-          table: node_field_data
-          plugin_id: date
-          entity_type: node
-          entity_field: created
+        field_date_value:
+          id: field_date_value
+          table: node__field_date
+          field: field_date_value
+          plugin_id: datetime
+      sorts:
+        id:
+          field: nid
+          id: nid
+          order: ASC
+          relationship: none
+          table: node
+          plugin_id: numeric
       pager:
         type: full
       query:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_sort_datetime.yml
similarity index 58%
copy from core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
copy to core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_sort_datetime.yml
index 47556800..8b8d052 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
+++ b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_sort_datetime.yml
@@ -1,9 +1,9 @@
-langcode: en
+langcode: und
 status: true
 dependencies:
   module:
     - node
-id: test_filter_date_between
+id: test_sort_datetime
 label: ''
 module: views
 description: ''
@@ -17,25 +17,30 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
         nid:
           field: nid
           id: nid
-          table: node_field_data
+          table: node
           plugin_id: node
-          entity_type: node
-          entity_field: nid
-      filters:
-        created:
-          field: created
-          id: created
-          table: node_field_data
-          plugin_id: date
-          entity_type: node
-          entity_field: created
+      sorts:
+        field_date_value:
+          field: field_date_value
+          id: field_date_value
+          relationship: none
+          table: node__field_date
+          order: DESC
+          plugin_id: datetime
+        id:
+          field: nid
+          id: nid
+          order: ASC
+          relationship: none
+          table: node
+          plugin_id: numeric
       pager:
         type: full
       query:
diff --git a/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php b/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php
index 9109775..25c7a90 100644
--- a/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php
+++ b/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\dblog\Tests\Rest;
 
 use Drupal\Component\Serialization\Json;
-use Drupal\Core\Url;
 use Drupal\rest\Tests\RESTTestBase;
 
 /**
@@ -46,7 +45,7 @@ public function testWatchdog() {
     $account = $this->drupalCreateUser(array('restful get dblog'));
     $this->drupalLogin($account);
 
-    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => $id, '_format' => $this->defaultFormat]), 'GET');
+    $response = $this->httpRequest("dblog/$id", 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse(200);
     $this->assertHeader('content-type', $this->defaultMimeType);
     $log = Json::decode($response);
@@ -55,7 +54,7 @@ public function testWatchdog() {
     $this->assertEqual($log['message'], 'Test message', 'Log message text is correct.');
 
     // Request an unknown log entry.
-    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 9999, '_format' => $this->defaultFormat]), 'GET');
+    $response = $this->httpRequest("dblog/9999", 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse(404);
     $decoded = Json::decode($response);
     $this->assertEqual($decoded['error'], 'Log entry with ID 9999 was not found', 'Response message is correct.');
diff --git a/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.test_dblog.yml b/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.test_dblog.yml
index d3ebfc8..06dd35f 100644
--- a/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.test_dblog.yml
+++ b/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.test_dblog.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/editor/src/Tests/EditorSecurityTest.php b/core/modules/editor/src/Tests/EditorSecurityTest.php
index 703c65b..305692d 100644
--- a/core/modules/editor/src/Tests/EditorSecurityTest.php
+++ b/core/modules/editor/src/Tests/EditorSecurityTest.php
@@ -409,7 +409,7 @@ function testSwitchingSecurity() {
           'value' => self::$sampleContent,
           'original_format_id' => $case['format'],
         );
-        $response = $this->drupalPostWithFormat('editor/filter_xss/' . $format, 'json', $post);
+        $response = $this->drupalPost('editor/filter_xss/' . $format, 'application/json', $post);
         $this->assertResponse(200);
         $json = Json::decode($response);
         $this->assertIdentical($json, $expected_filtered_value, 'The value was correctly filtered for XSS attack vectors.');
diff --git a/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php b/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php
index 9204f28..c4b81ea 100644
--- a/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php
+++ b/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\editor\Tests;
 
 use Drupal\Component\Serialization\Json;
-use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -89,7 +88,7 @@ public function testUsersWithoutPermission() {
       $this->assertRaw('<p>Do you also love Drupal?</p><figure class="caption caption-img"><img src="druplicon.png" /><figcaption>Druplicon</figcaption></figure>');
 
       // Retrieving the untransformed text should result in an empty 403 response.
-      $response = $this->drupalPost('editor/' . 'node/1/body/en/full', '', array(), array('query' => array(MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax')));
+      $response = $this->drupalPost('editor/' . 'node/1/body/en/full', 'application/vnd.drupal-ajax', array());
       $this->assertResponse(403);
       $this->assertIdentical('{}', $response);
     }
diff --git a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
index be11617..189fed6 100644
--- a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
@@ -131,9 +131,9 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
     $selection_plugins = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionGroups($this->getSetting('target_type'));
     $handlers_options = array();
     foreach (array_keys($selection_plugins) as $selection_group_id) {
-      // We only display base plugins (e.g., 'default', 'views', etc.) and not
-      // entity type specific plugins (e.g., 'default:node', 'default:user',
-      // etc.).
+      // We only display base plugins (e.g. 'default', 'views', ...) and not
+      // entity type specific plugins (e.g. 'default:node', 'default:user',
+      // ...).
       if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
         $handlers_options[$selection_group_id] = SafeMarkup::checkPlain($selection_plugins[$selection_group_id][$selection_group_id]['label']);
       }
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference.yml b/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference.yml
index 919028b..5b6ba8f 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference.yml
@@ -24,7 +24,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference_entity_test.yml b/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference_entity_test.yml
index ec3ab5b..7902c23 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference_entity_test.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test/config/install/views.view.test_entity_reference_entity_test.yml
@@ -23,7 +23,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_mul_view.yml b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_mul_view.yml
index 489ea04..8f81302 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_mul_view.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_mul_view.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_view.yml b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_view.yml
index 291b474..bb381c2 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_view.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_entity_test_view.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_mul_view.yml b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_mul_view.yml
index 33911a6..993d843 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_mul_view.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_mul_view.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_view.yml b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_view.yml
index c281ef5c..f7c25ab 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_view.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_reverse_entity_test_view.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 88ccff9..1ebea04 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -7,6 +7,7 @@
 use Drupal\Core\Config\ConfigImporter;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface;
+use Drupal\Core\Extension\Extension;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
@@ -145,6 +146,40 @@ function field_cron() {
 }
 
 /**
+ * Implements hook_system_info_alter().
+ *
+ * Goes through a list of all modules that provide a field type and makes them
+ * required if there are any active fields of that type.
+ */
+function field_system_info_alter(&$info, Extension $file, $type) {
+  // It is not safe to call entity_load_multiple_by_properties() during
+  // maintenance mode.
+  if ($type == 'module' && !defined('MAINTENANCE_MODE')) {
+    $field_storages = entity_load_multiple_by_properties('field_storage_config', array('module' => $file->getName(), 'include_deleted' => TRUE));
+    if ($field_storages) {
+      $info['required'] = TRUE;
+
+      // Provide an explanation message (only mention pending deletions if there
+      // remains no actual, non-deleted fields)
+      $non_deleted = FALSE;
+      foreach ($field_storages as $field_storage) {
+        if (!$field_storage->isDeleted()) {
+          $non_deleted = TRUE;
+          break;
+        }
+      }
+      if ($non_deleted) {
+        $explanation = t('Fields type(s) in use');
+      }
+      else {
+        $explanation = t('Fields pending deletion');
+      }
+      $info['explanation'] = $explanation;
+    }
+  }
+}
+
+/**
  * Implements hook_entity_field_storage_info().
  */
 function field_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
diff --git a/core/modules/field/field.services.yml b/core/modules/field/field.services.yml
deleted file mode 100644
index 6c2187a..0000000
--- a/core/modules/field/field.services.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
-  field.uninstall_validator:
-    class: Drupal\field\FieldUninstallValidator
-    tags:
-      - { name: module_install.uninstall_validator }
-    arguments: ['@entity.manager', '@string_translation']
-    lazy: true
diff --git a/core/modules/field/src/FieldStorageConfigStorage.php b/core/modules/field/src/FieldStorageConfigStorage.php
index 4e7a280..55800b3 100644
--- a/core/modules/field/src/FieldStorageConfigStorage.php
+++ b/core/modules/field/src/FieldStorageConfigStorage.php
@@ -16,7 +16,7 @@
 use Drupal\Core\Language\LanguageManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ModuleHandler;
 use Drupal\Core\State\StateInterface;
 
 /**
@@ -27,7 +27,7 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
   /**
    * The module handler.
    *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   * @var \Drupal\Core\Extension\ModuleHandler
    */
   protected $moduleHandler;
 
@@ -65,14 +65,14 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
    *   The language manager.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   * @param \Drupal\Core\Extension\ModuleHandler $module_handler
    *   The module handler.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state key value store.
    * @param \Drupal\Component\Plugin\PluginManagerInterface\FieldTypePluginManagerInterface
    *   The field type plugin manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
+  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
     parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
     $this->entityManager = $entity_manager;
     $this->moduleHandler = $module_handler;
diff --git a/core/modules/field/src/FieldUninstallValidator.php b/core/modules/field/src/FieldUninstallValidator.php
deleted file mode 100644
index 3302b04..0000000
--- a/core/modules/field/src/FieldUninstallValidator.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\field\FieldUninstallValidator.
- */
-
-namespace Drupal\field;
-
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-
-/**
- * Prevents uninstallation of modules providing active field storage.
- */
-class FieldUninstallValidator implements ModuleUninstallValidatorInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The field storage config storage.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected $fieldStorageConfigStorage;
-
-  /**
-   * Constructs a new FieldUninstallValidator.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   */
-  public function __construct(EntityManagerInterface $entity_manager, TranslationInterface $string_translation) {
-    $this->fieldStorageConfigStorage = $entity_manager->getStorage('field_storage_config');
-    $this->stringTranslation = $string_translation;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($module) {
-    $reasons = [];
-    if ($field_storages = $this->getFieldStoragesByModule($module)) {
-      // Provide an explanation message (only mention pending deletions if there
-      // remain no actual, non-deleted fields.)
-      $non_deleted = FALSE;
-      foreach ($field_storages as $field_storage) {
-        if (!$field_storage->isDeleted()) {
-          $non_deleted = TRUE;
-          break;
-        }
-      }
-      if ($non_deleted) {
-        $reasons[] = $this->t('Fields type(s) in use');
-      }
-      else {
-        $reasons[] = $this->t('Fields pending deletion');
-      }
-    }
-    return $reasons;
-  }
-
-  /**
-   * Returns all field storages for a specified module.
-   *
-   * @param string $module
-   *   The module to filter field storages by.
-   *
-   * @return \Drupal\field\FieldStorageConfigInterface[]
-   *   An array of field storages for a specified module.
-   */
-  protected function getFieldStoragesByModule($module) {
-    return $this->fieldStorageConfigStorage->loadByProperties(['module' => $module, 'include_deleted' => TRUE]);
-  }
-
-}
diff --git a/core/modules/field/src/Tests/FormTest.php b/core/modules/field/src/Tests/FormTest.php
index 564e300..748d2ac 100644
--- a/core/modules/field/src/Tests/FormTest.php
+++ b/core/modules/field/src/Tests/FormTest.php
@@ -259,7 +259,7 @@ function testFieldFormUnlimited() {
     $this->assertFieldByName("{$field_name}[0][value]", '', 'Widget 1 is displayed');
     $this->assertFieldByName("{$field_name}[1][value]", '', 'New widget is displayed');
     $this->assertNoField("{$field_name}[2][value]", 'No extraneous widget is displayed');
-    // TODO : check that non-field inputs are preserved ('title'), etc.
+    // TODO : check that non-field inputs are preserved ('title')...
 
     // Yet another time so that we can play with more values -> 3 widgets.
     $this->drupalPostForm(NULL, array(), t('Add another item'));
diff --git a/core/modules/field/src/Tests/reEnableModuleFieldTest.php b/core/modules/field/src/Tests/reEnableModuleFieldTest.php
index 42fcc2b..cbbf386 100644
--- a/core/modules/field/src/Tests/reEnableModuleFieldTest.php
+++ b/core/modules/field/src/Tests/reEnableModuleFieldTest.php
@@ -92,10 +92,10 @@ function testReEnabledField() {
     // for it's fields.
     $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules'));
     $this->drupalLogin($admin_user);
-    $this->drupalGet('admin/modules/uninstall');
+    $this->drupalGet('admin/modules');
     $this->assertText('Fields type(s) in use');
     $field_storage->delete();
-    $this->drupalGet('admin/modules/uninstall');
+    $this->drupalGet('admin/modules');
     $this->assertText('Fields pending deletion');
     $this->cronRun();
     $this->assertNoText('Fields type(s) in use');
diff --git a/core/modules/field/tests/modules/field_test_views/test_views/views.view.test_view_fieldapi.yml b/core/modules/field/tests/modules/field_test_views/test_views/views.view.test_view_fieldapi.yml
index 869e441..e5098e3 100644
--- a/core/modules/field/tests/modules/field_test_views/test_views/views.view.test_view_fieldapi.yml
+++ b/core/modules/field/tests/modules/field_test_views/test_views/views.view.test_view_fieldapi.yml
@@ -47,7 +47,7 @@ display:
           entity_type: node
           entity_field: field_no_view_access
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/field/tests/src/Unit/FieldUninstallValidatorTest.php b/core/modules/field/tests/src/Unit/FieldUninstallValidatorTest.php
deleted file mode 100644
index ea9e0c8..0000000
--- a/core/modules/field/tests/src/Unit/FieldUninstallValidatorTest.php
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\field\Unit\FieldUninstallValidatorTest.
- */
-
-namespace Drupal\Tests\field\Unit;
-
-use Drupal\Tests\UnitTestCase;
-
-/**
- * @coversDefaultClass \Drupal\field\FieldUninstallValidator
- * @group field
- */
-class FieldUninstallValidatorTest extends UnitTestCase {
-
-  /**
-   * @var \Drupal\field\FieldUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $fieldUninstallValidator;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->fieldUninstallValidator = $this->getMockBuilder('Drupal\field\FieldUninstallValidator')
-      ->disableOriginalConstructor()
-      ->setMethods(['getFieldStoragesByModule'])
-      ->getMock();
-    $this->fieldUninstallValidator->setStringTranslation($this->getStringTranslationStub());
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNoStorages() {
-    $this->fieldUninstallValidator->expects($this->once())
-      ->method('getFieldStoragesByModule')
-      ->willReturn([]);
-
-    $module = $this->randomMachineName();
-    $expected = [];
-    $reasons = $this->fieldUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateDeleted() {
-    $field_storage = $this->getMockBuilder('Drupal\field\Entity\FieldStorageConfig')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $field_storage->expects($this->once())
-      ->method('isDeleted')
-      ->willReturn(TRUE);
-    $this->fieldUninstallValidator->expects($this->once())
-      ->method('getFieldStoragesByModule')
-      ->willReturn([$field_storage]);
-
-    $module = $this->randomMachineName();
-    $expected = ['Fields pending deletion'];
-    $reasons = $this->fieldUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNoDeleted() {
-    $field_storage = $this->getMockBuilder('Drupal\field\Entity\FieldStorageConfig')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $field_storage->expects($this->once())
-      ->method('isDeleted')
-      ->willReturn(FALSE);
-    $this->fieldUninstallValidator->expects($this->once())
-      ->method('getFieldStoragesByModule')
-      ->willReturn([$field_storage]);
-
-    $module = $this->randomMachineName();
-    $expected = ['Fields type(s) in use'];
-    $reasons = $this->fieldUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-}
diff --git a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
index d675cef..61cfd0c 100644
--- a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
+++ b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
@@ -238,9 +238,9 @@ public function form(array $form, FormStateInterface $form_state) {
       '#type' => 'submit',
       '#value' => $this->t('Refresh'),
       '#op' => 'refresh_table',
-      '#submit' => array('::multistepSubmit'),
+      '#submit' => array(array($this, 'multistepSubmit')),
       '#ajax' => array(
-        'callback' => '::multistepAjax',
+        'callback' => array($this, 'multistepAjax'),
         'wrapper' => 'field-display-overview-wrapper',
         'effect' => 'fade',
         // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc
@@ -316,6 +316,7 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, arr
           '#attributes' => array('class' => array('field-name')),
         ),
       ),
+
     );
 
     $field_row['plugin'] = array(
@@ -331,14 +332,27 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, arr
       'settings_edit_form' => array(),
     );
 
+    // Check the currently selected plugin, and merge persisted values for its
+    // settings.
+    if ($display_type = $form_state->getValue(array('fields', $field_name, 'type'))) {
+      $display_options['type'] = $display_type;
+    }
+    $plugin_settings = $form_state->get('plugin_settings');
+    if (isset($plugin_settings[$field_name]['settings'])) {
+      $display_options['settings'] = $plugin_settings[$field_name]['settings'];
+    }
+    if (isset($plugin_settings[$field_name]['third_party_settings'])) {
+      $display_options['third_party_settings'] = $plugin_settings[$field_name]['third_party_settings'];
+    }
+
     // Get the corresponding plugin object.
-    $plugin = $this->entity->getRenderer($field_name);
+    $plugin = $this->getPlugin($field_definition, $display_options);
 
     // Base button element for the various plugin settings actions.
     $base_button = array(
-      '#submit' => array('::multistepSubmit'),
+      '#submit' => array(array($this, 'multistepSubmit')),
       '#ajax' => array(
-        'callback' => '::multistepAjax',
+        'callback' => array($this, 'multistepAjax'),
         'wrapper' => 'field-display-overview-wrapper',
         'effect' => 'fade',
       ),
@@ -503,13 +517,6 @@ protected function buildExtraFieldRow($field_id, $extra_field) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
-    // If the main "Save" button was submitted while a field settings subform
-    // was being edited, update the new incoming settings when rebuilding the
-    // entity, just as if the subform's "Update" button had been submitted.
-    if ($edit_field = $form_state->get('plugin_settings_edit')) {
-      $form_state->set('plugin_settings_update', $edit_field);
-    }
-
     parent::submitForm($form, $form_state);
     $form_values = $form_state->getValues();
 
@@ -555,30 +562,57 @@ protected function copyFormValuesToEntity(EntityInterface $entity, array $form,
 
     // Collect data for 'regular' fields.
     foreach ($form['#fields'] as $field_name) {
+      // Retrieve the stored field settings to merge with the incoming
+      // values.
       $values = $form_values['fields'][$field_name];
 
       if ($values['type'] == 'hidden') {
         $entity->removeComponent($field_name);
       }
       else {
-        $options = $entity->getComponent($field_name);
-
-        // Update field settings only if the submit handler told us to.
-        if ($form_state->get('plugin_settings_update') === $field_name) {
-          // Only store settings actually used by the selected plugin.
-          $default_settings = $this->pluginManager->getDefaultSettings($options['type']);
-          $options['settings'] = array_intersect_key($values['settings_edit_form']['settings'], $default_settings);
-          $options['third_party_settings'] = isset($values['settings_edit_form']['third_party_settings']) ? $values['settings_edit_form']['third_party_settings'] : [];
-          $form_state->set('plugin_settings_update', NULL);
+        // Get plugin settings. They lie either directly in submitted form
+        // values (if the whole form was submitted while some plugin settings
+        // were being edited), or have been persisted in $form_state.
+        $plugin_settings = $form_state->get('plugin_settings');
+        $settings = array();
+        if (isset($values['settings_edit_form']['settings'])) {
+          $settings = $values['settings_edit_form']['settings'];
+        }
+        elseif (isset($plugin_settings[$field_name]['settings'])) {
+          $settings = $plugin_settings[$field_name]['settings'];
+        }
+        elseif ($current_options = $entity->getComponent($field_name)) {
+          $settings = $current_options['settings'];
+        }
+        $third_party_settings = array();
+        if (isset($values['settings_edit_form']['third_party_settings'])) {
+          $third_party_settings = $values['settings_edit_form']['third_party_settings'];
+        }
+        elseif (isset($plugin_settings[$field_name]['third_party_settings'])) {
+          $third_party_settings = $plugin_settings[$field_name]['third_party_settings'];
+        }
+        elseif (($current_options = $entity->getComponent($field_name)) && isset($current_options['third_party_settings'])) {
+          $third_party_settings = $current_options['third_party_settings'];
         }
 
-        $options['type'] = $values['type'];
-        $options['weight'] = $values['weight'];
+        // Only save settings actually used by the selected plugin.
+        $default_settings = $this->pluginManager->getDefaultSettings($values['type']);
+        $settings = array_intersect_key($settings, $default_settings);
+
+        // Default component values.
+        $component_values = array(
+          'type' => $values['type'],
+          'weight' => $values['weight'],
+          'settings' => $settings,
+          'third_party_settings' => $third_party_settings,
+        );
+
         // Only formatters have configurable label visibility.
         if (isset($values['label'])) {
-          $options['label'] = $values['label'];
+          $component_values['label'] = $values['label'];
         }
-        $entity->setComponent($field_name, $options);
+
+        $entity->setComponent($field_name, $component_values);
       }
     }
 
@@ -610,12 +644,15 @@ public function multistepSubmit($form, FormStateInterface $form_state) {
         break;
 
       case 'update':
-        // Set the field back to 'non edit' mode, and update $this->entity with
-        // the new settings fro the next rebuild.
+        // Store the saved settings, and set the field back to 'non edit' mode.
         $field_name = $trigger['#field_name'];
+        if ($plugin_settings = $form_state->getValue(array('fields', $field_name, 'settings_edit_form', 'settings'))) {
+          $form_state->set(['plugin_settings', $field_name, 'settings'], $plugin_settings);
+        }
+        if ($plugin_third_party_settings = $form_state->getValue(array('fields', $field_name, 'settings_edit_form', 'third_party_settings'))) {
+          $form_state->set(['plugin_settings', $field_name, 'third_party_settings'], $plugin_third_party_settings);
+        }
         $form_state->set('plugin_settings_edit', NULL);
-        $form_state->set('plugin_settings_update', $field_name);
-        $this->entity = $this->buildEntity($form, $form_state);
         break;
 
       case 'cancel':
@@ -629,6 +666,7 @@ public function multistepSubmit($form, FormStateInterface $form_state) {
         $updated_rows = explode(' ', $form_state->getValue('refresh_rows'));
         $plugin_settings_edit = $form_state->get('plugin_settings_edit');
         if ($plugin_settings_edit && in_array($plugin_settings_edit, $updated_rows)) {
+
           $form_state->set('plugin_settings_edit', NULL);
         }
         break;
@@ -819,6 +857,19 @@ protected function getExtraFields() {
   abstract protected function getEntityDisplay($entity_type_id, $bundle, $mode);
 
   /**
+   * Returns the widget or formatter plugin for a field.
+   *
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The field.
+   * @param array $configuration
+   *   The plugin configuration
+   *
+   * @return object
+   *   The corresponding plugin.
+   */
+  abstract protected function getPlugin(FieldDefinitionInterface $field_definition, $configuration);
+
+  /**
    * Returns an array of widget or formatter options for a field.
    *
    * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
diff --git a/core/modules/field_ui/src/Form/EntityFormDisplayEditForm.php b/core/modules/field_ui/src/Form/EntityFormDisplayEditForm.php
index 7ddd9f4..cb2086d 100644
--- a/core/modules/field_ui/src/Form/EntityFormDisplayEditForm.php
+++ b/core/modules/field_ui/src/Form/EntityFormDisplayEditForm.php
@@ -62,6 +62,23 @@ protected function getEntityDisplay($entity_type_id, $bundle, $mode) {
   /**
    * {@inheritdoc}
    */
+  protected function getPlugin(FieldDefinitionInterface $field_definition, $configuration) {
+    $plugin = NULL;
+
+    if ($configuration && $configuration['type'] != 'hidden') {
+      $plugin = $this->pluginManager->getInstance(array(
+        'field_definition' => $field_definition,
+        'form_mode' => $this->entity->getMode(),
+        'configuration' => $configuration
+      ));
+    }
+
+    return $plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   protected function getDefaultPlugin($field_type) {
     return isset($this->fieldTypes[$field_type]['default_widget']) ? $this->fieldTypes[$field_type]['default_widget'] : NULL;
   }
diff --git a/core/modules/field_ui/src/Form/EntityViewDisplayEditForm.php b/core/modules/field_ui/src/Form/EntityViewDisplayEditForm.php
index 4c5766f..84331f2 100644
--- a/core/modules/field_ui/src/Form/EntityViewDisplayEditForm.php
+++ b/core/modules/field_ui/src/Form/EntityViewDisplayEditForm.php
@@ -95,6 +95,23 @@ protected function getEntityDisplay($entity_type_id, $bundle, $mode) {
   /**
    * {@inheritdoc}
    */
+  protected function getPlugin(FieldDefinitionInterface $field_definition, $configuration) {
+    $plugin = NULL;
+
+    if ($configuration && $configuration['type'] != 'hidden') {
+      $plugin = $this->pluginManager->getInstance(array(
+        'field_definition' => $field_definition,
+        'view_mode' => $this->entity->getMode(),
+        'configuration' => $configuration
+      ));
+    }
+
+    return $plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   protected function getDefaultPlugin($field_type) {
     return isset($this->fieldTypes[$field_type]['default_formatter']) ? $this->fieldTypes[$field_type]['default_formatter'] : NULL;
   }
diff --git a/core/modules/file/config/optional/views.view.files.yml b/core/modules/file/config/optional/views.view.files.yml
index 5e727fb..fc1b540 100644
--- a/core/modules/file/config/optional/views.view.files.yml
+++ b/core/modules/file/config/optional/views.view.files.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access files overview'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index 782ae70..2578844 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -27,8 +27,8 @@ function template_preprocess_file_widget(&$variables) {
     $element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
   }
   $variables['element'] = $element;
-  // The "js-form-managed-file" class is required for proper Ajax functionality.
-  $variables['attributes'] = array('class' => array('file-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
+  // The "form-managed-file" class is required for proper Ajax functionality.
+  $variables['attributes'] = array('class' => array('file-widget', 'form-managed-file', 'clearfix'));
 }
 
 /**
diff --git a/core/modules/file/file.js b/core/modules/file/file.js
index 5a4aea8..ec607fc 100644
--- a/core/modules/file/file.js
+++ b/core/modules/file/file.js
@@ -74,12 +74,12 @@ function removeFileValidation(selector) {
     attach: function (context) {
       var $context = $(context);
       $context.find('.js-form-submit').on('mousedown', Drupal.file.disableFields);
-      $context.find('.js-form-managed-file .js-form-submit').on('mousedown', Drupal.file.progressBar);
+      $context.find('.form-managed-file .js-form-submit').on('mousedown', Drupal.file.progressBar);
     },
     detach: function (context) {
       var $context = $(context);
       $context.find('.js-form-submit').off('mousedown', Drupal.file.disableFields);
-      $context.find('.js-form-managed-file .js-form-submit').off('mousedown', Drupal.file.progressBar);
+      $context.find('.form-managed-file .js-form-submit').off('mousedown', Drupal.file.progressBar);
     }
   };
 
@@ -90,10 +90,10 @@ function removeFileValidation(selector) {
    */
   Drupal.behaviors.filePreviewLinks = {
     attach: function (context) {
-      $(context).find('div.js-form-managed-file .file a, .file-widget .file a').on('click', Drupal.file.openInNewWindow);
+      $(context).find('div.form-managed-file .file a, .file-widget .file a').on('click', Drupal.file.openInNewWindow);
     },
     detach: function (context) {
-      $(context).find('div.js-form-managed-file .file a, .file-widget .file a').off('click', Drupal.file.openInNewWindow);
+      $(context).find('div.form-managed-file .file a, .file-widget .file a').off('click', Drupal.file.openInNewWindow);
     }
   };
 
@@ -132,7 +132,7 @@ function removeFileValidation(selector) {
             '%filename': this.value.replace('C:\\fakepath\\', ''),
             '%extensions': extensionPattern.replace(/\|/g, ', ')
           });
-          $(this).closest('div.js-form-managed-file').prepend('<div class="messages messages--error file-upload-js-error" aria-live="polite">' + error + '</div>');
+          $(this).closest('div.form-managed-file').prepend('<div class="messages messages--error file-upload-js-error" aria-live="polite">' + error + '</div>');
           this.value = '';
           // Cancel all other change event handlers.
           event.stopImmediatePropagation();
@@ -148,7 +148,7 @@ function removeFileValidation(selector) {
      * @param {jQuery.Event} event
      */
     triggerUploadButton: function (event) {
-      $(event.target).closest('.js-form-managed-file').find('.js-form-submit').trigger('mousedown');
+      $(event.target).closest('.form-managed-file').find('.js-form-submit').trigger('mousedown');
     },
 
     /**
@@ -168,8 +168,8 @@ function removeFileValidation(selector) {
 
       // Check if we're working with an "Upload" button.
       var $enabledFields = [];
-      if ($clickedButton.closest('div.js-form-managed-file').length > 0) {
-        $enabledFields = $clickedButton.closest('div.js-form-managed-file').find('input.js-form-file');
+      if ($clickedButton.closest('div.form-managed-file').length > 0) {
+        $enabledFields = $clickedButton.closest('div.form-managed-file').find('input.form-file');
       }
 
       // Temporarily disable upload fields other than the one we're currently
@@ -181,7 +181,7 @@ function removeFileValidation(selector) {
       // functions are called, so we don't have to worry about the fields being
       // re-enabled too soon. @todo If the previous sentence is true, why not
       // set the timeout to 0?
-      var $fieldsToTemporarilyDisable = $('div.js-form-managed-file input.js-form-file').not($enabledFields).not(':disabled');
+      var $fieldsToTemporarilyDisable = $('div.form-managed-file input.form-file').not($enabledFields).not(':disabled');
       $fieldsToTemporarilyDisable.prop('disabled', true);
       setTimeout(function () {
         $fieldsToTemporarilyDisable.prop('disabled', false);
@@ -197,7 +197,7 @@ function removeFileValidation(selector) {
      */
     progressBar: function (event) {
       var $clickedButton = $(this);
-      var $progressId = $clickedButton.closest('div.js-form-managed-file').find('input.file-progress');
+      var $progressId = $clickedButton.closest('div.form-managed-file').find('input.file-progress');
       if ($progressId.length) {
         var originalName = $progressId.attr('name');
 
@@ -211,7 +211,7 @@ function removeFileValidation(selector) {
       }
       // Show the progress bar if the upload takes longer than half a second.
       setTimeout(function () {
-        $clickedButton.closest('div.js-form-managed-file').find('div.ajax-progress-bar').slideDown();
+        $clickedButton.closest('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
       }, 500);
     },
 
diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
index 0631289..56804af 100644
--- a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
@@ -192,6 +192,7 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#title' => t('Enable <em>Description</em> field'),
       '#default_value' => isset($settings['description_field']) ? $settings['description_field'] : '',
       '#description' => t('The description field allows users to enter a description about the uploaded file.'),
+      '#parents' => array('instance', 'settings', 'description_field'),
       '#weight' => 11,
     );
 
diff --git a/core/modules/file/src/Tests/FileFieldDisplayTest.php b/core/modules/file/src/Tests/FileFieldDisplayTest.php
index 900374c..f1a3f8a 100644
--- a/core/modules/file/src/Tests/FileFieldDisplayTest.php
+++ b/core/modules/file/src/Tests/FileFieldDisplayTest.php
@@ -120,44 +120,4 @@ function testDefaultFileFieldDisplay() {
     $this->assertFieldByXPath('//input[@type="checkbox" and @name="' . $field_name . '[0][display]"]', NULL, 'Default file display checkbox field exists.');
     $this->assertFieldByXPath('//input[@type="checkbox" and @name="' . $field_name . '[0][display]" and not(@checked)]', NULL, 'Default file display is off.');
   }
-
-  /**
-   * Tests description toggle for field instance configuration.
-   */
-  function testDescToggle() {
-    $type_name = 'test';
-    $field_type = 'file';
-    $field_name = strtolower($this->randomMachineName());
-    // Use the UI to add a new content type that also contains a file field.
-    $edit = array(
-      'name' => $type_name,
-      'type' => $type_name,
-    );
-    $this->drupalPostForm('admin/structure/types/add', $edit, t('Save and manage fields'));
-    $edit = array(
-      'new_storage_type' => $field_type,
-      'field_name' => $field_name,
-      'label' => $this->randomString(),
-    );
-    $this->drupalPostForm('/admin/structure/types/manage/' . $type_name . '/fields/add-field', $edit, t('Save and continue'));
-    $this->drupalPostForm(NULL, array(), t('Save field settings'));
-    // Ensure the description field is selected on the field instance settings
-    // form. That's what this test is all about.
-    $edit = array(
-      'settings[description_field]' => TRUE,
-    );
-    $this->drupalPostForm(NULL, $edit, t('Save settings'));
-    // Add a node of our new type and upload a file to it.
-    $file = current($this->drupalGetTestFiles('text'));
-    $title = $this->randomString();
-    $edit = array(
-      'title[0][value]' => $title,
-      'files[field_' . $field_name . '_0]' => drupal_realpath($file->uri),
-    );
-    $this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
-    $node = $this->drupalGetNodeByTitle($title);
-    $this->drupalGet('node/' . $node->id() . '/edit');
-    $this->assertText(t('The description may be used as the label of the link to the file.'));
-  }
-
 }
diff --git a/core/modules/file/templates/file-managed-file.html.twig b/core/modules/file/templates/file-managed-file.html.twig
index 39de9b4..7a87511 100644
--- a/core/modules/file/templates/file-managed-file.html.twig
+++ b/core/modules/file/templates/file-managed-file.html.twig
@@ -12,12 +12,6 @@
  * @ingroup themeable
  */
 #}
-{%
-  set classes = [
-    'js-form-managed-file',
-    'form-managed-file',
-  ]
-%}
-<div{{ attributes.addClass(classes) }}>
+<div{{ attributes.addClass('form-managed-file') }}>
   {{ element }}
 </div>
diff --git a/core/modules/file/tests/file_test/src/StreamWrapper/DummyReadOnlyStreamWrapper.php b/core/modules/file/tests/file_test/src/StreamWrapper/DummyReadOnlyStreamWrapper.php
index cb8a6aa..99cf3e8 100644
--- a/core/modules/file/tests/file_test/src/StreamWrapper/DummyReadOnlyStreamWrapper.php
+++ b/core/modules/file/tests/file_test/src/StreamWrapper/DummyReadOnlyStreamWrapper.php
@@ -31,7 +31,7 @@ public function getDescription() {
   }
 
   function getDirectoryPath() {
-    return \Drupal::service('site.path') . '/files';
+    return conf_path() . '/files';
   }
 
   /**
diff --git a/core/modules/file/tests/file_test/src/StreamWrapper/DummyStreamWrapper.php b/core/modules/file/tests/file_test/src/StreamWrapper/DummyStreamWrapper.php
index b2b6900..2ed31d0 100644
--- a/core/modules/file/tests/file_test/src/StreamWrapper/DummyStreamWrapper.php
+++ b/core/modules/file/tests/file_test/src/StreamWrapper/DummyStreamWrapper.php
@@ -31,7 +31,7 @@ public function getDescription() {
   }
 
   function getDirectoryPath() {
-    return \Drupal::service('site.path') . '/files';
+    return conf_path() . '/files';
   }
 
   /**
diff --git a/core/modules/file/tests/modules/file_test_views/test_views/views.view.test_file_user_file_data.yml b/core/modules/file/tests/modules/file_test_views/test_views/views.view.test_file_user_file_data.yml
index 1b630e4..4404085 100644
--- a/core/modules/file/tests/modules/file_test_views/test_views/views.view.test_file_user_file_data.yml
+++ b/core/modules/file/tests/modules/file_test_views/test_views/views.view.test_file_user_file_data.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access user profiles'
       cache:
-        type: tag
+        type: none
       style:
         type: table
         options:
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 400d6cc..afdaadf 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -83,6 +84,44 @@ function filter_theme() {
 }
 
 /**
+ * Implements hook_system_info_alter().
+ *
+ * Prevents uninstallation of modules that provide filter plugins that are being
+ * used in a filter format.
+ */
+function filter_system_info_alter(&$info, Extension $file, $type) {
+  // It is not safe to call filter_formats() during maintenance mode.
+  if ($type == 'module' && !defined('MAINTENANCE_MODE')) {
+    // Get filter plugins supplied by this module.
+    $filter_plugins = array_filter(\Drupal::service('plugin.manager.filter')->getDefinitions(), function ($definition) use ($file) {
+      return $definition['provider'] == $file->getName();
+    });
+    if (!empty($filter_plugins)) {
+      $used_in = [];
+      // Find out if any filter formats have the plugin enabled.
+      foreach (filter_formats() as $filter_format) {
+        $filters = $filter_format->filters();
+        // Typically, all formats will contain settings for all filter plugins,
+        // even if they are disabled. However, if a module which provides filter
+        // plugins is being enabled right now, that won't be the case, so we
+        // still check to see if this format has this filter before we check
+        // the filter status.
+       foreach ($filter_plugins as $filter_plugin) {
+          if ($filters->has($filter_plugin['id']) && $filters->get($filter_plugin['id'])->status) {
+            $used_in[] = $filter_format->label();
+            $info['required'] = TRUE;
+            break;
+          }
+        }
+      }
+      if (!empty($used_in)) {
+        $info['explanation'] = t('Provides a filter plugin that is in use in the following filter formats: %formats', array('%formats' => implode(', ', $used_in)));
+      }
+    }
+  }
+}
+
+/**
  * Retrieves a list of enabled text formats, ordered by weight.
  *
  * @param \Drupal\Core\Session\AccountInterface|null $account
diff --git a/core/modules/filter/filter.services.yml b/core/modules/filter/filter.services.yml
index 996304a..406161a 100644
--- a/core/modules/filter/filter.services.yml
+++ b/core/modules/filter/filter.services.yml
@@ -2,10 +2,3 @@ services:
   plugin.manager.filter:
     class: Drupal\filter\FilterPluginManager
     parent: default_plugin_manager
-
-  filter.uninstall_validator:
-    class: Drupal\filter\FilterUninstallValidator
-    tags:
-      - { name: module_install.uninstall_validator }
-    arguments: ['@plugin.manager.filter', '@entity.manager', '@string_translation']
-    lazy: true
diff --git a/core/modules/filter/src/FilterUninstallValidator.php b/core/modules/filter/src/FilterUninstallValidator.php
deleted file mode 100644
index 74e04b0..0000000
--- a/core/modules/filter/src/FilterUninstallValidator.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\filter\FilterUninstallValidator.
- */
-
-namespace Drupal\filter;
-
-use Drupal\Component\Plugin\PluginManagerInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-
-/**
- * Prevents uninstallation of modules providing used filter plugins.
- */
-class FilterUninstallValidator implements ModuleUninstallValidatorInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The filter plugin manager.
-   *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
-   */
-  protected $filterManager;
-
-  /**
-   * The filter entity storage.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected $filterStorage;
-
-  /**
-   * Constructs a new FilterUninstallValidator.
-   *
-   * @param \Drupal\Component\Plugin\PluginManagerInterface $filter_manager
-   *   The filter plugin manager.
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   */
-  public function __construct(PluginManagerInterface $filter_manager, EntityManagerInterface $entity_manager, TranslationInterface $string_translation) {
-    $this->filterManager = $filter_manager;
-    $this->filterStorage = $entity_manager->getStorage('filter_format');
-    $this->stringTranslation = $string_translation;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($module) {
-    $reasons = [];
-    // Get filter plugins supplied by this module.
-    if ($filter_plugins = $this->getFilterDefinitionsByProvider($module)) {
-      $used_in = [];
-      // Find out if any filter formats have the plugin enabled.
-      foreach ($this->getEnabledFilterFormats() as $filter_format) {
-        $filters = $filter_format->filters();
-        foreach ($filter_plugins as $filter_plugin) {
-          if ($filters->has($filter_plugin['id']) && $filters->get($filter_plugin['id'])->status) {
-            $used_in[] = $filter_format->label();
-            break;
-          }
-        }
-      }
-      if (!empty($used_in)) {
-        $reasons[] = $this->t('Provides a filter plugin that is in use in the following filter formats: %formats', ['%formats' => implode(', ', $used_in)]);
-      }
-    }
-    return $reasons;
-  }
-
-  /**
-   * Returns all filter definitions that are provided by the specified provider.
-   *
-   * @param string $provider
-   *   The provider of the filters.
-   *
-   * @return array
-   *   The filter definitions for the specified provider.
-   */
-  protected function getFilterDefinitionsByProvider($provider) {
-    return array_filter($this->filterManager->getDefinitions(), function ($definition) use ($provider) {
-      return $definition['provider'] == $provider;
-    });
-  }
-
-  /**
-   * Returns all enabled filter formats.
-   *
-   * @return \Drupal\filter\FilterFormatInterface[]
-   */
-  protected function getEnabledFilterFormats() {
-    return $this->filterStorage->loadByProperties(['status' => TRUE]);
-  }
-
-}
diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php
index ff23d39..c0bf1d5 100644
--- a/core/modules/filter/src/Tests/FilterAPITest.php
+++ b/core/modules/filter/src/Tests/FilterAPITest.php
@@ -417,6 +417,18 @@ public function testDependencyRemoval() {
     $this->installSchema('user', array('users_data'));
     $filter_format = \Drupal\filter\Entity\FilterFormat::load('filtered_html');
 
+    // Enable the filter_test_restrict_tags_and_attributes filter plugin on the
+    // filtered_html filter format.
+    $filter_config = [
+      'weight' => 10,
+      'status' => 1,
+    ];
+    $filter_format->setFilterConfig('filter_test_restrict_tags_and_attributes', $filter_config)->save();
+
+    $module_data = _system_rebuild_module_data();
+    $this->assertTrue($module_data['filter_test']->info['required'], 'The filter_test module is required.');
+    $this->assertEqual($module_data['filter_test']->info['explanation'], SafeMarkup::format('Provides a filter plugin that is in use in the following filter formats: %formats', array('%formats' => $filter_format->label())));
+
     // Disable the filter_test_restrict_tags_and_attributes filter plugin but
     // have custom configuration so that the filter plugin is still configured
     // in filtered_html the filter format.
diff --git a/core/modules/filter/src/Tests/FilterUnitTest.php b/core/modules/filter/src/Tests/FilterUnitTest.php
index e4eeb33..0e6c3c4 100644
--- a/core/modules/filter/src/Tests/FilterUnitTest.php
+++ b/core/modules/filter/src/Tests/FilterUnitTest.php
@@ -582,7 +582,7 @@ function testUrlFilter() {
       ),
       // Absolute URL protocols.
       // The list to test is found in the beginning of _filter_url() at
-      // $protocols = $this->config('system.filter')->get('protocols').
+      // $protocols = $this->config('system.filter')->get('protocols')... (approx line 1555).
       '
 https://example.com,
 ftp://ftp.example.com,
diff --git a/core/modules/filter/tests/src/Unit/FilterUninstallValidatorTest.php b/core/modules/filter/tests/src/Unit/FilterUninstallValidatorTest.php
deleted file mode 100644
index cb37bf4..0000000
--- a/core/modules/filter/tests/src/Unit/FilterUninstallValidatorTest.php
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\filter\Unit\FilterUninstallValidatorTest.
- */
-
-namespace Drupal\Tests\filter\Unit;
-
-use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Tests\UnitTestCase;
-
-/**
- * @coversDefaultClass \Drupal\filter\FilterUninstallValidator
- * @group filter
- */
-class FilterUninstallValidatorTest extends UnitTestCase {
-
-  /**
-   * @var \Drupal\filter\FilterUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $filterUninstallValidator;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->filterUninstallValidator = $this->getMockBuilder('Drupal\filter\FilterUninstallValidator')
-      ->disableOriginalConstructor()
-      ->setMethods(['getFilterDefinitionsByProvider', 'getEnabledFilterFormats'])
-      ->getMock();
-    $this->filterUninstallValidator->setStringTranslation($this->getStringTranslationStub());
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNoPlugins() {
-    $this->filterUninstallValidator->expects($this->once())
-      ->method('getFilterDefinitionsByProvider')
-      ->willReturn([]);
-    $this->filterUninstallValidator->expects($this->never())
-      ->method('getEnabledFilterFormats');
-
-    $module = $this->randomMachineName();
-    $expected = [];
-    $reasons = $this->filterUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNoFormats() {
-    $this->filterUninstallValidator->expects($this->once())
-      ->method('getFilterDefinitionsByProvider')
-      ->willReturn([
-        'test_filter_plugin' => [
-          'id' => 'test_filter_plugin',
-          'provider' => 'filter_test',
-        ],
-      ]);
-    $this->filterUninstallValidator->expects($this->once())
-      ->method('getEnabledFilterFormats')
-      ->willReturn([]);
-
-    $module = $this->randomMachineName();
-    $expected = [];
-    $reasons = $this->filterUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNoMatchingFormats() {
-    $this->filterUninstallValidator->expects($this->once())
-      ->method('getFilterDefinitionsByProvider')
-      ->willReturn([
-        'test_filter_plugin1' => [
-          'id' => 'test_filter_plugin1',
-          'provider' => 'filter_test',
-        ],
-        'test_filter_plugin2' => [
-          'id' => 'test_filter_plugin2',
-          'provider' => 'filter_test',
-        ],
-        'test_filter_plugin3' => [
-          'id' => 'test_filter_plugin3',
-          'provider' => 'filter_test',
-        ],
-        'test_filter_plugin4' => [
-          'id' => 'test_filter_plugin4',
-          'provider' => 'filter_test',
-        ],
-      ]);
-
-    $filter_plugin_enabled = $this->getMockForAbstractClass('Drupal\filter\Plugin\FilterBase', [['status' => TRUE], '', ['provider' => 'filter_test']]);
-    $filter_plugin_disabled = $this->getMockForAbstractClass('Drupal\filter\Plugin\FilterBase', [['status' => FALSE], '', ['provider' => 'filter_test']]);
-
-    // The first format has 2 matching and enabled filters, but the loop breaks
-    // after finding the first one.
-    $filter_plugin_collection1 = $this->getMockBuilder('Drupal\filter\FilterPluginCollection')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $filter_plugin_collection1->expects($this->exactly(3))
-      ->method('has')
-      ->willReturnMap([
-        ['test_filter_plugin1', FALSE],
-        ['test_filter_plugin2', TRUE],
-        ['test_filter_plugin3', TRUE],
-        ['test_filter_plugin4', TRUE],
-      ]);
-    $filter_plugin_collection1->expects($this->exactly(2))
-      ->method('get')
-      ->willReturnMap([
-        ['test_filter_plugin2', $filter_plugin_disabled],
-        ['test_filter_plugin3', $filter_plugin_enabled],
-        ['test_filter_plugin4', $filter_plugin_enabled],
-      ]);
-
-    $filter_format1 = $this->getMock('Drupal\filter\FilterFormatInterface');
-    $filter_format1->expects($this->once())
-      ->method('filters')
-      ->willReturn($filter_plugin_collection1);
-    $filter_format1->expects($this->once())
-      ->method('label')
-      ->willReturn('Filter Format 1 Label');
-
-    // The second filter format only has one matching and enabled filter.
-    $filter_plugin_collection2 = $this->getMockBuilder('Drupal\filter\FilterPluginCollection')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $filter_plugin_collection2->expects($this->exactly(4))
-      ->method('has')
-      ->willReturnMap([
-        ['test_filter_plugin1', FALSE],
-        ['test_filter_plugin2', FALSE],
-        ['test_filter_plugin3', FALSE],
-        ['test_filter_plugin4', TRUE],
-      ]);
-    $filter_plugin_collection2->expects($this->exactly(1))
-      ->method('get')
-      ->with('test_filter_plugin4')
-      ->willReturn($filter_plugin_enabled);
-
-    $filter_format2 = $this->getMock('Drupal\filter\FilterFormatInterface');
-    $filter_format2->expects($this->once())
-      ->method('filters')
-      ->willReturn($filter_plugin_collection2);
-    $filter_format2->expects($this->once())
-      ->method('label')
-      ->willReturn('Filter Format 2 Label');
-    $this->filterUninstallValidator->expects($this->once())
-      ->method('getEnabledFilterFormats')
-      ->willReturn([
-        'test_filter_format1' => $filter_format1,
-        'test_filter_format2' => $filter_format2,
-      ]);
-
-    $expected = [
-      SafeMarkup::format('Provides a filter plugin that is in use in the following filter formats: %formats', ['%formats' => implode(', ', [
-        'Filter Format 1 Label',
-        'Filter Format 2 Label',
-      ])]),
-    ];
-    $reasons = $this->filterUninstallValidator->validate($this->randomMachineName());
-    $this->assertSame($expected, $reasons);
-  }
-
-}
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index eb25bf8..01a66e5 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -11,8 +11,11 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Url;
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\taxonomy\Entity\Vocabulary;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
 use Drupal\user\Entity\User;
 
 /**
@@ -633,5 +636,65 @@ function template_preprocess_forum_submitted(&$variables) {
     $username = array('#theme' => 'username', '#account' => User::load($variables['topic']->uid));
     $variables['author'] = drupal_render($username);
   }
-  $variables['time'] = isset($variables['topic']->created) ? \Drupal::service('date.formatter')->formatTimeDiffSince($variables['topic']->created) : '';
+  $variables['time'] = isset($variables['topic']->created) ? \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $variables['topic']->created) : '';
+}
+
+/**
+ * Implements hook_system_info_alter().
+ *
+ * Prevents forum module from being uninstalled whilst any forum nodes exist
+ * or there are any terms in the forum vocabulary.
+ */
+function forum_system_info_alter(&$info, Extension $file, $type) {
+  // It is not safe use the entity query service during maintenance mode.
+  if ($type == 'module' && !defined('MAINTENANCE_MODE') && $file->getName() == 'forum') {
+    $factory = \Drupal::service('entity.query');
+    $nodes = $factory->get('node')
+      ->condition('type', 'forum')
+      ->accessCheck(FALSE)
+      ->range(0, 1)
+      ->execute();
+    if (!empty($nodes)) {
+      $info['required'] = TRUE;
+      $info['explanation'] = t('To uninstall Forum first delete all <em>Forum</em> content.');
+    }
+    $vid = \Drupal::config('forum.settings')->get('vocabulary');
+    $terms = $factory->get('taxonomy_term')
+      ->condition('vid', $vid)
+      ->accessCheck(FALSE)
+      ->range(0, 1)
+      ->execute();
+    if (!empty($terms)) {
+      $vocabulary = Vocabulary::load($vid);
+      $info['required'] = TRUE;
+      try {
+        if (!empty($info['explanation'])) {
+          if ($vocabulary->access('view')) {
+            $info['explanation'] = t('To uninstall Forum first delete all <em>Forum</em> content and <a href="!url">%vocabulary</a> terms.', [
+              '%vocabulary' => $vocabulary->label(),
+              '!url' => $vocabulary->url('overview-form'),
+            ]);
+          }
+          else {
+            $info['explanation'] = t('To uninstall Forum first delete all <em>Forum</em> content and %vocabulary terms.', [
+              '%vocabulary' => $vocabulary->label()
+            ]);
+          }
+        }
+        else {
+          $info['explanation'] = t('To uninstall Forum first delete all <a href="!url">%vocabulary</a> terms.', [
+            '%vocabulary' => $vocabulary->label(),
+            '!url' => $vocabulary->url('overview-form'),
+          ]);
+        }
+      }
+      catch (RouteNotFoundException $e) {
+        // Route rebuilding might not have occurred before this hook is fired.
+        // Just use an explanation without a link for the time being.
+        $info['explanation'] = t('To uninstall Forum first delete all <em>Forum</em> content and %vocabulary terms.', [
+          '%vocabulary' => $vocabulary->label()
+        ]);
+      }
+    }
+  }
 }
diff --git a/core/modules/forum/forum.services.yml b/core/modules/forum/forum.services.yml
index 6ab41c9..d5c0fe3 100644
--- a/core/modules/forum/forum.services.yml
+++ b/core/modules/forum/forum.services.yml
@@ -19,10 +19,3 @@ services:
     arguments: ['@database', '@forum_manager']
     tags:
       - { name: backend_overridable }
-
-  forum.uninstall_validator:
-    class: Drupal\forum\ForumUninstallValidator
-    tags:
-      - { name: module_install.uninstall_validator }
-    arguments: ['@entity.manager', '@entity.query', '@config.factory', '@string_translation']
-    lazy: true
diff --git a/core/modules/forum/src/ForumUninstallValidator.php b/core/modules/forum/src/ForumUninstallValidator.php
deleted file mode 100644
index 9c6220d..0000000
--- a/core/modules/forum/src/ForumUninstallValidator.php
+++ /dev/null
@@ -1,139 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\forum\ForumUninstallValidator.
- */
-
-namespace Drupal\forum;
-
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-use Drupal\taxonomy\VocabularyInterface;
-
-/**
- * Prevents forum module from being uninstalled whilst any forum nodes exist
- * or there are any terms in the forum vocabulary.
- */
-class ForumUninstallValidator implements ModuleUninstallValidatorInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The field storage config storage.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected $vocabularyStorage;
-
-  /**
-   * The entity query factory.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryFactory
-   */
-  protected $queryFactory;
-
-  /**
-   * The config factory.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected $configFactory;
-
-  /**
-   * Constructs a new ForumUninstallValidator.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
-   *   The entity query factory.
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *  The config factory.
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   */
-  public function __construct(EntityManagerInterface $entity_manager, QueryFactory $query_factory, ConfigFactoryInterface $config_factory, TranslationInterface $string_translation) {
-    $this->vocabularyStorage = $entity_manager->getStorage('taxonomy_vocabulary');
-    $this->queryFactory = $query_factory;
-    $this->configFactory = $config_factory;
-    $this->stringTranslation = $string_translation;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($module) {
-    $reasons = [];
-    if ($module == 'forum') {
-      if ($this->hasForumNodes()) {
-        $reasons[] = $this->t('To uninstall Forum, first delete all <em>Forum</em> content');
-      }
-
-      $vocabulary = $this->getForumVocabulary();
-      if ($this->hasTermsForVocabulary($vocabulary)) {
-        if ($vocabulary->access('view')) {
-          $reasons[] = $this->t('To uninstall Forum, first delete all <a href="@url">%vocabulary</a> terms', [
-            '%vocabulary' => $vocabulary->label(),
-            '@url' => $vocabulary->url('overview-form'),
-          ]);
-        }
-        else {
-          $reasons[] = $this->t('To uninstall Forum, first delete all %vocabulary terms', [
-            '%vocabulary' => $vocabulary->label()
-          ]);
-        }
-      }
-    }
-
-    return $reasons;
-  }
-
-  /**
-   * Determines if there are any forum nodes or not.
-   *
-   * @return bool
-   *   TRUE if there are forum nodes, FALSE otherwise.
-   */
-  protected function hasForumNodes() {
-    $nodes = $this->queryFactory->get('node')
-      ->condition('type', 'forum')
-      ->accessCheck(FALSE)
-      ->range(0, 1)
-      ->execute();
-    return !empty($nodes);
-  }
-
-  /**
-   * Determines if there are any taxonomy terms for a specified vocabulary.
-   *
-   * @param \Drupal\taxonomy\VocabularyInterface $vocabulary
-   *   The vocabulary to check for terms.
-   *
-   * @return bool
-   *   TRUE if there are terms for this vocabulary, FALSE otherwise.
-   */
-  protected function hasTermsForVocabulary(VocabularyInterface $vocabulary) {
-    $terms = $this->queryFactory->get('taxonomy_term')
-      ->condition('vid', $vocabulary->id())
-      ->accessCheck(FALSE)
-      ->range(0, 1)
-      ->execute();
-    return !empty($terms);
-  }
-
-  /**
-   * Returns the vocabulary configured for forums.
-   *
-   * @return \Drupal\taxonomy\VocabularyInterface
-   *   The vocabulary entity for forums.
-   */
-  protected function getForumVocabulary() {
-    $vid = $this->configFactory->get('forum.settings')->get('vocabulary');
-    return $this->vocabularyStorage->load($vid);
-  }
-
-}
diff --git a/core/modules/forum/src/Tests/ForumUninstallTest.php b/core/modules/forum/src/Tests/ForumUninstallTest.php
index db7c091..a0270ca 100644
--- a/core/modules/forum/src/Tests/ForumUninstallTest.php
+++ b/core/modules/forum/src/Tests/ForumUninstallTest.php
@@ -74,7 +74,8 @@ public function testForumUninstallWithField() {
     $this->drupalGet('admin/modules/uninstall');
     // Assert forum is required.
     $this->assertNoFieldByName('uninstall[forum]');
-    $this->assertText('To uninstall Forum, first delete all Forum content');
+    $this->drupalGet('admin/modules');
+    $this->assertText('To uninstall Forum first delete all Forum content');
 
     // Delete the node.
     $this->drupalPostForm('node/' . $node->id() . '/delete', array(), t('Delete'));
@@ -83,7 +84,8 @@ public function testForumUninstallWithField() {
     $this->drupalGet('admin/modules/uninstall');
     // Assert forum is still required.
     $this->assertNoFieldByName('uninstall[forum]');
-    $this->assertText('To uninstall Forum, first delete all Forums terms');
+    $this->drupalGet('admin/modules');
+    $this->assertText('To uninstall Forum first delete all Forums terms');
 
     // Delete any forum terms.
     $vid = $this->config('forum.settings')->get('vocabulary');
@@ -100,6 +102,8 @@ public function testForumUninstallWithField() {
     $this->drupalGet('admin/modules/uninstall');
     // Assert forum is no longer required.
     $this->assertFieldByName('uninstall[forum]');
+    $this->drupalGet('admin/modules');
+    $this->assertNoText('To uninstall Forum first delete all Forum content');
     $this->drupalPostForm('admin/modules/uninstall', array(
       'uninstall[forum]' => 1,
     ), t('Uninstall'));
@@ -138,13 +142,6 @@ public function testForumUninstallWithoutFieldStorage() {
     $field_storage = FieldStorageConfig::loadByName('node', 'taxonomy_forums');
     $this->assertNull($field_storage, 'The taxonomy_forums field storage has been deleted.');
 
-    // Delete all terms in the Forums vocabulary. Uninstalling the forum module
-    // will fail unless this is done.
-    $terms = entity_load_multiple_by_properties('taxonomy_term', array('vid' => 'forums'));
-    foreach($terms as $term) {
-      $term->delete();
-    }
-
     // Ensure that uninstallation succeeds even if the field has already been
     // deleted manually beforehand.
     $this->container->get('module_installer')->uninstall(array('forum'));
diff --git a/core/modules/forum/tests/modules/forum_test_views/test_views/views.view.test_forum_index.yml b/core/modules/forum/tests/modules/forum_test_views/test_views/views.view.test_forum_index.yml
index a874401..32a9306 100644
--- a/core/modules/forum/tests/modules/forum_test_views/test_views/views.view.test_forum_index.yml
+++ b/core/modules/forum/tests/modules/forum_test_views/test_views/views.view.test_forum_index.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/forum/tests/src/Unit/ForumUninstallValidatorTest.php b/core/modules/forum/tests/src/Unit/ForumUninstallValidatorTest.php
deleted file mode 100644
index 85145c2..0000000
--- a/core/modules/forum/tests/src/Unit/ForumUninstallValidatorTest.php
+++ /dev/null
@@ -1,247 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\forum\Unit\ForumUninstallValidatorTest.
- */
-
-namespace Drupal\Tests\forum\Unit;
-
-use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Tests\UnitTestCase;
-
-/**
- * @coversDefaultClass \Drupal\forum\ForumUninstallValidator
- * @group forum
- */
-class ForumUninstallValidatorTest extends UnitTestCase {
-
-  /**
-   * @var \Drupal\forum\ForumUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $forumUninstallValidator;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->forumUninstallValidator = $this->getMockBuilder('Drupal\forum\ForumUninstallValidator')
-      ->disableOriginalConstructor()
-      ->setMethods(['hasForumNodes', 'hasTermsForVocabulary', 'getForumVocabulary'])
-      ->getMock();
-    $this->forumUninstallValidator->setStringTranslation($this->getStringTranslationStub());
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNotForum() {
-    $this->forumUninstallValidator->expects($this->never())
-      ->method('hasForumNodes');
-    $this->forumUninstallValidator->expects($this->never())
-      ->method('hasTermsForVocabulary');
-    $this->forumUninstallValidator->expects($this->never())
-      ->method('getForumVocabulary');
-
-    $module = 'not_forum';
-    $expected = [];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidate() {
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasForumNodes')
-      ->willReturn(FALSE);
-
-    $vocabulary = $this->getMock('Drupal\taxonomy\VocabularyInterface');
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('getForumVocabulary')
-      ->willReturn($vocabulary);
-
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasTermsForVocabulary')
-      ->willReturn(FALSE);
-
-    $module = 'forum';
-    $expected = [];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateHasForumNodes() {
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasForumNodes')
-      ->willReturn(TRUE);
-
-    $vocabulary = $this->getMock('Drupal\taxonomy\VocabularyInterface');
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('getForumVocabulary')
-      ->willReturn($vocabulary);
-
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasTermsForVocabulary')
-      ->willReturn(FALSE);
-
-    $module = 'forum';
-    $expected = [
-      'To uninstall Forum, first delete all <em>Forum</em> content',
-    ];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateHasTermsForVocabularyWithNodesAccess() {
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasForumNodes')
-      ->willReturn(TRUE);
-
-    $vocabulary = $this->getMock('Drupal\taxonomy\VocabularyInterface');
-    $vocabulary->expects($this->once())
-      ->method('label')
-      ->willReturn('Vocabulary label');
-    $vocabulary->expects($this->once())
-      ->method('url')
-      ->willReturn('/path/to/vocabulary/overview');
-    $vocabulary->expects($this->once())
-      ->method('access')
-      ->willReturn(TRUE);
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('getForumVocabulary')
-      ->willReturn($vocabulary);
-
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasTermsForVocabulary')
-      ->willReturn(TRUE);
-
-    $module = 'forum';
-    $expected = [
-      'To uninstall Forum, first delete all <em>Forum</em> content',
-      SafeMarkup::format('To uninstall Forum, first delete all <a href="@url">%vocabulary</a> terms', [
-        '@url' => '/path/to/vocabulary/overview',
-        '%vocabulary' => 'Vocabulary label',
-      ]),
-    ];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateHasTermsForVocabularyWithNodesNoAccess() {
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasForumNodes')
-      ->willReturn(TRUE);
-
-    $vocabulary = $this->getMock('Drupal\taxonomy\VocabularyInterface');
-    $vocabulary->expects($this->once())
-      ->method('label')
-      ->willReturn('Vocabulary label');
-    $vocabulary->expects($this->never())
-      ->method('url');
-    $vocabulary->expects($this->once())
-      ->method('access')
-      ->willReturn(FALSE);
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('getForumVocabulary')
-      ->willReturn($vocabulary);
-
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasTermsForVocabulary')
-      ->willReturn(TRUE);
-
-    $module = 'forum';
-    $expected = [
-      'To uninstall Forum, first delete all <em>Forum</em> content',
-      SafeMarkup::format('To uninstall Forum, first delete all %vocabulary terms', [
-        '%vocabulary' => 'Vocabulary label',
-      ]),
-    ];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateHasTermsForVocabularyAccess() {
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasForumNodes')
-      ->willReturn(FALSE);
-
-    $vocabulary = $this->getMock('Drupal\taxonomy\VocabularyInterface');
-    $vocabulary->expects($this->once())
-      ->method('url')
-      ->willReturn('/path/to/vocabulary/overview');
-    $vocabulary->expects($this->once())
-      ->method('label')
-      ->willReturn('Vocabulary label');
-    $vocabulary->expects($this->once())
-      ->method('access')
-      ->willReturn(TRUE);
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('getForumVocabulary')
-      ->willReturn($vocabulary);
-
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasTermsForVocabulary')
-      ->willReturn(TRUE);
-
-    $module = 'forum';
-    $expected = [
-      SafeMarkup::format('To uninstall Forum, first delete all <a href="@url">%vocabulary</a> terms', [
-        '@url' => '/path/to/vocabulary/overview',
-        '%vocabulary' => 'Vocabulary label',
-      ]),
-    ];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateHasTermsForVocabularyNoAccess() {
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasForumNodes')
-      ->willReturn(FALSE);
-
-    $vocabulary = $this->getMock('Drupal\taxonomy\VocabularyInterface');
-    $vocabulary->expects($this->once())
-      ->method('label')
-      ->willReturn('Vocabulary label');
-    $vocabulary->expects($this->never())
-      ->method('url');
-    $vocabulary->expects($this->once())
-      ->method('access')
-      ->willReturn(FALSE);
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('getForumVocabulary')
-      ->willReturn($vocabulary);
-
-    $this->forumUninstallValidator->expects($this->once())
-      ->method('hasTermsForVocabulary')
-      ->willReturn(TRUE);
-
-    $module = 'forum';
-    $expected = [
-      SafeMarkup::format('To uninstall Forum, first delete all %vocabulary terms', [
-        '%vocabulary' => 'Vocabulary label',
-      ]),
-    ];
-    $reasons = $this->forumUninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-}
diff --git a/core/modules/hal/src/Encoder/JsonEncoder.php b/core/modules/hal/src/Encoder/JsonEncoder.php
index 897bc44..4d932ff 100644
--- a/core/modules/hal/src/Encoder/JsonEncoder.php
+++ b/core/modules/hal/src/Encoder/JsonEncoder.php
@@ -12,7 +12,7 @@
 /**
  * Encodes HAL data in JSON.
  *
- * Simply respond to hal_json format requests using the JSON encoder.
+ * Simply respond to application/hal+json requests using the JSON encoder.
  */
 class JsonEncoder extends SymfonyJsonEncoder {
 
diff --git a/core/modules/hal/src/HalServiceProvider.php b/core/modules/hal/src/HalServiceProvider.php
index afe8d2d..d8ac47f 100644
--- a/core/modules/hal/src/HalServiceProvider.php
+++ b/core/modules/hal/src/HalServiceProvider.php
@@ -19,7 +19,7 @@ class HalServiceProvider implements ServiceModifierInterface {
    * {@inheritdoc}
    */
   public function alter(ContainerBuilder $container) {
-    if ($container->has('http_middleware.negotiation') && is_a($container->getDefinition('http_middleware.negotiation')->getClass(), '\Drupal\Core\StackMiddleware\NegotiationMiddleware', TRUE)) {
+    if ($container->has('http_middleware.negotiation')) {
       $container->getDefinition('http_middleware.negotiation')->addMethodCall('registerFormat', ['hal_json', ['application/hal+json']]);
     }
   }
diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
index a4761b3..14fdb0b 100644
--- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
+++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
@@ -8,7 +8,6 @@
 namespace Drupal\hal\Normalizer;
 
 use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\rest\LinkManager\LinkManagerInterface;
@@ -196,19 +195,14 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
   /**
    * Constructs the entity URI.
    *
-   * @param \Drupal\Core\Entity\EntityInterface
+   * @param $entity
    *   The entity.
+   *
    * @return string
    *   The entity URI.
    */
-  protected function getEntityUri(EntityInterface $entity) {
-    // Some entity types don't provide a canonical link template, at least call
-    // out to ->url().
-    if ($entity->isNew() || !$entity->hasLinkTemplate('canonical')) {
-      return $entity->url('canonical', []);
-    }
-    $url = $entity->urlInfo('canonical', ['absolute' => TRUE]);
-    return $url->setRouteParameter('_format', 'hal_json')->toString();
+  protected function getEntityUri($entity) {
+    return $entity->url('canonical', array('absolute' => TRUE));
   }
 
   /**
diff --git a/core/modules/hal/src/Tests/NormalizeTest.php b/core/modules/hal/src/Tests/NormalizeTest.php
index 44d7f24..9525f05 100644
--- a/core/modules/hal/src/Tests/NormalizeTest.php
+++ b/core/modules/hal/src/Tests/NormalizeTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\hal\Tests;
 
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Url;
 
 /**
@@ -170,15 +169,14 @@ public function testNormalize() {
   /**
    * Constructs the entity URI.
    *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
+   * @param $entity
    *   The entity.
    *
    * @return string
    *   The entity URI.
    */
-  protected function getEntityUri(EntityInterface $entity) {
-    $url = $entity->urlInfo('canonical', ['absolute' => TRUE]);
-    return $url->setRouteParameter('_format', 'hal_json')->toString();
+  protected function getEntityUri($entity) {
+    return $entity->url('canonical', array('absolute' => TRUE));
   }
 
 }
diff --git a/core/modules/help/help.api.php b/core/modules/help/help.api.php
index a88a218..09a3d3d 100644
--- a/core/modules/help/help.api.php
+++ b/core/modules/help/help.api.php
@@ -22,8 +22,7 @@
  * Help block (provided by the core Help module), if the block is displayed on
  * that page. The module overview help information is displayed by the Help
  * module. It can be accessed from the page at admin/help or from the Extend
- * Extend page. If a module implements hook_help() the help system expects
- * module overview help to be provided.
+ * Extend page.
  *
  * For detailed usage examples of:
  * - Module overview help, see content_translation_help(). Module overview
diff --git a/core/modules/help/src/Controller/HelpController.php b/core/modules/help/src/Controller/HelpController.php
index e6c3d16..ab969d8 100644
--- a/core/modules/help/src/Controller/HelpController.php
+++ b/core/modules/help/src/Controller/HelpController.php
@@ -68,7 +68,9 @@ public function helpMain() {
   protected function helpLinksAsList() {
     $modules = array();
     foreach ($this->moduleHandler()->getImplementations('help') as $module) {
-      $modules[$module] = $this->moduleHandler->getName($module);
+      if ($this->moduleHandler()->invoke($module, 'help', array("help.page.$module", $this->routeMatch))) {
+        $modules[$module] = $this->moduleHandler->getName($module);
+      }
     }
     asort($modules);
 
diff --git a/core/modules/help/src/Tests/HelpTest.php b/core/modules/help/src/Tests/HelpTest.php
index 5669097..66626a5 100644
--- a/core/modules/help/src/Tests/HelpTest.php
+++ b/core/modules/help/src/Tests/HelpTest.php
@@ -19,16 +19,11 @@ class HelpTest extends WebTestBase {
   /**
    * Modules to enable.
    *
-   * The help_test module implements hook_help() but does not provide a module
-   * overview page.
-   *
    * @var array.
    */
-  public static $modules = array('help_test');
+  public static $modules = array('shortcut');
 
-  /**
-   * Use the Standard profile to test help implementations of many core modules.
-   */
+  // Tests help implementations of many arbitrary core modules.
   protected $profile = 'standard';
 
   /**
@@ -76,11 +71,6 @@ public function testHelp() {
     foreach ($this->getModuleList() as $module => $name) {
       $this->assertLink($name, 0, format_string('Link properly added to @name (admin/help/@module)', array('@module' => $module, '@name' => $name)));
     }
-
-    // Ensure that module which does not provide an module overview page is
-    // handled correctly.
-    $this->clickLink(\Drupal::moduleHandler()->getName('help_test'));
-    $this->assertRaw(t('No help is available for module %module.', array('%module' => \Drupal::moduleHandler()->getName('help_test'))));
   }
 
   /**
diff --git a/core/modules/help/src/Tests/NoHelpTest.php b/core/modules/help/src/Tests/NoHelpTest.php
index 886e138..cd4d460 100644
--- a/core/modules/help/src/Tests/NoHelpTest.php
+++ b/core/modules/help/src/Tests/NoHelpTest.php
@@ -44,10 +44,6 @@ public function testMainPageNoHelp() {
     $this->drupalGet('admin/help');
     $this->assertResponse(200);
     $this->assertText('Help is available on the following items', 'Help page is found.');
-    $this->assertFalse(\Drupal::moduleHandler()->implementsHook('menu_test', 'help'), 'The menu_test module does not implement hook_help');
-    $this->assertNoText(\Drupal::moduleHandler()->getName('menu_test'), 'Making sure the test module menu_test does not display a help link on admin/help.');
-
-    $this->drupalGet('admin/help/menu_test');
-    $this->assertResponse(404, 'Getting a module overview help page for a module that does not implement hook_help() results in a 404.');
+    $this->assertNoText('Hook menu tests', 'Making sure the test module menu_test does not display a help link on admin/help.');
   }
 }
diff --git a/core/modules/help/tests/modules/help_test/help_test.module b/core/modules/help/tests/modules/help_test/help_test.module
deleted file mode 100644
index 2fd4991..0000000
--- a/core/modules/help/tests/modules/help_test/help_test.module
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-/**
- * @file
- * Test Help module.
- */
-
-use \Drupal\Core\Routing\RouteMatchInterface;
-
-/**
- * Implements hook_help().
- */
-function help_test_help($route_name, RouteMatchInterface $route_match) {
-  // Do not implement a module overview page to test an empty implementation.
-  // @see \Drupal\help\Tests\HelpTest
-}
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index 49c6534..dbdbcc8 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -21,7 +21,7 @@
 function template_preprocess_image_widget(&$variables) {
   $element = $variables['element'];
 
-  $variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
+  $variables['attributes'] = array('class' => array('image-widget', 'form-managed-file', 'clearfix'));
 
   if (!empty($element['fids']['#value'])) {
     $file = reset($element['#files']);
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 59ab1b8..0e926fe 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -177,7 +177,7 @@ function image_file_download($uri) {
       // Confirm there's at least one module granting access and none denying access.
       if (!empty($headers) && !in_array(-1, $headers)) {
         return array(
-          // Send headers describing the image's size, and MIME-type.
+          // Send headers describing the image's size, and MIME-type...
           'Content-Type' => $image->getMimeType(),
           'Content-Length' => $image->getFileSize(),
           // By not explicitly setting them here, this uses normal Drupal
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index 74b07ed..875a2a2 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -317,8 +317,8 @@ function testImageFieldSettings() {
       'files[' . $field_name . '_2][]' => drupal_realpath($test_image->uri),
     );
     $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button');
-    $this->assertNoRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="js-form-file form-file">');
-    $this->assertRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="js-form-file form-file">');
+    $this->assertNoRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="form-file">');
+    $this->assertRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="form-file">');
   }
 
   /**
diff --git a/core/modules/image/tests/modules/image_test_views/test_views/views.view.test_image_user_image_data.yml b/core/modules/image/tests/modules/image_test_views/test_views/views.view.test_image_user_image_data.yml
index 8ea166b..3c02a8b 100644
--- a/core/modules/image/tests/modules/image_test_views/test_views/views.view.test_image_user_image_data.yml
+++ b/core/modules/image/tests/modules/image_test_views/test_views/views.view.test_image_user_image_data.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access user profiles'
       cache:
-        type: tag
+        type: none
       style:
         type: table
         options:
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index aa260ef..0258767 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -15,8 +15,7 @@
 function locale_install() {
   // Create the interface translations directory and ensure it's writable.
   if (!$directory = \Drupal::config('locale.settings')->get('translation.path')) {
-    $site_path = \Drupal::service('site.path');
-    $directory = $site_path . '/files/translations';
+    $directory = conf_path() . '/files/translations';
     \Drupal::configFactory()->getEditable('locale.settings')->set('translation.path', $directory)->save();
   }
   file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index d58d955..41ce0b8 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -119,6 +119,6 @@ function template_preprocess_locale_translation_update_info(array &$variables) {
 function template_preprocess_locale_translation_last_check(array &$variables) {
   $last = $variables['last'];
   $variables['last_checked'] = ($last != NULL);
-  $variables['time'] = \Drupal::service('date.formatter')->formatTimeDiffSince($last);
+  $variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $last);
   $variables['link'] = \Drupal::l(t('Check manually'), new Url('locale.check_translation', array(), array('query' => \Drupal::destination()->getAsArray())));
 }
diff --git a/core/modules/locale/src/StringDatabaseStorage.php b/core/modules/locale/src/StringDatabaseStorage.php
index da4e295..d206f52 100644
--- a/core/modules/locale/src/StringDatabaseStorage.php
+++ b/core/modules/locale/src/StringDatabaseStorage.php
@@ -433,7 +433,7 @@ protected function dbStringSelect(array $conditions, array $options = array()) {
       }
     }
 
-    // Process other options, string filter, query limit, etc.
+    // Process other options, string filter, query limit, etc...
     if (!empty($options['filters'])) {
       if (count($options['filters']) > 1) {
         $filter = db_or();
diff --git a/core/modules/locale/src/StringInterface.php b/core/modules/locale/src/StringInterface.php
index 0992c1d..046f414 100644
--- a/core/modules/locale/src/StringInterface.php
+++ b/core/modules/locale/src/StringInterface.php
@@ -156,7 +156,7 @@ public function getValues(array $fields);
    *
    * Locations are arbitrary pairs of type and name strings, used to store
    * information about the origins of the string, like the file name it
-   * was found on, the path on which it was discovered, etc.
+   * was found on, the path on which it was discovered, etc...
    *
    * A string can have any number of locations since the same string may be
    * found on different places of Drupal code and configuration.
@@ -179,7 +179,7 @@ public function getLocations($check_only = FALSE);
    * @param string $name
    *   Location name. Drupal path in case of online discovered translations,
    *   file path in case of imported strings, configuration name for strings
-   *   that come from configuration, etc.
+   *   that come from configuration, etc...
    *
    * @return $this
    */
diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module
index 0c097ba..c67dbea 100644
--- a/core/modules/menu_ui/menu_ui.module
+++ b/core/modules/menu_ui/menu_ui.module
@@ -46,10 +46,10 @@ function menu_ui_help($route_name, RouteMatchInterface $route_match) {
       $output .= '</dl>';
       return $output;
   }
-  if ($route_name == 'entity.menu.add_form' && \Drupal::moduleHandler()->moduleExists('block') && \Drupal::currentUser()->hasPermission('administer blocks')) {
+  if ($route_name == 'entity.menu.add_form' && \Drupal::moduleHandler()->moduleExists('block')) {
     return '<p>' . t('You can enable the newly-created block for this menu on the <a href="!blocks">Block layout page</a>.', array('!blocks' => \Drupal::url('block.admin_display'))) . '</p>';
   }
-  elseif ($route_name == 'entity.menu.collection' && \Drupal::moduleHandler()->moduleExists('block') && \Drupal::currentUser()->hasPermission('administer blocks')) {
+  elseif ($route_name == 'entity.menu.collection' && \Drupal::moduleHandler()->moduleExists('block')) {
     return '<p>' . t('Each menu has a corresponding block that is managed on the <a href="!blocks">Block layout page</a>.', array('!blocks' => \Drupal::url('block.admin_display'))) . '</p>';
   }
 }
diff --git a/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php b/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php
index 258eb9c..b741780 100644
--- a/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php
+++ b/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php
@@ -24,21 +24,17 @@ class MigrateSqlIdMapTest extends MigrateTestCase {
    *
    * @var array
    */
-  protected $migrationConfiguration = [
+  protected $migrationConfiguration = array(
     'id' => 'sql_idmap_test',
-  ];
+  );
 
-  protected $sourceIds = [
-    'source_id_property' => [
-      'type' => 'string',
-    ],
-  ];
+  protected $sourceIds = array(
+    'source_id_property' => array(),
+  );
 
-  protected $destinationIds = [
-    'destination_id_property' => [
-      'type' => 'string',
-    ],
-  ];
+  protected $destinationIds = array(
+    'destination_id_property' => array(),
+  );
 
   /**
    * The database connection.
@@ -47,66 +43,41 @@ class MigrateSqlIdMapTest extends MigrateTestCase {
    */
   protected $database;
 
-  public function setUp() {
-    $this->database = $this->getDatabase([]);
-  }
-
-  /**
-   * Saves a single ID mapping row in the database.
-   *
-   * @param array $map
-   *  The row to save.
-   */
-  protected function saveMap(array $map) {
-    $table = 'migrate_map_sql_idmap_test';
-
-    $schema = $this->database->schema();
-    // If the table already exists, add any columns which are in the map array,
-    // but don't yet exist in the table. Yay, flexibility!
-    if ($schema->tableExists($table)) {
-      foreach (array_keys($map) as $field) {
-        if (!$schema->fieldExists($table, $field)) {
-          $schema->addField($table, $field, ['type' => 'text']);
-        }
-      }
-    }
-    else {
-      $schema->createTable($table, $this->createSchemaFromRow($map));
-    }
-
-    $this->database->insert($table)->fields($map)->execute();
-  }
-
   /**
    * Creates a test SQL ID map plugin.
    *
+   * @param array $database_contents
+   *   (optional) An array keyed by table names. Value are list of rows where
+   *   each row is an associative array of field => value.
+   * @param array $connection_options
+   *   (optional) An array of database connection options.
+   * @param string $prefix
+   *   (optional) The database prefix.
+   *
    * @return \Drupal\Tests\migrate\Unit\TestSqlIdMap
    *   A SQL ID map plugin test instance.
    */
-  protected function getIdMap() {
+  protected function getIdMap($database_contents = array(), $connection_options = array(), $prefix = '') {
     $migration = $this->getMigration();
-
     $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
-    $plugin
+    $plugin->expects($this->any())
       ->method('getIds')
-      ->willReturn($this->sourceIds);
-    $migration
+      ->will($this->returnValue($this->sourceIds));
+    $migration->expects($this->any())
       ->method('getSourcePlugin')
-      ->willReturn($plugin);
-
-    $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
-    $plugin
+      ->will($this->returnValue($plugin));
+    $plugin = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
+    $plugin->expects($this->any())
       ->method('getIds')
-      ->willReturn($this->destinationIds);
-    $migration
+      ->will($this->returnValue($this->destinationIds));
+    $migration->expects($this->any())
       ->method('getDestinationPlugin')
-      ->willReturn($plugin);
-
-    $id_map = new TestSqlIdMap($this->database, [], 'sql', [], $migration);
-    $migration
+      ->will($this->returnValue($plugin));
+    $this->database = $this->getDatabase($database_contents, $connection_options, $prefix);
+    $id_map = new TestSqlIdMap($this->database, array(), 'sql', array(), $migration);
+    $migration->expects($this->any())
       ->method('getIdMap')
-      ->willReturn($id_map);
-
+      ->will($this->returnValue($id_map));
     return $id_map;
   }
 
@@ -114,22 +85,11 @@ protected function getIdMap() {
    * Sets defaults for SQL ID map plugin tests.
    */
   protected function idMapDefaults() {
-    $defaults = array(
+    return array(
       'source_row_status' => MigrateIdMapInterface::STATUS_IMPORTED,
       'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
       'hash' => '',
     );
-    // By default, the PDO SQLite driver strongly prefers to return strings
-    // from SELECT queries. Even for columns that don't store strings. Even
-    // if the connection's STRINGIFY_FETCHES attribute is FALSE. This can cause
-    // assertSame() calls to fail, since 0 !== '0'. Casting these values to
-    // strings isn't the most elegant workaround, but it allows the assertions
-    // to pass properly.
-    if ($this->database->driver() == 'sqlite') {
-      $defaults['source_row_status'] = (string) $defaults['source_row_status'];
-      $defaults['rollback_action'] = (string) $defaults['rollback_action'];
-    }
-    return $defaults;
   }
 
   /**
@@ -144,29 +104,29 @@ public function testSaveIdMapping() {
     $source = array(
       'source_id_property' => 'source_value',
     );
-    $row = new Row($source, ['source_id_property' => []]);
+    $row = new Row($source, array('source_id_property' => array()));
     $id_map = $this->getIdMap();
-    $id_map->saveIdMapping($row, ['destination_id_property' => 2]);
-    $expected_result = [
-      [
+    $id_map->saveIdMapping($row, array('destination_id_property' => 2));
+    $expected_result = array(
+      array(
         'sourceid1' => 'source_value',
         'destid1' => 2,
-      ] + $this->idMapDefaults(),
-    ];
-    $this->queryResultTest($this->getIdMapContents(), $expected_result);
-    $source = [
+      ) + $this->idMapDefaults(),
+    );
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_result);
+    $source = array(
       'source_id_property' => 'source_value_1',
-    ];
-    $row = new Row($source, ['source_id_property' => []]);
-    $id_map->saveIdMapping($row, ['destination_id_property' => 3]);
-    $expected_result[] = [
+    );
+    $row = new Row($source, array('source_id_property' => array()));
+    $id_map->saveIdMapping($row, array('destination_id_property' => 3));
+    $expected_result[] = array(
       'sourceid1' => 'source_value_1',
       'destid1' => 3,
-    ] + $this->idMapDefaults();
-    $this->queryResultTest($this->getIdMapContents(), $expected_result);
-    $id_map->saveIdMapping($row, ['destination_id_property' => 4]);
+    ) + $this->idMapDefaults();
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_result);
+    $id_map->saveIdMapping($row, array('destination_id_property' => 4));
     $expected_result[1]['destid1'] = 4;
-    $this->queryResultTest($this->getIdMapContents(), $expected_result);
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_result);
   }
 
   /**
@@ -184,12 +144,12 @@ public function testSetMessage() {
    */
   public function testClearMessages() {
     $message = 'Hello world.';
-    $expected_results = [0, 1, 2, 3];
+    $expected_results = array(0, 1, 2, 3);
     $id_map = $this->getIdMap();
 
     // Insert 4 message for later delete.
     foreach ($expected_results as $key => $expected_result) {
-      $id_map->saveMessage([$key], $message);
+      $id_map->saveMessage(array($key), $message);
     }
 
     // Truncate and check that 4 messages were deleted.
@@ -204,25 +164,25 @@ public function testClearMessages() {
    */
   public function testGetRowsNeedingUpdate() {
     $id_map = $this->getIdMap();
-    $row_statuses = [
+    $row_statuses = array(
       MigrateIdMapInterface::STATUS_IMPORTED,
       MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
       MigrateIdMapInterface::STATUS_IGNORED,
       MigrateIdMapInterface::STATUS_FAILED,
-    ];
+    );
     // Create a mapping row for each STATUS constant.
     foreach ($row_statuses as $status) {
-      $source = ['source_id_property' => 'source_value_' . $status];
-      $row = new Row($source, ['source_id_property' => []]);
-      $destination = ['destination_id_property' => 'destination_value_' . $status];
+      $source = array('source_id_property' => 'source_value_' . $status);
+      $row = new Row($source, array('source_id_property' => array()));
+      $destination = array('destination_id_property' => 'destination_value_' . $status);
       $id_map->saveIdMapping($row, $destination, $status);
-      $expected_results[] = [
+      $expected_results[] = array(
         'sourceid1' => 'source_value_' . $status,
         'destid1' => 'destination_value_' . $status,
         'source_row_status' => $status,
         'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
         'hash' => '',
-      ];
+      );
       // Assert zero rows need an update.
       if ($status == MigrateIdMapInterface::STATUS_IMPORTED) {
         $rows_needing_update = $id_map->getRowsNeedingUpdate(1);
@@ -230,7 +190,7 @@ public function testGetRowsNeedingUpdate() {
       }
     }
     // Assert that test values exist.
-    $this->queryResultTest($this->getIdMapContents(), $expected_results);
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_results);
 
     // Assert a single row needs an update.
     $row_needing_update = $id_map->getRowsNeedingUpdate(1);
@@ -238,15 +198,13 @@ public function testGetRowsNeedingUpdate() {
 
     // Assert the row matches its original source.
     $source_id = $expected_results[MigrateIdMapInterface::STATUS_NEEDS_UPDATE]['sourceid1'];
-    $test_row = $id_map->getRowBySource([$source_id]);
-    // $row_needing_update is an array of objects returned from the database,
-    // but $test_row is an array, so the cast is necessary.
-    $this->assertSame($test_row, (array) $row_needing_update[0]);
+    $test_row = $id_map->getRowBySource(array($source_id));
+    $this->assertSame($test_row, $row_needing_update[0]);
 
     // Add additional row that needs an update.
-    $source = ['source_id_property' => 'source_value_multiple'];
-    $row = new Row($source, ['source_id_property' => []]);
-    $destination = ['destination_id_property' => 'destination_value_multiple'];
+    $source = array('source_id_property' => 'source_value_multiple');
+    $row = new Row($source, array('source_id_property' => array()));
+    $destination = array('destination_id_property' => 'destination_value_multiple');
     $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
 
     // Assert multiple rows need an update.
@@ -259,14 +217,14 @@ public function testGetRowsNeedingUpdate() {
    */
   public function testMessageCount() {
     $message = 'Hello world.';
-    $expected_results = [0, 1, 2, 3];
+    $expected_results = array(0, 1, 2, 3);
     $id_map = $this->getIdMap();
 
     // Test count message multiple times starting from 0.
     foreach ($expected_results as $key => $expected_result) {
       $count = $id_map->messageCount();
       $this->assertEquals($expected_result, $count);
-      $id_map->saveMessage([$key], $message);
+      $id_map->saveMessage(array($key), $message);
     }
   }
 
@@ -275,16 +233,16 @@ public function testMessageCount() {
    */
   public function testMessageSave() {
     $message = 'Hello world.';
-    $expected_results = [
-      1 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_ERROR],
-      2 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_WARNING],
-      3 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_NOTICE],
-      4 => ['message' => $message, 'level' => MigrationInterface::MESSAGE_INFORMATIONAL],
-    ];
+    $expected_results = array(
+      1 => array('message' => $message, 'level' => MigrationInterface::MESSAGE_ERROR),
+      2 => array('message' => $message, 'level' => MigrationInterface::MESSAGE_WARNING),
+      3 => array('message' => $message, 'level' => MigrationInterface::MESSAGE_NOTICE),
+      4 => array('message' => $message, 'level' => MigrationInterface::MESSAGE_INFORMATIONAL),
+    );
     $id_map = $this->getIdMap();
 
     foreach ($expected_results as $key => $expected_result) {
-      $id_map->saveMessage([$key], $message, $expected_result['level']);
+      $id_map->saveMessage(array($key), $message, $expected_result['level']);
       $message_row = $this->database->select($id_map->messageTableName(), 'message')
                        ->fields('message')
                        ->condition('level', $expected_result['level'])
@@ -296,7 +254,7 @@ public function testMessageSave() {
 
     // Insert with default level.
     $message_default = 'Hello world default.';
-    $id_map->saveMessage([5], $message_default);
+    $id_map->saveMessage(array(5), $message_default);
     $message_row = $this->database->select($id_map->messageTableName(), 'message')
                      ->fields('message')
                      ->condition('level', MigrationInterface::MESSAGE_ERROR)
@@ -310,30 +268,29 @@ public function testMessageSave() {
    * Tests the getRowBySource method.
    */
   public function testGetRowBySource() {
-    $this->getDatabase([]);
-    $row = [
+    $row = array(
       'sourceid1' => 'source_id_value_1',
       'sourceid2' => 'source_id_value_2',
       'destid1' => 'destination_id_value_1',
-    ] + $this->idMapDefaults();
-    $this->saveMap($row);
-    $row = [
+    ) + $this->idMapDefaults();
+    $database_contents['migrate_map_sql_idmap_test'][] = $row;
+    $row = array(
       'sourceid1' => 'source_id_value_3',
       'sourceid2' => 'source_id_value_4',
       'destid1' => 'destination_id_value_2',
-    ] + $this->idMapDefaults();
-    $this->saveMap($row);
-    $source_id_values = [$row['sourceid1'], $row['sourceid2']];
-    $id_map = $this->getIdMap();
+    ) + $this->idMapDefaults();
+    $database_contents['migrate_map_sql_idmap_test'][] = $row;
+    $source_id_values = array($row['sourceid1'], $row['sourceid2']);
+    $id_map = $this->getIdMap($database_contents);
     $result_row = $id_map->getRowBySource($source_id_values);
     $this->assertSame($row, $result_row);
-    $source_id_values = ['missing_value_1', 'missing_value_2'];
+    $source_id_values = array('missing_value_1', 'missing_value_2');
     $result_row = $id_map->getRowBySource($source_id_values);
     $this->assertFalse($result_row);
   }
 
   /**
-   * Data provider for testLookupDestinationIdMapping().
+   * Tests the destination ID lookup method.
    *
    * Scenarios to test (for both hits and misses) are:
    * - Single-value source ID to single-value destination ID.
@@ -341,13 +298,11 @@ public function testGetRowBySource() {
    * - Single-value source ID to multi-value destination ID.
    * - Multi-value source ID to single-value destination ID.
    */
-  public function lookupDestinationIdMappingDataProvider() {
-    return [
-      [1, 1],
-      [2, 2],
-      [1, 2],
-      [2, 1],
-    ];
+  public function testLookupDestinationIdMapping() {
+    $this->performLookupDestinationIdTest(1, 1);
+    $this->performLookupDestinationIdTest(2, 2);
+    $this->performLookupDestinationIdTest(1, 2);
+    $this->performLookupDestinationIdTest(2, 1);
   }
 
   /**
@@ -357,30 +312,29 @@ public function lookupDestinationIdMappingDataProvider() {
    *   Number of source fields to test.
    * @param int $num_destination_fields
    *   Number of destination fields to test.
-   * @dataProvider lookupDestinationIdMappingDataProvider
    */
-  public function testLookupDestinationIdMapping($num_source_fields, $num_destination_fields) {
+  protected function performLookupDestinationIdTest($num_source_fields, $num_destination_fields) {
     // Adjust the migration configuration according to the number of source and
     // destination fields.
-    $this->sourceIds = [];
-    $this->destinationIds = [];
-    $source_id_values = [];
-    $nonexistent_id_values = [];
+    $this->sourceIds = array();
+    $this->destinationIds = array();
+    $source_id_values = array();
+    $nonexistent_id_values = array();
     $row = $this->idMapDefaults();
     for ($i = 1; $i <= $num_source_fields; $i++) {
       $row["sourceid$i"] = "source_id_value_$i";
       $source_id_values[] = "source_id_value_$i";
       $nonexistent_id_values[] = "nonexistent_source_id_value_$i";
-      $this->sourceIds["source_id_property_$i"] = [];
+      $this->sourceIds["source_id_property_$i"] = array();
     }
-    $expected_result = [];
+    $expected_result = array();
     for ($i = 1; $i <= $num_destination_fields; $i++) {
       $row["destid$i"] = "destination_id_value_$i";
       $expected_result[] = "destination_id_value_$i";
-      $this->destinationIds["destination_id_property_$i"] = [];
+      $this->destinationIds["destination_id_property_$i"] = array();
     }
-    $this->saveMap($row);
-    $id_map = $this->getIdMap();
+    $database_contents['migrate_map_sql_idmap_test'][] = $row;
+    $id_map = $this->getIdMap($database_contents);
     // Test for a valid hit.
     $destination_id = $id_map->lookupDestinationId($source_id_values);
     $this->assertSame($expected_result, $destination_id);
@@ -393,31 +347,31 @@ public function testLookupDestinationIdMapping($num_source_fields, $num_destinat
    * Tests the getRowByDestination method.
    */
   public function testGetRowByDestination() {
-    $row = [
+    $row = array(
       'sourceid1' => 'source_id_value_1',
       'sourceid2' => 'source_id_value_2',
       'destid1' => 'destination_id_value_1',
-    ] + $this->idMapDefaults();
-    $this->saveMap($row);
-    $row = [
+    ) + $this->idMapDefaults();
+    $database_contents['migrate_map_sql_idmap_test'][] = $row;
+    $row = array(
       'sourceid1' => 'source_id_value_3',
       'sourceid2' => 'source_id_value_4',
       'destid1' => 'destination_id_value_2',
-    ] + $this->idMapDefaults();
-    $this->saveMap($row);
-    $dest_id_values = [$row['destid1']];
-    $id_map = $this->getIdMap();
+    ) + $this->idMapDefaults();
+    $database_contents['migrate_map_sql_idmap_test'][] = $row;
+    $dest_id_values = array($row['destid1']);
+    $id_map = $this->getIdMap($database_contents);
     $result_row = $id_map->getRowByDestination($dest_id_values);
     $this->assertSame($row, $result_row);
     // This value does not exist.
-    $dest_id_values = ['invalid_destination_id_property'];
-    $id_map = $this->getIdMap();
+    $dest_id_values = array('invalid_destination_id_property');
+    $id_map = $this->getIdMap($database_contents);
     $result_row = $id_map->getRowByDestination($dest_id_values);
     $this->assertFalse($result_row);
   }
 
   /**
-   * Data provider for testLookupSourceIDMapping().
+   * Tests the source ID lookup method.
    *
    * Scenarios to test (for both hits and misses) are:
    * - Single-value destination ID to single-value source ID.
@@ -425,13 +379,11 @@ public function testGetRowByDestination() {
    * - Single-value destination ID to multi-value source ID.
    * - Multi-value destination ID to single-value source ID.
    */
-  public function lookupSourceIDMappingDataProvider() {
-    return [
-      [1, 1],
-      [2, 2],
-      [1, 2],
-      [2, 1],
-    ];
+  public function testLookupSourceIDMapping() {
+    $this->performLookupSourceIdTest(1, 1);
+    $this->performLookupSourceIdTest(2, 2);
+    $this->performLookupSourceIdTest(1, 2);
+    $this->performLookupSourceIdTest(2, 1);
   }
 
   /**
@@ -441,30 +393,29 @@ public function lookupSourceIDMappingDataProvider() {
    *   Number of source fields to test.
    * @param int $num_destination_fields
    *   Number of destination fields to test.
-   * @dataProvider lookupSourceIDMappingDataProvider
    */
-  public function testLookupSourceIDMapping($num_source_fields, $num_destination_fields) {
+  protected function performLookupSourceIdTest($num_source_fields, $num_destination_fields) {
     // Adjust the migration configuration according to the number of source and
     // destination fields.
-    $this->sourceIds = [];
-    $this->destinationIds = [];
+    $this->sourceIds = array();
+    $this->destinationIds = array();
     $row = $this->idMapDefaults();
-    $expected_result = [];
+    $expected_result = array();
     for ($i = 1; $i <= $num_source_fields; $i++) {
       $row["sourceid$i"] = "source_id_value_$i";
       $expected_result[] = "source_id_value_$i";
-      $this->sourceIds["source_id_property_$i"] = [];
+      $this->sourceIds["source_id_property_$i"] = array();
     }
-    $destination_id_values = [];
-    $nonexistent_id_values = [];
+    $destination_id_values = array();
+    $nonexistent_id_values = array();
     for ($i = 1; $i <= $num_destination_fields; $i++) {
       $row["destid$i"] = "destination_id_value_$i";
       $destination_id_values[] = "destination_id_value_$i";
       $nonexistent_id_values[] = "nonexistent_destination_id_value_$i";
-      $this->destinationIds["destination_id_property_$i"] = [];
+      $this->destinationIds["destination_id_property_$i"] = array();
     }
-    $this->saveMap($row);
-    $id_map = $this->getIdMap();
+    $database_contents['migrate_map_sql_idmap_test'][] = $row;
+    $id_map = $this->getIdMap($database_contents);
     // Test for a valid hit.
     $source_id = $id_map->lookupSourceID($destination_id_values);
     $this->assertSame($expected_result, $source_id);
@@ -484,25 +435,28 @@ public function testLookupSourceIDMapping($num_source_fields, $num_destination_f
   public function testImportedCount() {
     $id_map = $this->getIdMap();
     // Add a single failed row and assert zero imported rows.
-    $source = ['source_id_property' => 'source_value_failed'];
-    $row = new Row($source, ['source_id_property' => []]);
-    $destination = ['destination_id_property' => 'destination_value_failed'];
+    $source = array('source_id_property' => 'source_value_failed');
+    $row = new Row($source, array('source_id_property' => array()));
+    $destination = array('destination_id_property' => 'destination_value_failed');
     $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_FAILED);
-    $this->assertSame(0, (int) $id_map->importedCount());
+    $imported_count = $id_map->importedCount();
+    $this->assertSame(0, $imported_count);
 
     // Add an imported row and assert single count.
-    $source = ['source_id_property' => 'source_value_imported'];
-    $row = new Row($source, ['source_id_property' => []]);
-    $destination = ['destination_id_property' => 'destination_value_imported'];
+    $source = array('source_id_property' => 'source_value_imported');
+    $row = new Row($source, array('source_id_property' => array()));
+    $destination = array('destination_id_property' => 'destination_value_imported');
     $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_IMPORTED);
-    $this->assertSame(1, (int) $id_map->importedCount());
+    $imported_count = $id_map->importedCount();
+    $this->assertSame(1, $imported_count);
 
     // Add a row needing update and assert multiple imported rows.
-    $source = ['source_id_property' => 'source_value_update'];
-    $row = new Row($source, ['source_id_property' => []]);
-    $destination = ['destination_id_property' => 'destination_value_update'];
+    $source = array('source_id_property' => 'source_value_update');
+    $row = new Row($source, array('source_id_property' => array()));
+    $destination = array('destination_id_property' => 'destination_value_update');
     $id_map->saveIdMapping($row, $destination, MigrateIdMapInterface::STATUS_NEEDS_UPDATE);
-    $this->assertSame(2, (int) $id_map->importedCount());
+    $imported_count = $id_map->importedCount();
+    $this->assertSame(2, $imported_count);
   }
 
   /**
@@ -516,42 +470,43 @@ public function testImportedCount() {
   public function testProcessedCount() {
     $id_map = $this->getIdMap();
     // Assert zero rows have been processed before adding rows.
-    $this->assertSame(0, (int) $id_map->processedCount());
-    $row_statuses = [
+    $processed_count = $id_map->processedCount();
+    $this->assertSame(0, $processed_count);
+    $row_statuses = array(
       MigrateIdMapInterface::STATUS_IMPORTED,
       MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
       MigrateIdMapInterface::STATUS_IGNORED,
       MigrateIdMapInterface::STATUS_FAILED,
-    ];
+    );
     // Create a mapping row for each STATUS constant.
     foreach ($row_statuses as $status) {
-      $source = ['source_id_property' => 'source_value_' . $status];
-      $row = new Row($source, ['source_id_property' => []]);
-      $destination = ['destination_id_property' => 'destination_value_' . $status];
+      $source = array('source_id_property' => 'source_value_' . $status);
+      $row = new Row($source, array('source_id_property' => array()));
+      $destination = array('destination_id_property' => 'destination_value_' . $status);
       $id_map->saveIdMapping($row, $destination, $status);
       if ($status == MigrateIdMapInterface::STATUS_IMPORTED) {
         // Assert a single row has been processed.
-        $this->assertSame(1, (int) $id_map->processedCount());
+        $processed_count = $id_map->processedCount();
+        $this->assertSame(1, $processed_count);
       }
     }
     // Assert multiple rows have been processed.
-    $this->assertSame(count($row_statuses), (int) $id_map->processedCount());
+    $processed_count = $id_map->processedCount();
+    $this->assertSame(count($row_statuses), $processed_count);
   }
 
   /**
-   * Data provider for testUpdateCount().
+   * Tests the update count method.
    *
    * Scenarios to test for:
    * - No updates.
    * - One update.
    * - Multiple updates.
    */
-  public function updateCountDataProvider() {
-    return [
-      [0],
-      [1],
-      [3],
-    ];
+  public function testUpdateCount() {
+    $this->performUpdateCountTest(0);
+    $this->performUpdateCountTest(1);
+    $this->performUpdateCountTest(3);
   }
 
   /**
@@ -559,41 +514,40 @@ public function updateCountDataProvider() {
    *
    * @param int $num_update_rows
    *   The number of update rows to test.
-   * @dataProvider updateCountDataProvider
    */
-  public function testUpdateCount($num_update_rows) {
+  protected function performUpdateCountTest($num_update_rows) {
+    $database_contents['migrate_map_sql_idmap_test'] = array();
     for ($i = 0; $i < 5; $i++) {
       $row = $this->idMapDefaults();
       $row['sourceid1'] = "source_id_value_$i";
       $row['destid1'] = "destination_id_value_$i";
       $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
-      $this->saveMap($row);
+      $database_contents['migrate_map_sql_idmap_test'][] = $row;
     }
     for (; $i < 5 + $num_update_rows; $i++) {
       $row = $this->idMapDefaults();
       $row['sourceid1'] = "source_id_value_$i";
       $row['destid1'] = "destination_id_value_$i";
       $row['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
-      $this->saveMap($row);
+      $database_contents['migrate_map_sql_idmap_test'][] = $row;
     }
-    $id_map = $this->getIdMap();
-    $this->assertSame($num_update_rows, (int) $id_map->updateCount());
+    $id_map = $this->getIdMap($database_contents);
+    $count = $id_map->updateCount();
+    $this->assertSame($num_update_rows, $count);
   }
 
   /**
-   * Data provider for testErrorCount().
+   * Tests the error count method.
    *
    * Scenarios to test for:
    * - No errors.
    * - One error.
    * - Multiple errors.
    */
-  public function errorCountDataProvider() {
-    return [
-      [0],
-      [1],
-      [3],
-    ];
+  public function testErrorCount() {
+    $this->performErrorCountTest(0);
+    $this->performErrorCountTest(1);
+    $this->performErrorCountTest(3);
   }
 
   /**
@@ -601,25 +555,27 @@ public function errorCountDataProvider() {
    *
    * @param int $num_error_rows
    *   Number of error rows to test.
-   * @dataProvider errorCountDataProvider
    */
-  public function testErrorCount($num_error_rows) {
+  protected function performErrorCountTest($num_error_rows) {
+    $database_contents['migrate_map_sql_idmap_test'] = array();
     for ($i = 0; $i < 5; $i++) {
       $row = $this->idMapDefaults();
       $row['sourceid1'] = "source_id_value_$i";
       $row['destid1'] = "destination_id_value_$i";
       $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
-      $this->saveMap($row);
+      $database_contents['migrate_map_sql_idmap_test'][] = $row;
     }
     for (; $i < 5 + $num_error_rows; $i++) {
       $row = $this->idMapDefaults();
       $row['sourceid1'] = "source_id_value_$i";
       $row['destid1'] = "destination_id_value_$i";
       $row['source_row_status'] = MigrateIdMapInterface::STATUS_FAILED;
-      $this->saveMap($row);
+      $database_contents['migrate_map_sql_idmap_test'][] = $row;
     }
 
-    $this->assertSame($num_error_rows, (int) $this->getIdMap()->errorCount());
+    $id_map = $this->getIdMap($database_contents);
+    $count = $id_map->errorCount();
+    $this->assertSame($num_error_rows, $count);
   }
 
   /**
@@ -627,41 +583,41 @@ public function testErrorCount($num_error_rows) {
    */
   public function testSetUpdate() {
     $id_map = $this->getIdMap();
-    $row_statuses = [
+    $row_statuses = array(
       MigrateIdMapInterface::STATUS_IMPORTED,
       MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
       MigrateIdMapInterface::STATUS_IGNORED,
       MigrateIdMapInterface::STATUS_FAILED,
-    ];
+    );
     // Create a mapping row for each STATUS constant.
     foreach ($row_statuses as $status) {
-      $source = ['source_id_property' => 'source_value_' . $status];
-      $row = new Row($source, ['source_id_property' => []]);
-      $destination = ['destination_id_property' => 'destination_value_' . $status];
+      $source = array('source_id_property' => 'source_value_' . $status);
+      $row = new Row($source, array('source_id_property' => array()));
+      $destination = array('destination_id_property' => 'destination_value_' . $status);
       $id_map->saveIdMapping($row, $destination, $status);
-      $expected_results[] = [
+      $expected_results[] = array(
         'sourceid1' => 'source_value_' . $status,
         'destid1' => 'destination_value_' . $status,
         'source_row_status' => $status,
         'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
         'hash' => '',
-      ];
+      );
     }
     // Assert that test values exist.
-    $this->queryResultTest($this->getIdMapContents(), $expected_results);
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_results);
     // Mark each row as STATUS_NEEDS_UPDATE.
     foreach ($row_statuses as $status) {
-      $id_map->setUpdate(['source_value_' . $status]);
+      $id_map->setUpdate(array('source_value_' . $status));
     }
     // Update expected results.
     foreach ($expected_results as $key => $value) {
       $expected_results[$key]['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
     }
     // Assert that updated expected values match.
-    $this->queryResultTest($this->getIdMapContents(), $expected_results);
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_results);
     // Assert an exception is thrown when source identifiers are not provided.
     try {
-      $id_map->setUpdate([]);
+      $id_map->setUpdate(array());
       $this->assertFalse(FALSE, 'MigrateException not thrown, when source identifiers were provided to update.');
     }
     catch (MigrateException $e) {
@@ -674,30 +630,30 @@ public function testSetUpdate() {
    */
   public function testPrepareUpdate() {
     $id_map = $this->getIdMap();
-    $row_statuses = [
+    $row_statuses = array(
       MigrateIdMapInterface::STATUS_IMPORTED,
       MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
       MigrateIdMapInterface::STATUS_IGNORED,
       MigrateIdMapInterface::STATUS_FAILED,
-    ];
+    );
 
     // Create a mapping row for each STATUS constant.
     foreach ($row_statuses as $status) {
-      $source = ['source_id_property' => 'source_value_' . $status];
-      $row = new Row($source, ['source_id_property' => []]);
-      $destination = ['destination_id_property' => 'destination_value_' . $status];
+      $source = array('source_id_property' => 'source_value_' . $status);
+      $row = new Row($source, array('source_id_property' => array()));
+      $destination = array('destination_id_property' => 'destination_value_' . $status);
       $id_map->saveIdMapping($row, $destination, $status);
-      $expected_results[] = [
+      $expected_results[] = array(
         'sourceid1' => 'source_value_' . $status,
         'destid1' => 'destination_value_' . $status,
         'source_row_status' => $status,
         'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE,
         'hash' => '',
-      ];
+      );
     }
 
     // Assert that test values exist.
-    $this->queryResultTest($this->getIdMapContents(), $expected_results);
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_results);
 
     // Mark all rows as STATUS_NEEDS_UPDATE.
     $id_map->prepareUpdate();
@@ -707,7 +663,7 @@ public function testPrepareUpdate() {
       $expected_results[$key]['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE;
     }
     // Assert that updated expected values match.
-    $this->queryResultTest($this->getIdMapContents(), $expected_results);
+    $this->queryResultTest($this->database->databaseContents['migrate_map_sql_idmap_test'], $expected_results);
   }
 
   /**
@@ -724,9 +680,9 @@ public function testDestroy() {
     $id_map->getDatabase();
     $map_table_name = $id_map->mapTableName();
     $message_table_name = $id_map->messageTableName();
-    $row = new Row(['source_id_property' => 'source_value'], ['source_id_property' => []]);
-    $id_map->saveIdMapping($row, ['destination_id_property' => 2]);
-    $id_map->saveMessage(['source_value'], 'A message');
+    $row = new Row(array('source_id_property' => 'source_value'), array('source_id_property' => array()));
+    $id_map->saveIdMapping($row, array('destination_id_property' => 2));
+    $id_map->saveMessage(array('source_value'), 'A message');
     $this->assertTrue($this->database->schema()->tableExists($map_table_name),
                       "$map_table_name exists");
     $this->assertTrue($this->database->schema()->tableExists($message_table_name),
@@ -739,20 +695,21 @@ public function testDestroy() {
   }
 
   /**
+   * Tests the getQualifiedMapTable method with an unprefixed database.
+   */
+  public function testGetQualifiedMapTableNoPrefix() {
+    $id_map = $this->getIdMap(array(), array('database' => 'source_database'));
+    $qualified_map_table = $id_map->getQualifiedMapTableName();
+    $this->assertEquals('source_database.migrate_map_sql_idmap_test', $qualified_map_table);
+  }
+
+  /**
    * Tests the getQualifiedMapTable method with a prefixed database.
    */
   public function testGetQualifiedMapTablePrefix() {
-    $this->database = $this->getDatabase([], ['database' => 'source_database', 'prefix' => 'prefix']);
-    $qualified_map_table = $this->getIdMap()->getQualifiedMapTableName();
-    // The SQLite driver is a special flower. It will prefix tables with
-    // PREFIX.TABLE, instead of the standard PREFIXTABLE.
-    // @see \Drupal\Core\Database\Driver\sqlite\Connection::__construct()
-    if ($this->database->driver() == 'sqlite') {
-      $this->assertEquals('prefix.migrate_map_sql_idmap_test', $qualified_map_table);
-    }
-    else {
-      $this->assertEquals('source_database.prefixmigrate_map_sql_idmap_test', $qualified_map_table);
-    }
+    $id_map = $this->getIdMap(array(), array('database' => 'source_database'), 'prefix');
+    $qualified_map_table = $id_map->getQualifiedMapTableName();
+    $this->assertEquals('source_database.prefixmigrate_map_sql_idmap_test', $qualified_map_table);
   }
 
   /**
@@ -766,32 +723,18 @@ public function testGetQualifiedMapTablePrefix() {
    * - Sql::current()
    */
   public function testIterators() {
+    $database_contents['migrate_map_sql_idmap_test'] = array();
     for ($i = 0; $i < 3; $i++) {
       $row = $this->idMapDefaults();
       $row['sourceid1'] = "source_id_value_$i";
       $row['destid1'] = "destination_id_value_$i";
       $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED;
-      $expected_results[serialize(['sourceid1' => $row['sourceid1']])] = ['destid1' => $row['destid1']];
-      $this->saveMap($row);
+      $expected_results[serialize(array('sourceid1' => $row['sourceid1']))] = array('destid1' => $row['destid1']);
+      $database_contents['migrate_map_sql_idmap_test'][] = $row;
     }
 
-    $this->assertSame(iterator_to_array($this->getIdMap()), $expected_results);
-  }
-
-  private function getIdMapContents() {
-    $result = $this->database
-      ->select('migrate_map_sql_idmap_test', 't')
-      ->fields('t')
-      ->execute();
-
-    // The return value needs to be countable, or it will fail certain
-    // assertions. iterator_to_array() will not suffice because it won't
-    // respect the PDO fetch mode, if specified.
-    $contents = [];
-    foreach ($result as $row) {
-      $contents[] = (array) $row;
-    }
-    return $contents;
+    $id_map = $this->getIdMap($database_contents);
+    $this->assertSame(iterator_to_array($id_map), $expected_results);
   }
 
 }
diff --git a/core/modules/migrate/tests/src/Unit/MigrateTestCase.php b/core/modules/migrate/tests/src/Unit/MigrateTestCase.php
index 7a84125..5f8154b 100644
--- a/core/modules/migrate/tests/src/Unit/MigrateTestCase.php
+++ b/core/modules/migrate/tests/src/Unit/MigrateTestCase.php
@@ -7,16 +7,15 @@
 
 namespace Drupal\Tests\migrate\Unit;
 
-use Drupal\Core\Database\Driver\sqlite\Connection;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Tests\UnitTestCase;
+use Drupal\Core\Database\Driver\fake\FakeConnection;
 
 /**
  * Provides setup and helper methods for Migrate module tests.
  */
 abstract class MigrateTestCase extends UnitTestCase {
 
-  protected $migrationConfiguration = [];
+  protected $migrationConfiguration = array();
 
   /**
    * Retrieve a mocked migration.
@@ -55,59 +54,21 @@ protected function getMigration() {
   }
 
   /**
-   * Get an SQLite database connection object for use in tests.
+   * Get a fake database connection object for use in tests.
    *
    * @param array $database_contents
    *   The database contents faked as an array. Each key is a table name, each
    *   value is a list of table rows, an associative array of field => value.
    * @param array $connection_options
-   *  (optional) Options for the database connection.
+   *   (optional) The array of connection options for the database.
+   * @param string $prefix
+   *   (optional) The table prefix on the database.
    *
-   * @return \Drupal\Core\Database\Driver\sqlite\Connection
+   * @return \Drupal\Core\Database\Driver\fake\FakeConnection
    *   The database connection.
    */
-  protected function getDatabase(array $database_contents, $connection_options = []) {
-    if (extension_loaded('pdo_sqlite')) {
-      $connection_options['database'] = ':memory:';
-      $pdo = Connection::open($connection_options);
-      $connection = new Connection($pdo, $connection_options);
-    }
-    else {
-      throw new \Exception('pdo_sqlite extension is required.');
-    }
-
-    // Initialize the DIC with a fake module handler for alterable queries.
-    $container = new ContainerBuilder();
-    $container->set('module_handler', $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'));
-    \Drupal::setContainer($container);
-
-    // Create the tables and load them up with data, skipping empty ones.
-    foreach (array_filter($database_contents) as $table => $rows) {
-      $pilot_row = reset($rows);
-      $connection->schema()->createTable($table, $this->createSchemaFromRow($pilot_row));
-
-      $insert = $connection->insert($table)->fields(array_keys($pilot_row));
-      array_walk($rows, [$insert, 'values']);
-      $insert->execute();
-    }
-
-    return $connection;
-  }
-
-  /**
-   * Generates a table schema from a row.
-   *
-   * @param array $row
-   *  The reference row on which to base the schema.
-   *
-   * @return array
-   *  The Schema API-ready table schema.
-   */
-  protected function createSchemaFromRow(array $row) {
-    // SQLite uses loose ("affinity") typing, so it's OK for every column
-    // to be a text field.
-    $fields = array_map(function() { return ['type' => 'text']; }, $row);
-    return ['fields' => $fields];
+  protected function getDatabase(array $database_contents, $connection_options = array(), $prefix = '') {
+    return new FakeConnection($database_contents, $connection_options, $prefix);
   }
 
   /**
diff --git a/core/modules/migrate_drupal/config/optional/migrate.migration.d6_system_maintenance.yml b/core/modules/migrate_drupal/config/optional/migrate.migration.d6_system_maintenance.yml
index 0d93cd1..ee40683 100644
--- a/core/modules/migrate_drupal/config/optional/migrate.migration.d6_system_maintenance.yml
+++ b/core/modules/migrate_drupal/config/optional/migrate.migration.d6_system_maintenance.yml
@@ -1,5 +1,5 @@
 id: d6_system_maintenance
-label: Drupal 6 maintenance page configuration
+label: Drupal 6 maintainence page configuration
 migration_tags:
   - Drupal 6
 source:
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Action.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Action.php
index d3c7533..274190b 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Action.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Action.php
@@ -22,7 +22,8 @@ class Action extends DrupalSqlBase {
    * {@inheritdoc}
    */
   public function query() {
-    $query = $this->select('actions', 'a')
+    $query = $this->database
+      ->select('actions', 'a')
       ->fields('a', array(
         'aid',
         'type',
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Term.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Term.php
index 8d64d39..98aac3d 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Term.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Term.php
@@ -32,8 +32,7 @@ public function query() {
       ->fields('td', array('tid', 'vid', 'name', 'description', 'weight'))
     // This works, but we cannot test that, because there is no support for
     // distinct() in FakeSelect, yet.
-      ->distinct()
-      ->orderBy('tid');
+      ->distinct();
     if (isset($this->configuration['vocabulary'])) {
       $query->condition('vid', $this->configuration['vocabulary'], 'IN');
     }
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/UserPicture.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/UserPicture.php
index c45f269..9efa99d 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/UserPicture.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/UserPicture.php
@@ -24,7 +24,8 @@ class UserPicture extends DrupalSqlBase {
    * {@inheritdoc}
    */
   public function query() {
-    $query = $this->select('users', 'u')
+    $query = $this->getDatabase()
+      ->select('users', 'u')
       ->condition('picture', '', '<>')
       ->fields('u', array('uid', 'access', 'picture'))
       ->orderBy('access');
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d6/FieldInstanceTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d6/FieldInstanceTest.php
index 5a987fc..1eaeef9 100644
--- a/core/modules/migrate_drupal/tests/src/Unit/source/d6/FieldInstanceTest.php
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d6/FieldInstanceTest.php
@@ -21,20 +21,20 @@ class FieldInstanceTest extends MigrateSqlSourceTestCase {
   const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\FieldInstance';
 
   // The fake Migration configuration entity.
-  protected $migrationConfiguration = [
+  protected $migrationConfiguration = array(
     // The id of the entity, can be any string.
     'id' => 'test_fieldinstance',
     // Leave it empty for now.
-    'idlist' => [],
-    'source' => [
-      'plugin' => 'd6_field_instance',
-    ],
-  ];
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd6_fieldinstance',
+    ),
+  );
 
   // We need to set up the database contents; it's easier to do that below.
   // These are sample result queries.
-  protected $expectedResults = [
-    [
+  protected $expectedResults = array(
+    array(
       'field_name' => 'field_body',
       'type_name' => 'page',
       'weight' => 1,
@@ -47,51 +47,50 @@ class FieldInstanceTest extends MigrateSqlSourceTestCase {
       'widget_active' => 1,
       'required' => 1,
       'active' => 1,
-      'global_settings' => [],
-    ],
-  ];
+      'global_settings' => array(),
+    ),
+  );
 
   /**
    * Prepopulate contents with results.
    */
   protected function setUp() {
-    $this->expectedResults[0]['widget_settings'] = [
+    $this->expectedResults[0]['widget_settings'] = array(
       'rows' => 5,
       'size' => 60,
-      'default_value' => [
-        [
+      'default_value' => array(
+        array(
           'value' => '',
           '_error_element' => 'default_value_widget][field_body][0][value',
           'default_value_php' => '',
-        ],
-      ],
-    ];
-    $this->expectedResults[0]['display_settings'] = [
-      'label' => [
+        ),
+      ),
+    );
+    $this->expectedResults[0]['display_settings'] = array(
+      'label' => array(
         'format' => 'above',
         'exclude' => 0,
-      ],
-      'teaser' => [
+      ),
+      'teaser' => array(
         'format' => 'default',
         'exclude' => 0,
-      ],
-      'full' => [
+      ),
+      'full' => array(
         'format' => 'default',
         'exclude' => 0,
-      ],
-    ];
+      ),
+    );
     $this->databaseContents['content_node_field_instance'] = $this->expectedResults;
     $this->databaseContents['content_node_field_instance'][0]['widget_settings'] = serialize($this->expectedResults[0]['widget_settings']);
     $this->databaseContents['content_node_field_instance'][0]['display_settings'] = serialize($this->expectedResults[0]['display_settings']);
-    $this->databaseContents['content_node_field_instance'][0]['global_settings'] = 'a:0:{}';
 
-    $this->databaseContents['content_node_field'][0] = [
+    $this->databaseContents['content_node_field'][0] = array(
       'field_name' => 'field_body',
       'required' => 1,
       'type' => 'text',
       'active' => 1,
-      'global_settings' => serialize([]),
-    ];
+      'global_settings' => serialize(array()),
+    );
     parent::setUp();
   }
 
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionByNodeTypeTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionByNodeTypeTest.php
index e4e7acb..9abbd63 100644
--- a/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionByNodeTypeTest.php
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionByNodeTypeTest.php
@@ -19,118 +19,30 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
   const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\NodeRevision';
 
   // The fake Migration configuration entity.
-  protected $migrationConfiguration = [
+  protected $migrationConfiguration = array(
     'id' => 'test',
     // Leave it empty for now.
-    'idlist' => [],
+    'idlist' => array(),
     // The fake configuration for the source.
-    'source' => [
+    'source' => array(
       'plugin' => 'd6_node_revision',
       'node_type' => 'page',
-    ],
-    'sourceIds' => [
-      'vid' => [
+    ),
+    'sourceIds' => array(
+      'vid' => array(
         'alias' => 'v',
-      ],
-    ],
-    'destinationIds' => [
-      'vid' => [
+      ),
+    ),
+    'destinationIds' => array(
+      'vid' => array(
         // This is where the field schema would go.
-      ],
-    ],
-  ];
+      ),
+    ),
+  );
 
-  protected $databaseContents = [
-    'node' => [
-      [
-        'nid' => 1,
-        'type' => 'page',
-        'language' => 'en',
-        'status' => 1,
-        'created' => 1279051598,
-        'changed' => 1279051598,
-        'comment' => 2,
-        'promote' => 1,
-        'moderate' => 0,
-        'sticky' => 0,
-        'tnid' => 0,
-        'translate' => 0,
-        'vid' => 4,
-        'uid' => 1,
-        'title' => 'title for revision 4 (node 1)',
-      ],
-      [
-        'nid' => 2,
-        'type' => 'article',
-        'language' => 'en',
-        'status' => 1,
-        'created' => 1279290908,
-        'changed' => 1279308993,
-        'comment' => 0,
-        'promote' => 1,
-        'moderate' => 0,
-        'sticky' => 0,
-        'tnid' => 0,
-        'translate' => 0,
-        'vid' => 2,
-        'uid' => 1,
-        'title' => 'title for revision 2 (node 2)',
-      ],
-    ],
-    'node_revisions' => [
-      [
-        'nid' => 1,
-        'vid' => 1,
-        'uid' => 1,
-        'title' => 'title for revision 1 (node 1)',
-        'body' => 'body for revision 1 (node 1)',
-        'teaser' => 'teaser for revision 1 (node 1)',
-        'log' => 'log for revision 1 (node 1)',
-        'format' => 1,
-        'timestamp' => 1279051598,
-      ],
-      [
-        'nid' => 1,
-        'vid' => 3,
-        'uid' => 1,
-        'title' => 'title for revision 3 (node 1)',
-        'body' => 'body for revision 3 (node 1)',
-        'teaser' => 'teaser for revision 3 (node 1)',
-        'log' => 'log for revision 3 (node 1)',
-        'format' => 1,
-        'timestamp' => 1279051598,
-      ],
-      [
-        'nid' => 1,
-        'vid' => 4,
-        'uid' => 1,
-        'title' => 'title for revision 4 (node 1)',
-        'body' => 'body for revision 4 (node 1)',
-        'teaser' => 'teaser for revision 4 (node 1)',
-        'log' => 'log for revision 4 (node 1)',
-        'format' => 1,
-        'timestamp' => 1279051598,
-      ],
-      [
-        'nid' => 2,
-        'vid' => 2,
-        'uid' => 1,
-        'title' => 'title for revision 2 (node 2)',
-        'body' => 'body for revision 2 (node 2)',
-        'teaser' => 'teaser for revision 2 (node 2)',
-        'log' => 'log for revision 2 (node 2)',
-        'format' => 1,
-        'timestamp' => 1279308993,
-      ],
-    ],
-  ];
-
-  // There are three revisions of nid 1; vid 4 is the current one. The
-  // NodeRevision plugin should capture every revision EXCEPT that one.
-  // nid 2 will be ignored because $this->migrationConfiguration specifies
-  // a particular node type.
-  protected $expectedResults = [
-    [
+  protected $expectedResults = array(
+    array(
+      // Node fields.
       'nid' => 1,
       'type' => 'page',
       'language' => 'en',
@@ -143,16 +55,27 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
       'sticky' => 0,
       'tnid' => 0,
       'translate' => 0,
+      // Node revision fields.
       'vid' => 1,
-      'node_uid' => 1,
-      'revision_uid' => 1,
+      'uid' => 1,
       'title' => 'title for revision 1 (node 1)',
       'body' => 'body for revision 1 (node 1)',
       'teaser' => 'teaser for revision 1 (node 1)',
       'log' => 'log for revision 1 (node 1)',
       'format' => 1,
-    ],
-    [
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
       'nid' => 1,
       'type' => 'page',
       'language' => 'en',
@@ -165,15 +88,251 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
       'sticky' => 0,
       'tnid' => 0,
       'translate' => 0,
+      // Node revision fields.
       'vid' => 3,
-      'node_uid' => 1,
-      'revision_uid' => 1,
+      'uid' => 1,
       'title' => 'title for revision 3 (node 1)',
       'body' => 'body for revision 3 (node 1)',
       'teaser' => 'teaser for revision 3 (node 1)',
       'log' => 'log for revision 3 (node 1)',
       'format' => 1,
-    ],
-  ];
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 4,
+      'uid' => 1,
+      'title' => 'title for revision 4 (node 1)',
+      'body' => 'body for revision 4 (node 1)',
+      'teaser' => 'teaser for revision 4 (node 1)',
+      'log' => 'log for revision 4 (node 1)',
+      'format' => 1,
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+  );
+
+  protected $fields = array(
+    'field_test_one' => array(
+      'content_node_field_instance' => array(
+        'field_name' => 'field_test_one',
+        'type_name' => 'page',
+        'weight' => 1,
+        'label' => 'Field Label One',
+        'widget_type' => 'text_textfield',
+        'widget_settings' => 'a:4:{s:4:"rows";i:5;s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:42:"default_value_widget][field_test][0][value";}}s:17:"default_value_php";N;}',
+        'display_settings' => 'a:6:{s:6:"weight";s:2:"31";s:6:"parent";s:0:"";s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
+        'description' => '',
+        'widget_module' => 'text',
+        'widget_active' => 1,
+      ),
+      'content_node_field' => array(
+        'field_name' => 'field_test_one',
+        'type' => 'text',
+        'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+        'required' => 0,
+        'multiple' => 0,
+        'db_storage' => 1,
+        'module' => 'text',
+        'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
+        'active' => 1,
+        'locked' => 0,
+      ),
+    ),
+    'field_test_two' => array(
+      'content_node_field_instance' => array(
+        'field_name' => 'field_test_two',
+        'type_name' => 'page',
+        'weight' => 1,
+        'label' => 'Field Label One',
+        'widget_type' => 'text_textfield',
+        'widget_settings' => 'a:4:{s:4:"rows";i:5;s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:42:"default_value_widget][field_test][0][value";}}s:17:"default_value_php";N;}',
+        'display_settings' => 'a:6:{s:6:"weight";s:2:"31";s:6:"parent";s:0:"";s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
+        'description' => '',
+        'widget_module' => 'text',
+        'widget_active' => 1,
+      ),
+      'content_node_field' => array(
+        'field_name' => 'field_test_two',
+        'type' => 'text',
+        'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+        'required' => 0,
+        'multiple' => 1,
+        'db_storage' => 0,
+        'module' => 'text',
+        'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
+        'active' => 1,
+        'locked' => 0,
+      ),
+
+      // Multi field values.
+      'values' => array(
+        array(
+          'vid' => 1,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 1,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 3,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 3,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 4,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 4,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 2,
+          'nid' => 2,
+          'field_test_two_value' => 'test field node 2',
+          'delta' => 0,
+        ),
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $database_contents = $this->expectedResults;
+
+    $database_contents[] = array(
+      // Node fields.
+      'nid' => 2,
+      'type' => 'article',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279290908,
+      'changed' => 1279308993,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 2,
+      'uid' => 1,
+      'title' => 'title for revision 2 (node 2)',
+      'body' => 'body for revision 2 (node 2)',
+      'teaser' => 'teaser for revision 2 (node 2)',
+      'log' => 'log for revision 2 (node 2)',
+      'format' => 1,
+      'field_test_two' => array(
+        'test field node 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 2',
+      ),
+    );
+
+    foreach ($database_contents as $k => $row) {
+      $this->databaseContents['node_revisions'][$k]['nid'] = $row['nid'];
+      $this->databaseContents['node_revisions'][$k]['vid'] = $row['vid'];
+      $this->databaseContents['node_revisions'][$k]['uid'] = $row['uid'];
+      $this->databaseContents['node_revisions'][$k]['title'] = $row['title'];
+      $this->databaseContents['node_revisions'][$k]['body'] = $row['body'];
+      $this->databaseContents['node_revisions'][$k]['teaser'] = $row['teaser'];
+      $this->databaseContents['node_revisions'][$k]['format'] = $row['format'];
+      $this->databaseContents['node_revisions'][$k]['log'] = $row['log'];
+
+      unset($row['body']);
+      unset($row['teaser']);
+      unset($row['format']);
+      unset($row['log']);
+
+      //$this->databaseContents['node'][$k] = $row;
+      $this->databaseContents['node'][$row['nid']] = $row;
+
+      // Add the column field storage data.
+      $table = 'content_type_' . $row['type'];
+      foreach ($row['fields'] as $field_name => $value) {
+        $this->databaseContents[$table][$k][$field_name . "_value"] = $value;
+        $this->databaseContents[$table][$k]['vid'] = $row['vid'];
+        $this->databaseContents[$table][$k]['nid'] = $row['nid'];
+      }
+      // Unset from results.
+      unset($row['fields']);
+      unset($this->expectedResults[$k]['fields']);
+    }
+
+    // Setup field tables.
+    foreach ($this->fields as $field) {
+      $cnf = $field['content_node_field'];
+      $this->databaseContents['content_node_field'][] = $cnf;
+      $this->databaseContents['content_node_field_instance'][] = $field['content_node_field_instance'];
+
+      // If it's a multi-field then setup a new table.
+      if ($cnf['multiple']) {
+        foreach ($field['values'] as $value) {
+          $this->databaseContents['content_' . $cnf['field_name']][] = $value;
+        }
+      }
+    }
+
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testRetrieval() {
+    // @todo: Fix this as per https://www.drupal.org/node/2299795
+    $this->markTestIncomplete('FakeSelect does not support multiple source identifiers, can not test.');
+  }
 
 }
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionTest.php
index 4dde4b1..d9b17b1 100644
--- a/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionTest.php
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d6/NodeRevisionTest.php
@@ -19,116 +19,28 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
   const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\NodeRevision';
 
   // The fake Migration configuration entity.
-  protected $migrationConfiguration = [
+  protected $migrationConfiguration = array(
     'id' => 'test',
     // Leave it empty for now.
-    'idlist' => [],
+    'idlist' => array(),
     // The fake configuration for the source.
-    'source' => [
+    'source' => array(
       'plugin' => 'd6_node_revision',
-    ],
-    'sourceIds' => [
-      'vid' => [
+    ),
+    'sourceIds' => array(
+      'vid' => array(
         'alias' => 'v',
-      ],
-    ],
-    'destinationIds' => [
-      'vid' => [
+      ),
+    ),
+    'destinationIds' => array(
+      'vid' => array(
         // This is where the field schema would go.
-      ],
-    ],
-  ];
+      ),
+    ),
+  );
 
-  protected $databaseContents = [
-    'node' => [
-      [
-        'nid' => 1,
-        'type' => 'page',
-        'language' => 'en',
-        'status' => 1,
-        'created' => 1279051598,
-        'changed' => 1279051598,
-        'comment' => 2,
-        'promote' => 1,
-        'moderate' => 0,
-        'sticky' => 0,
-        'tnid' => 0,
-        'translate' => 0,
-        'vid' => 4,
-        'uid' => 1,
-        'title' => 'title for revision 1 (node 1)',
-      ],
-      [
-        'nid' => 2,
-        'type' => 'article',
-        'language' => 'en',
-        'status' => 1,
-        'created' => 1279290908,
-        'changed' => 1279308993,
-        'comment' => 0,
-        'promote' => 1,
-        'moderate' => 0,
-        'sticky' => 0,
-        'tnid' => 0,
-        'translate' => 0,
-        'vid' => 2,
-        'uid' => 1,
-        'title' => 'title for revision 2 (node 2)',
-      ],
-    ],
-    'node_revisions' => [
-      [
-        'nid' => 1,
-        'vid' => 1,
-        'uid' => 1,
-        'title' => 'title for revision 1 (node 1)',
-        'body' => 'body for revision 1 (node 1)',
-        'teaser' => 'teaser for revision 1 (node 1)',
-        'log' => 'log for revision 1 (node 1)',
-        'format' => 1,
-        'timestamp' => 1279051598,
-      ],
-      [
-        'nid' => 1,
-        'vid' => 3,
-        'uid' => 1,
-        'title' => 'title for revision 3 (node 1)',
-        'body' => 'body for revision 3 (node 1)',
-        'teaser' => 'teaser for revision 3 (node 1)',
-        'log' => 'log for revision 3 (node 1)',
-        'format' => 1,
-        'timestamp' => 1279051598,
-      ],
-      [
-        'nid' => 1,
-        'vid' => 4,
-        'uid' => 1,
-        'title' => 'title for revision 4 (node 1)',
-        'body' => 'body for revision 4 (node 1)',
-        'teaser' => 'teaser for revision 4 (node 1)',
-        'log' => 'log for revision 4 (node 1)',
-        'format' => 1,
-        'timestamp' => 1279051598,
-      ],
-      [
-        'nid' => 2,
-        'vid' => 2,
-        'uid' => 1,
-        'title' => 'title for revision 2 (node 2)',
-        'body' => 'body for revision 2 (node 2)',
-        'teaser' => 'teaser for revision 2 (node 2)',
-        'log' => 'log for revision 2 (node 2)',
-        'format' => 1,
-        'timestamp' => 1279308993,
-      ],
-    ],
-  ];
-
-  // There are three revisions of nid 1, but the NodeRevision source ignores
-  // the current revision. So only two revisions will be returned here. nid 2
-  // is ignored because it only has one revision (the current one).
-  protected $expectedResults = [
-    [
+  protected $expectedResults = array(
+    array(
       // Node fields.
       'nid' => 1,
       'type' => 'page',
@@ -144,15 +56,24 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
       'translate' => 0,
       // Node revision fields.
       'vid' => 1,
-      'node_uid' => 1,
-      'revision_uid' => 1,
+      'uid' => 1,
       'title' => 'title for revision 1 (node 1)',
       'body' => 'body for revision 1 (node 1)',
       'teaser' => 'teaser for revision 1 (node 1)',
       'log' => 'log for revision 1 (node 1)',
       'format' => 1,
-    ],
-    [
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
       // Node fields.
       'nid' => 1,
       'type' => 'page',
@@ -168,14 +89,246 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
       'translate' => 0,
       // Node revision fields.
       'vid' => 3,
-      'node_uid' => 1,
-      'revision_uid' => 1,
+      'uid' => 1,
       'title' => 'title for revision 3 (node 1)',
       'body' => 'body for revision 3 (node 1)',
       'teaser' => 'teaser for revision 3 (node 1)',
       'log' => 'log for revision 3 (node 1)',
       'format' => 1,
-    ],
-  ];
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 4,
+      'uid' => 1,
+      'title' => 'title for revision 4 (node 1)',
+      'body' => 'body for revision 4 (node 1)',
+      'teaser' => 'teaser for revision 4 (node 1)',
+      'log' => 'log for revision 4 (node 1)',
+      'format' => 1,
+      'field_test_one_value' => 'text for node 1',
+      'field_test_two' => array(
+        'test field node 1, value 1',
+        'test field node 1, value 2',
+      ),
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 1',
+      ),
+    ),
+    array(
+      // Node fields.
+      'nid' => 2,
+      'type' => 'article',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279290908,
+      'changed' => 1279308993,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'tnid' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'vid' => 2,
+      'uid' => 1,
+      'title' => 'title for revision 2 (node 2)',
+      'body' => 'body for revision 2 (node 2)',
+      'teaser' => 'teaser for revision 2 (node 2)',
+      'log' => 'log for revision 2 (node 2)',
+      'format' => 1,
+      'field_test_two' => array(
+        'test field node 2',
+      ),
+
+      // This is just to help with databaseContents and gets unset later.
+      'fields' => array(
+        'field_test_one' => 'text for node 2',
+      ),
+    ),
+  );
+
+  protected $fields = array(
+    'field_test_one' => array(
+      'content_node_field_instance' => array(
+        'field_name' => 'field_test_one',
+        'type_name' => 'page',
+        'weight' => 1,
+        'label' => 'Field Label One',
+        'widget_type' => 'text_textfield',
+        'widget_settings' => 'a:4:{s:4:"rows";i:5;s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:42:"default_value_widget][field_test][0][value";}}s:17:"default_value_php";N;}',
+        'display_settings' => 'a:6:{s:6:"weight";s:2:"31";s:6:"parent";s:0:"";s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
+        'description' => '',
+        'widget_module' => 'text',
+        'widget_active' => 1,
+      ),
+      'content_node_field' => array(
+        'field_name' => 'field_test_one',
+        'type' => 'text',
+        'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+        'required' => 0,
+        'multiple' => 0,
+        'db_storage' => 1,
+        'module' => 'text',
+        'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
+        'active' => 1,
+        'locked' => 0,
+      ),
+    ),
+    'field_test_two' => array(
+      'content_node_field_instance' => array(
+        'field_name' => 'field_test_two',
+        'type_name' => 'page',
+        'weight' => 1,
+        'label' => 'Field Label One',
+        'widget_type' => 'text_textfield',
+        'widget_settings' => 'a:4:{s:4:"rows";i:5;s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:0:"";s:14:"_error_element";s:42:"default_value_widget][field_test][0][value";}}s:17:"default_value_php";N;}',
+        'display_settings' => 'a:6:{s:6:"weight";s:2:"31";s:6:"parent";s:0:"";s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
+        'description' => '',
+        'widget_module' => 'text',
+        'widget_active' => 1,
+      ),
+      'content_node_field' => array(
+        'field_name' => 'field_test_two',
+        'type' => 'text',
+        'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
+        'required' => 0,
+        'multiple' => 1,
+        'db_storage' => 0,
+        'module' => 'text',
+        'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}',
+        'active' => 1,
+        'locked' => 0,
+      ),
+
+      // Multi field values.
+      'values' => array(
+        array(
+          'vid' => 1,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 1,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 3,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 3,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 4,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 1',
+          'delta' => 0,
+        ),
+        array(
+          'vid' => 4,
+          'nid' => 1,
+          'field_test_two_value' => 'test field node 1, value 2',
+          'delta' => 1,
+        ),
+        array(
+          'vid' => 2,
+          'nid' => 2,
+          'field_test_two_value' => 'test field node 2',
+          'delta' => 0,
+        ),
+      ),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    foreach ($this->expectedResults as $k => $row) {
+      $this->databaseContents['node_revisions'][$k]['nid'] = $row['nid'];
+      $this->databaseContents['node_revisions'][$k]['vid'] = $row['vid'];
+      $this->databaseContents['node_revisions'][$k]['uid'] = $row['uid'];
+      $this->databaseContents['node_revisions'][$k]['title'] = $row['title'];
+      $this->databaseContents['node_revisions'][$k]['body'] = $row['body'];
+      $this->databaseContents['node_revisions'][$k]['teaser'] = $row['teaser'];
+      $this->databaseContents['node_revisions'][$k]['format'] = $row['format'];
+      $this->databaseContents['node_revisions'][$k]['log'] = $row['log'];
+
+      unset($row['body']);
+      unset($row['teaser']);
+      unset($row['format']);
+      unset($row['log']);
+
+      //$this->databaseContents['node'][$k] = $row;
+      $this->databaseContents['node'][$row['nid']] = $row;
+
+      // Add the column field storage data.
+      $table = 'content_type_' . $row['type'];
+      foreach ($row['fields'] as $field_name => $value) {
+        $this->databaseContents[$table][$k][$field_name . "_value"] = $value;
+        $this->databaseContents[$table][$k]['vid'] = $row['vid'];
+        $this->databaseContents[$table][$k]['nid'] = $row['nid'];
+      }
+      // Unset from results.
+      unset($row['fields']);
+      unset($this->expectedResults[$k]['fields']);
+    }
+
+    // Setup field tables.
+    foreach ($this->fields as $field) {
+      $cnf = $field['content_node_field'];
+      $this->databaseContents['content_node_field'][] = $cnf;
+      $this->databaseContents['content_node_field_instance'][] = $field['content_node_field_instance'];
+
+      // If it's a multi-field then setup a new table.
+      if ($cnf['multiple']) {
+        foreach ($field['values'] as $value) {
+          $this->databaseContents['content_' . $cnf['field_name']][] = $value;
+        }
+      }
+    }
+
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testRetrieval() {
+    // @todo: Fix this as per https://www.drupal.org/node/2299795
+    $this->markTestIncomplete('FakeSelect does not support multiple source identifiers, can not test.');
+  }
 
 }
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d6/ProfileFieldTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d6/ProfileFieldTest.php
index fe54877..b66c3c9 100644
--- a/core/modules/migrate_drupal/tests/src/Unit/source/d6/ProfileFieldTest.php
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d6/ProfileFieldTest.php
@@ -21,21 +21,21 @@ class ProfileFieldTest extends MigrateSqlSourceTestCase {
   const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\ProfileField';
 
   // The fake Migration configuration entity.
-  protected $migrationConfiguration = [
+  protected $migrationConfiguration = array(
     // The id of the entity, can be any string.
     'id' => 'test_profile_fields',
     // Leave it empty for now.
-    'idlist' => [],
-    'source' => [
+    'idlist' => array(),
+    'source' => array(
       'plugin' => 'd6_profile_field',
-    ],
-  ];
+    ),
+  );
 
   // We need to set up the database contents; it's easier to do that below.
   // These are sample result queries.
   // @todo Add multiple cases.
-  protected $expectedResults = [
-    [
+  protected $expectedResults = array(
+    array(
       'fid' => 1,
       'title' => 'First name',
       'name' => 'profile_first_name',
@@ -48,9 +48,9 @@ class ProfileFieldTest extends MigrateSqlSourceTestCase {
       'register' => 0,
       'visibility' => 2,
       'autocomplete' => 0,
-      'options' => [],
-    ],
-    [
+      'options' => array(),
+    ),
+    array(
       'fid' => 2,
       'title' => 'Last name',
       'name' => 'profile_last_name',
@@ -63,9 +63,9 @@ class ProfileFieldTest extends MigrateSqlSourceTestCase {
       'register' => 0,
       'visibility' => 2,
       'autocomplete' => 0,
-      'options' => [],
-    ],
-    [
+      'options' => array(),
+    ),
+    array(
       'fid' => 3,
       'title' => 'Policy',
       'name' => 'profile_policy',
@@ -78,18 +78,15 @@ class ProfileFieldTest extends MigrateSqlSourceTestCase {
       'register' => 1,
       'visibility' => 2,
       'autocomplete' => 0,
-      'options' => [],
-    ],
-  ];
+      'options' => array(),
+    ),
+  );
 
   /**
    * Prepopulate contents with results.
    */
   protected function setUp() {
     $this->databaseContents['profile_fields'] = $this->expectedResults;
-    foreach ($this->databaseContents['profile_fields'] as &$row) {
-      $row['options'] = serialize([]);
-    }
     parent::setUp();
   }
 
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d6/UserTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d6/UserTest.php
index 3e6dd4e..805e1be 100644
--- a/core/modules/migrate_drupal/tests/src/Unit/source/d6/UserTest.php
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d6/UserTest.php
@@ -75,14 +75,7 @@ protected function setUp() {
     foreach ($this->expectedResults as $k => $row) {
       $this->databaseContents['users'][$k] = $row;
     }
-    // getDatabase() will not create empty tables, so we need to insert data
-    // even if it's irrelevant to the test.
-    $this->databaseContents['users_roles'] = array(
-      array(
-        'uid' => 99,
-        'rid' => 99,
-      ),
-    );
+    $this->databaseContents['users_roles'] = array();
     parent::setUp();
   }
 
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d6/VocabularyTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d6/VocabularyTest.php
index adf3c30..d6db86c 100644
--- a/core/modules/migrate_drupal/tests/src/Unit/source/d6/VocabularyTest.php
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d6/VocabularyTest.php
@@ -19,18 +19,18 @@ class VocabularyTest extends MigrateSqlSourceTestCase {
   const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Vocabulary';
 
   // The fake Migration configuration entity.
-  protected $migrationConfiguration = [
+  protected $migrationConfiguration = array(
     // The ID of the entity, can be any string.
     'id' => 'test',
     // Leave it empty for now.
-    'idlist' => [],
-    'source' => [
+    'idlist' => array(),
+    'source' => array(
       'plugin' => 'd6_vocabulary',
-    ],
-  ];
+    ),
+  );
 
-  protected $expectedResults = [
-    [
+  protected $expectedResults = array(
+    array(
       'vid' => 1,
       'name' => 'Tags',
       'description' => 'Tags description.',
@@ -42,9 +42,9 @@ class VocabularyTest extends MigrateSqlSourceTestCase {
       'tags' => 1,
       'module' => 'taxonomy',
       'weight' => 0,
-      'node_types' => ['page', 'article'],
-    ],
-    [
+      'node_types' => array('page', 'article'),
+    ),
+    array(
       'vid' => 2,
       'name' => 'Categories',
       'description' => 'Categories description.',
@@ -56,20 +56,20 @@ class VocabularyTest extends MigrateSqlSourceTestCase {
       'tags' => 0,
       'module' => 'taxonomy',
       'weight' => 0,
-      'node_types' => ['article'],
-    ],
-  ];
+      'node_types' => array('article'),
+    ),
+  );
 
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
-    foreach ($this->expectedResults as &$row) {
+    foreach ($this->expectedResults as $row) {
       foreach ($row['node_types'] as $type) {
-        $this->databaseContents['vocabulary_node_types'][] = [
+        $this->databaseContents['vocabulary_node_types'][] = array(
           'type' => $type,
           'vid' => $row['vid'],
-        ];
+        );
       }
       unset($row['node_types']);
     }
diff --git a/core/modules/node/config/optional/views.view.archive.yml b/core/modules/node/config/optional/views.view.archive.yml
index 56ae50e..209346d 100644
--- a/core/modules/node/config/optional/views.view.archive.yml
+++ b/core/modules/node/config/optional/views.view.archive.yml
@@ -32,7 +32,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       exposed_form:
         type: basic
diff --git a/core/modules/node/config/optional/views.view.content.yml b/core/modules/node/config/optional/views.view.content.yml
index c8201f2..7849a0c 100644
--- a/core/modules/node/config/optional/views.view.content.yml
+++ b/core/modules/node/config/optional/views.view.content.yml
@@ -20,7 +20,7 @@ display:
         options:
           perm: 'access content overview'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/node/config/optional/views.view.content_recent.yml b/core/modules/node/config/optional/views.view.content_recent.yml
index 1d46cf5..500e1fa 100644
--- a/core/modules/node/config/optional/views.view.content_recent.yml
+++ b/core/modules/node/config/optional/views.view.content_recent.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/node/config/optional/views.view.frontpage.yml b/core/modules/node/config/optional/views.view.frontpage.yml
index 8b51ebb..2d9f093 100644
--- a/core/modules/node/config/optional/views.view.frontpage.yml
+++ b/core/modules/node/config/optional/views.view.frontpage.yml
@@ -20,7 +20,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       empty:
         area_text_custom:
diff --git a/core/modules/node/config/optional/views.view.glossary.yml b/core/modules/node/config/optional/views.view.glossary.yml
index 63bf6f7..1738e43 100644
--- a/core/modules/node/config/optional/views.view.glossary.yml
+++ b/core/modules/node/config/optional/views.view.glossary.yml
@@ -33,7 +33,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       exposed_form:
         type: basic
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index f7374da..a448b6c 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -567,7 +567,7 @@ function node_theme_suggestions_node(array $variables) {
  *   An associative array containing:
  *   - elements: An array of elements to display in view mode.
  *   - node: The node object.
- *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
+ *   - view_mode: View mode; e.g., 'full', 'teaser'...
  */
 function template_preprocess_node(&$variables) {
   $variables['view_mode'] = $variables['elements']['#view_mode'];
@@ -785,7 +785,7 @@ function node_get_recent($number = 10) {
  * @param \Drupal\node\NodeInterface $node
  *   A node entity.
  * @param $view_mode
- *   (optional) View mode, e.g., 'full', 'teaser', etc. Defaults to 'full.'
+ *   (optional) View mode, e.g., 'full', 'teaser'... Defaults to 'full.'
  * @param $langcode
  *   (optional) A language code to use for rendering. Defaults to NULL which is
  *   the global content language of the current request.
@@ -803,7 +803,7 @@ function node_view(NodeInterface $node, $view_mode = 'full', $langcode = NULL) {
  * @param $nodes
  *   An array of nodes as returned by Node::loadMultiple().
  * @param $view_mode
- *   (optional) View mode, e.g., 'full', 'teaser', etc. Defaults to 'teaser.'
+ *   (optional) View mode, e.g., 'full', 'teaser'... Defaults to 'teaser.'
  * @param $langcode
  *   (optional) A language code to use for rendering. Defaults to the global
  *   content language of the current request.
diff --git a/core/modules/node/src/Form/DeleteMultiple.php b/core/modules/node/src/Form/DeleteMultiple.php
index 227d4ba..e7cb6ea 100644
--- a/core/modules/node/src/Form/DeleteMultiple.php
+++ b/core/modules/node/src/Form/DeleteMultiple.php
@@ -9,11 +9,12 @@
 
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
-use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\user\PrivateTempStoreFactory;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides a node deletion confirmation form.
@@ -23,9 +24,9 @@ class DeleteMultiple extends ConfirmFormBase {
   /**
    * The array of nodes to delete.
    *
-   * @var string[][]
+   * @var array
    */
-  protected $nodeInfo = array();
+  protected $nodes = array();
 
   /**
    * The tempstore factory.
@@ -75,7 +76,7 @@ public function getFormId() {
    * {@inheritdoc}
    */
   public function getQuestion() {
-    return $this->formatPlural(count($this->nodeInfo), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
+    return $this->formatPlural(count($this->nodes), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
   }
 
   /**
@@ -96,48 +97,16 @@ public function getConfirmText() {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state) {
-    $this->nodeInfo = $this->tempStoreFactory->get('node_multiple_delete_confirm')->get(\Drupal::currentUser()->id());
-    if (empty($this->nodeInfo)) {
+    $this->nodes = $this->tempStoreFactory->get('node_multiple_delete_confirm')->get(\Drupal::currentUser()->id());
+    if (empty($this->nodes)) {
       return new RedirectResponse($this->getCancelUrl()->setAbsolute()->toString());
     }
-    /** @var \Drupal\node\NodeInterface[] $nodes */
-    $nodes = $this->storage->loadMultiple(array_keys($this->nodeInfo));
-
-    $items = [];
-    foreach ($this->nodeInfo as $id => $langcodes) {
-      foreach ($langcodes as $langcode) {
-        $node = $nodes[$id]->getTranslation($langcode);
-        $key = $id . ':' . $langcode;
-        $default_key = $id . ':' . $node->getUntranslated()->language()->getId();
-
-        // If we have a translated entity we build a nested list of translations
-        // that will be deleted.
-        $languages = $node->getTranslationLanguages();
-        if (count($languages) > 1 && $node->isDefaultTranslation()) {
-          $names = [];
-          foreach ($languages as $translation_langcode => $language) {
-            $names[] = $language->getName();
-            unset($items[$id . ':' . $translation_langcode]);
-          }
-          $items[$default_key] = [
-            'label' => [
-              '#markup' => $this->t('@label (Original translation) - <em>The following content translations will be deleted:</em>', ['@label' => $node->label()]),
-            ],
-            'deleted_translations' => [
-              '#theme' => 'item_list',
-              '#items' => $names,
-            ],
-          ];
-        }
-        elseif (!isset($items[$default_key])) {
-          $items[$key] = $node->label();
-        }
-      }
-    }
 
     $form['nodes'] = array(
       '#theme' => 'item_list',
-      '#items' => $items,
+      '#items' => array_map(function ($node) {
+        return SafeMarkup::checkPlain($node->label());
+      }, $this->nodes),
     );
     $form = parent::buildForm($form, $form_state);
 
@@ -148,56 +117,13 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
-    if ($form_state->getValue('confirm') && !empty($this->nodeInfo)) {
-      $total_count = 0;
-      $delete_nodes = [];
-      /** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
-      $delete_translations = [];
-      /** @var \Drupal\node\NodeInterface[] $nodes */
-      $nodes = $this->storage->loadMultiple(array_keys($this->nodeInfo));
-
-      foreach ($this->nodeInfo as $id => $langcodes) {
-        foreach ($langcodes as $langcode) {
-          $node = $nodes[$id]->getTranslation($langcode);
-          if ($node->isDefaultTranslation()) {
-            $delete_nodes[$id] = $node;
-            unset($delete_translations[$id]);
-            $total_count += count($node->getTranslationLanguages());
-          }
-          elseif (!isset($delete_nodes[$id])) {
-            $delete_translations[$id][] = $node;
-          }
-        }
-      }
-
-      if ($delete_nodes) {
-        $this->storage->delete($delete_nodes);
-        $this->logger('content')->notice('Deleted @count posts.', array('@count' => count($delete_nodes)));
-      }
-
-      if ($delete_translations) {
-        $count = 0;
-        foreach ($delete_translations as $id => $translations) {
-          $node = $nodes[$id]->getUntranslated();
-          foreach ($translations as $translation) {
-            $node->removeTranslation($translation->language()->getId());
-          }
-          $node->save();
-          $count += count($translations);
-        }
-        if ($count) {
-          $total_count += $count;
-          $this->logger('content')->notice('Deleted @count content translations.', array('@count' => $count));
-        }
-      }
-
-      if ($total_count) {
-        drupal_set_message($this->formatPlural($total_count, 'Deleted 1 post.', 'Deleted @count posts.'));
-      }
-
+    if ($form_state->getValue('confirm') && !empty($this->nodes)) {
+      $this->storage->delete($this->nodes);
       $this->tempStoreFactory->get('node_multiple_delete_confirm')->delete(\Drupal::currentUser()->id());
+      $count = count($this->nodes);
+      $this->logger('content')->notice('Deleted @count posts.', array('@count' => $count));
+      drupal_set_message($this->formatPlural($count, 'Deleted 1 post.', 'Deleted @count posts.'));
     }
-
     $form_state->setRedirect('system.admin_content');
   }
 
diff --git a/core/modules/node/src/Plugin/Action/DeleteNode.php b/core/modules/node/src/Plugin/Action/DeleteNode.php
index 4321396..d633dc8 100644
--- a/core/modules/node/src/Plugin/Action/DeleteNode.php
+++ b/core/modules/node/src/Plugin/Action/DeleteNode.php
@@ -77,13 +77,7 @@ public static function create(ContainerInterface $container, array $configuratio
    * {@inheritdoc}
    */
   public function executeMultiple(array $entities) {
-    $info = [];
-    /** @var \Drupal\node\NodeInterface $node */
-    foreach ($entities as $node) {
-      $langcode = $node->language()->getId();
-      $info[$node->id()][$langcode] = $langcode;
-    }
-    $this->tempStore->set($this->currentUser->id(), $info);
+    $this->tempStore->set($this->currentUser->id(), $entities);
   }
 
   /**
diff --git a/core/modules/node/src/Plugin/Action/SaveNode.php b/core/modules/node/src/Plugin/Action/SaveNode.php
index 2655173..4e56e8a 100644
--- a/core/modules/node/src/Plugin/Action/SaveNode.php
+++ b/core/modules/node/src/Plugin/Action/SaveNode.php
@@ -25,9 +25,6 @@ class SaveNode extends ActionBase {
    * {@inheritdoc}
    */
   public function execute($entity = NULL) {
-    // We need to change at least one value, otherwise the changed timestamp
-    // will not be updated.
-    $entity->changed = 0;
     $entity->save();
   }
 
diff --git a/core/modules/node/src/Plugin/views/row/Rss.php b/core/modules/node/src/Plugin/views/row/Rss.php
index 37261c1..b97bb64 100644
--- a/core/modules/node/src/Plugin/views/row/Rss.php
+++ b/core/modules/node/src/Plugin/views/row/Rss.php
@@ -111,7 +111,7 @@ public function render($row) {
       return;
     }
 
-    $description_build = [];
+    $item_text = '';
 
     $node->link = $node->url('canonical', array('absolute' => TRUE));
     $node->rss_namespaces = array();
@@ -154,25 +154,22 @@ public function render($row) {
 
     if ($display_mode != 'title') {
       // We render node contents.
-      $description_build = $build;
+      $item_text .= drupal_render_root($build);
     }
 
     $item = new \stdClass();
-    $item->description = $description_build;
+    $item->description = SafeMarkup::set($item_text);
     $item->title = $node->label();
     $item->link = $node->link;
-    // Provide a reference so that the render call in
-    // template_preprocess_views_view_row_rss() can still access it.
-    $item->elements = &$node->rss_elements;
+    $item->elements = $node->rss_elements;
     $item->nid = $node->id();
-    $build = array(
+    $theme_function = array(
       '#theme' => $this->themeFunctions(),
       '#view' => $this->view,
       '#options' => $this->options,
       '#row' => $item,
     );
-
-    return $build;
+    return drupal_render_root($theme_function);
   }
 
 }
diff --git a/core/modules/node/src/Tests/NodeTokenReplaceTest.php b/core/modules/node/src/Tests/NodeTokenReplaceTest.php
index 1ba3003..ffef457 100644
--- a/core/modules/node/src/Tests/NodeTokenReplaceTest.php
+++ b/core/modules/node/src/Tests/NodeTokenReplaceTest.php
@@ -73,8 +73,8 @@ function testNodeTokenReplacement() {
     $tests['[node:author]'] = SafeMarkup::checkPlain($account->getUsername());
     $tests['[node:author:uid]'] = $node->getOwnerId();
     $tests['[node:author:name]'] = SafeMarkup::checkPlain($account->getUsername());
-    $tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getCreatedTime(), array('langcode' => $this->interfaceLanguage->getId()));
-    $tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime(), array('langcode' => $this->interfaceLanguage->getId()));
+    $tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->getCreatedTime(), 2, $this->interfaceLanguage->getId());
+    $tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->getChangedTime(), 2, $this->interfaceLanguage->getId());
 
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
diff --git a/core/modules/node/src/Tests/Views/BulkFormTest.php b/core/modules/node/src/Tests/Views/BulkFormTest.php
index 2e46be5..3ab918a 100644
--- a/core/modules/node/src/Tests/Views/BulkFormTest.php
+++ b/core/modules/node/src/Tests/Views/BulkFormTest.php
@@ -7,9 +7,7 @@
 
 namespace Drupal\node\Tests\Views;
 
-use Drupal\Component\Utility\SafeMarkup;
-use Drupal\language\Entity\ConfigurableLanguage;
-use Drupal\views\Views;
+use Drupal\node\Entity\Node;
 
 /**
  * Tests a node bulk form.
@@ -20,13 +18,6 @@
 class BulkFormTest extends NodeTestBase {
 
   /**
-   * Modules to be enabled.
-   *
-   * @var array
-   */
-  public static $modules = array('node_test_views', 'language');
-
-  /**
    * Views used by this test.
    *
    * @var array
@@ -34,87 +25,30 @@ class BulkFormTest extends NodeTestBase {
   public static $testViews = array('test_node_bulk_form');
 
   /**
-   * The test nodes.
-   *
-   * @var \Drupal\node\NodeInterface[]
-   */
-  protected $nodes;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp($import_test_views = TRUE) {
-    parent::setUp($import_test_views);
-
-    ConfigurableLanguage::createFromLangcode('fr')->save();
-    ConfigurableLanguage::createFromLangcode('it')->save();
-
-    // Create some test nodes.
-    $this->nodes = [];
-    $langcodes = ['en', 'fr', 'it'];
-    for ($i = 1; $i <= 5; $i++) {
-      $langcode = $langcodes[($i - 1) % 3];
-      $values = [
-        'title' => $this->randomMachineName() . ' [' . $i . ':' . $langcode . ']',
-        'langcode' => $langcode,
-        'promote' => FALSE,
-      ];
-      $node = $this->drupalCreateNode($values);
-      $this->pass(SafeMarkup::format('Node %title created with language %langcode.', ['%title' => $node->label(), '%langcode' => $node->language()->getId()]));
-      $this->nodes[] = $node;
-    }
-
-    // Create translations for all languages for some nodes.
-    for ($i = 0; $i < 2; $i++) {
-      $node = $this->nodes[$i];
-      foreach ($langcodes as $langcode) {
-        if (!$node->hasTranslation($langcode)) {
-          $title = $this->randomMachineName() . ' [' . $node->id() . ':' . $langcode . ']';
-          $translation = $node->addTranslation($langcode, ['title' => $title, 'promote' => FALSE]);
-          $this->pass(SafeMarkup::format('Translation %title created with language %langcode.', ['%title' => $translation->label(), '%langcode' => $translation->language()->getId()]));
-        }
-      }
-      $node->save();
-    }
-
-    // Create a node with only one translation.
-    $node = $this->nodes[2];
-    $langcode = 'en';
-    $title = $this->randomMachineName() . ' [' . $node->id() . ':' . $langcode . ']';
-    $translation = $node->addTranslation($langcode, ['title' => $title]);
-    $this->pass(SafeMarkup::format('Translation %title created with language %langcode.', ['%title' => $translation->label(), '%langcode' => $translation->language()->getId()]));
-    $node->save();
-
-    // Check that all created translations are selected by the test view.
-    $view = Views::getView('test_node_bulk_form');
-    $view->execute();
-    $this->assertEqual(count($view->result), 10, 'All created translations are selected.');
-
-    // Check the operations are accessible to the logged in user.
-    $this->drupalLogin($this->drupalCreateUser(array('administer nodes', 'access content overview', 'bypass node access')));
-    $this->drupalGet('test-node-bulk-form');
-    $elements = $this->xpath('//select[@id="edit-action"]//option');
-    $this->assertIdentical(count($elements), 8, 'All node operations are found.');
-  }
-
-  /**
    * Tests the node bulk form.
    */
   public function testBulkForm() {
+    $node_storage = $this->container->get('entity.manager')->getStorage('node');
+    $this->drupalLogin($this->drupalCreateUser(array('administer nodes', 'access content overview', 'bypass node access')));
+    $node = $this->drupalCreateNode(array(
+      'promote' => FALSE,
+    ));
+
+    $this->drupalGet('test-node-bulk-form');
+    $elements = $this->xpath('//select[@id="edit-action"]//option');
+    $this->assertIdentical(count($elements), 8, 'All node operations are found.');
+
     // Unpublish a node using the bulk form.
-    $node = reset($this->nodes);
     $this->assertTrue($node->isPublished(), 'Node is initially published');
-    $this->assertTrue($node->getTranslation('fr')->isPublished(), 'Node translation is published');
-    $this->assertTrue($node->getTranslation('it')->isPublished(), 'Node translation is published');
     $edit = array(
       'node_bulk_form[0]' => TRUE,
       'action' => 'node_unpublish_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode($node->id());
+    // Re-load the node and check the status.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
     $this->assertFalse($node->isPublished(), 'Node has been unpublished');
-    $this->assertTrue($node->getTranslation('fr')->isPublished(), 'Node translation has not been unpublished');
-    $this->assertTrue($node->getTranslation('it')->isPublished(), 'Node translation has not been unpublished');
 
     // Publish action.
     $edit = array(
@@ -122,22 +56,22 @@ public function testBulkForm() {
       'action' => 'node_publish_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode($node->id());
-    $this->assertTrue($node->isPublished(), 'Node has been published again');
+    // Re-load the node and check the status.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
+    $this->assertTrue($node->isPublished(), 'Node has been published');
 
     // Make sticky action.
     $this->assertFalse($node->isSticky(), 'Node is not sticky');
-    $this->assertFalse($node->getTranslation('fr')->isSticky(), 'Node translation is not sticky');
-    $this->assertFalse($node->getTranslation('it')->isSticky(), 'Node translation is not sticky');
     $edit = array(
       'node_bulk_form[0]' => TRUE,
       'action' => 'node_make_sticky_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode($node->id());
-    $this->assertTrue($node->isPublished(), 'Node has been made sticky');
-    $this->assertFalse($node->getTranslation('fr')->isSticky(), 'Node translation has not been made sticky');
-    $this->assertFalse($node->getTranslation('it')->isSticky(), 'Node translation has not been made sticky');
+    // Re-load the node and check the sticky flag.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
+    $this->assertTrue($node->isSticky(), 'Node has been made sticky');
 
     // Make unsticky action.
     $edit = array(
@@ -145,22 +79,22 @@ public function testBulkForm() {
       'action' => 'node_make_unsticky_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode($node->id());
+    // Re-load the node and check the sticky flag.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
     $this->assertFalse($node->isSticky(), 'Node is not sticky anymore');
 
     // Promote to front page.
     $this->assertFalse($node->isPromoted(), 'Node is not promoted to the front page');
-    $this->assertFalse($node->getTranslation('fr')->isPromoted(), 'Node translation is not promoted to the front page');
-    $this->assertFalse($node->getTranslation('it')->isPromoted(), 'Node translation is not promoted to the front page');
     $edit = array(
       'node_bulk_form[0]' => TRUE,
       'action' => 'node_promote_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode($node->id());
+    // Re-load the node and check the promoted flag.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
     $this->assertTrue($node->isPromoted(), 'Node has been promoted to the front page');
-    $this->assertFalse($node->getTranslation('fr')->isPromoted(), 'Node translation has not been promoted to the front page');
-    $this->assertFalse($node->getTranslation('it')->isPromoted(), 'Node translation has not been promoted to the front page');
 
     // Demote from front page.
     $edit = array(
@@ -168,113 +102,22 @@ public function testBulkForm() {
       'action' => 'node_unpromote_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode($node->id());
+    // Re-load the node and check the promoted flag.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
     $this->assertFalse($node->isPromoted(), 'Node has been demoted');
 
-    // Select a bunch of translated and untranslated nodes and check that
-    // operations are always applied to individual translations.
+    // Delete node.
     $edit = array(
-      // Original and all translations.
-      'node_bulk_form[0]' => TRUE,  // Node 1, English, original.
-      'node_bulk_form[1]' => TRUE,  // Node 1, French.
-      'node_bulk_form[2]' => TRUE,  // Node 1, Italian.
-      // Original and only one translation.
-      'node_bulk_form[3]' => TRUE,  // Node 2, English.
-      'node_bulk_form[4]' => TRUE,  // Node 2, French, original.
-      'node_bulk_form[5]' => FALSE, // Node 2, Italian.
-      // Only a single translation.
-      'node_bulk_form[6]' => TRUE,  // Node 3, English.
-      'node_bulk_form[7]' => FALSE, // Node 3, Italian, original.
-      // Only a single untranslated node.
-      'node_bulk_form[8]' => TRUE,  // Node 4, English, untranslated.
-      'node_bulk_form[9]' => FALSE, // Node 5, French, untranslated.
-      'action' => 'node_unpublish_action',
-    );
-    $this->drupalPostForm(NULL, $edit, t('Apply'));
-    $node = $this->loadNode(1);
-    $this->assertFalse($node->getTranslation('en')->isPublished(), '1: English translation has been unpublished');
-    $this->assertFalse($node->getTranslation('fr')->isPublished(), '1: French translation has been unpublished');
-    $this->assertFalse($node->getTranslation('it')->isPublished(), '1: Italian translation has been unpublished');
-    $node = $this->loadNode(2);
-    $this->assertFalse($node->getTranslation('en')->isPublished(), '2: English translation has been unpublished');
-    $this->assertFalse($node->getTranslation('fr')->isPublished(), '2: French translation has been unpublished');
-    $this->assertTrue($node->getTranslation('it')->isPublished(), '2: Italian translation has not been unpublished');
-    $node = $this->loadNode(3);
-    $this->assertFalse($node->getTranslation('en')->isPublished(), '3: English translation has been unpublished');
-    $this->assertTrue($node->getTranslation('it')->isPublished(), '3: Italian translation has not been unpublished');
-    $node = $this->loadNode(4);
-    $this->assertFalse($node->isPublished(), '4: Node has been unpublished');
-    $node = $this->loadNode(5);
-    $this->assertTrue($node->isPublished(), '5: Node has not been unpublished');
-  }
-
-  /**
-   * Test multiple deletion.
-   */
-  public function testBulkDeletion() {
-    // Select a bunch of translated and untranslated nodes and check that
-    // nodes and individual translations are properly deleted.
-    $edit = array(
-      // Original and all translations.
-      'node_bulk_form[0]' => TRUE,  // Node 1, English, original.
-      'node_bulk_form[1]' => TRUE,  // Node 1, French.
-      'node_bulk_form[2]' => TRUE,  // Node 1, Italian.
-      // Original and only one translation.
-      'node_bulk_form[3]' => TRUE,  // Node 2, English.
-      'node_bulk_form[4]' => TRUE,  // Node 2, French, original.
-      'node_bulk_form[5]' => FALSE, // Node 2, Italian.
-      // Only a single translation.
-      'node_bulk_form[6]' => TRUE,  // Node 3, English.
-      'node_bulk_form[7]' => FALSE, // Node 3, Italian, original.
-      // Only a single untranslated node.
-      'node_bulk_form[8]' => TRUE,  // Node 4, English, untranslated.
-      'node_bulk_form[9]' => FALSE, // Node 5, French, untranslated.
+      'node_bulk_form[0]' => TRUE,
       'action' => 'node_delete_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-
-    $label = $this->loadNode(1)->label();
-    $this->assertText("$label (Original translation) - The following content translations will be deleted:");
-    $label = $this->loadNode(2)->label();
-    $this->assertText("$label (Original translation) - The following content translations will be deleted:");
-    $label = $this->loadNode(3)->getTranslation('en')->label();
-    $this->assertText($label);
-    $this->assertNoText("$label (Original translation) - The following content translations will be deleted:");
-    $label = $this->loadNode(4)->label();
-    $this->assertText($label);
-    $this->assertNoText("$label (Original translation) - The following content translations will be deleted:");
-
     $this->drupalPostForm(NULL, array(), t('Delete'));
-
-    $node = $this->loadNode(1);
-    $this->assertNull($node, '1: Node has been deleted');
-    $node = $this->loadNode(2);
-    $this->assertNull($node, '2: Node has been deleted');
-    $node = $this->loadNode(3);
-    $result = count($node->getTranslationLanguages()) && $node->language()->getId() == 'it';
-    $this->assertTrue($result, '3: English translation has been deleted');
-    $node = $this->loadNode(4);
-    $this->assertNull($node, '4: Node has been deleted');
-    $node = $this->loadNode(5);
-    $this->assertTrue($node, '5: Node has not been deleted');
-
-    $this->assertText('Deleted 8 posts.');
-  }
-
-  /**
-   * Load the specified node from the storage.
-   *
-   * @param int $id
-   *   The node identifier.
-   *
-   * @return \Drupal\node\NodeInterface
-   *   The loaded node.
-   */
-  protected function loadNode($id) {
-    /** @var \Drupal\node\NodeStorage $storage */
-    $storage = $this->container->get('entity.manager')->getStorage('node');
-    $storage->resetCache([$id]);
-    return $storage->load($id);
+    // Re-load the node and check if it has been deleted.
+    $node_storage->resetCache(array($node->id()));
+    $node = $node_storage->load($node->id());
+    $this->assertNull($node, 'Node has been deleted');
   }
 
 }
diff --git a/core/modules/node/src/Tests/Views/FrontPageTest.php b/core/modules/node/src/Tests/Views/FrontPageTest.php
index b3ab9c9..04414dc 100644
--- a/core/modules/node/src/Tests/Views/FrontPageTest.php
+++ b/core/modules/node/src/Tests/Views/FrontPageTest.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Url;
 use Drupal\node\Entity\Node;
+use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 use Drupal\views\Tests\AssertViewsCacheTagsTrait;
 use Drupal\views\Tests\ViewTestBase;
 use Drupal\views\ViewExecutable;
@@ -23,6 +24,7 @@
  */
 class FrontPageTest extends ViewTestBase {
 
+  use AssertPageCacheContextsAndTagsTrait;
   use AssertViewsCacheTagsTrait;
 
   /**
@@ -291,7 +293,6 @@ protected function assertFrontPageViewCacheTags($do_assert_views_caches) {
       'timezone',
     ]);
 
-    $this->pass('First page');
     // First page.
     $first_page_result_cache_tags = [
       'config:views.view.frontpage',
@@ -328,7 +329,6 @@ protected function assertFrontPageViewCacheTags($do_assert_views_caches) {
     );
 
     // Second page.
-    $this->pass('Second page');
     $this->assertPageCacheContextsAndTags(Url::fromRoute('view.frontpage.page_1', [], ['query' => ['page' => 1]]), $cache_contexts, [
       // The cache tags for the listed nodes.
       'node:1',
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml
index bd561b1..b25fafc 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml
@@ -20,7 +20,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       pager:
         type: full
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
index e476eae..ef61852 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml
index 4f8ba50..2bcce2f 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
index 1ac8f79..bfa5215 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
index 7469b7c..e26e8d3 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
@@ -39,27 +39,12 @@ display:
       sorts:
         nid:
           id: nid
-          table: node_field_data
+          table: node
           field: nid
           order: ASC
           plugin_id: standard
           entity_type: node
           entity_field: nid
-        langcode:
-          id: langcode
-          table: node_field_data
-          field: langcode
-          relationship: none
-          group_type: group
-          admin_label: ''
-          order: ASC
-          exposed: false
-          expose:
-            label: ''
-          entity_type: node
-          entity_field: langcode
-          plugin_id: standard
-      display_extenders: {  }
   page_1:
     display_plugin: page
     id: page_1
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml
index 165180f..7e76af9 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       filters:
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml
index f9c2bdf..e047e68 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml
index 8c6f7cf..b690589 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php b/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php
index 88f9794..327ebc1 100644
--- a/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php
+++ b/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php
@@ -57,8 +57,6 @@ public function testConstructor() {
       ->with('action')
       ->will($this->returnValue($entity_storage));
 
-    $language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
-
     $views_data = $this->getMockBuilder('Drupal\views\ViewsData')
       ->disableOriginalConstructor()
       ->getMock();
@@ -89,7 +87,7 @@ public function testConstructor() {
     $definition['title'] = '';
     $options = array();
 
-    $node_bulk_form = new NodeBulkForm(array(), 'node_bulk_form', $definition, $entity_manager, $language_manager);
+    $node_bulk_form = new NodeBulkForm(array(), 'node_bulk_form', $definition, $entity_manager);
     $node_bulk_form->init($executable, $display, $options);
 
     $this->assertAttributeEquals(array_slice($actions, 0, -1, TRUE), 'actions', $node_bulk_form);
diff --git a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml
index a950bc2..23a2e78 100644
--- a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml
+++ b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml
@@ -26,7 +26,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml
index 3037d6d..7c3b85d 100644
--- a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml
+++ b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml
@@ -26,7 +26,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml
index ae55b85..d2dbb92 100644
--- a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml
+++ b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml
@@ -26,7 +26,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/page_cache/src/Tests/PageCacheTest.php b/core/modules/page_cache/src/Tests/PageCacheTest.php
index da8d5e4..7faa45e 100644
--- a/core/modules/page_cache/src/Tests/PageCacheTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTest.php
@@ -79,16 +79,15 @@ function testPageCacheTags() {
   }
 
   /**
-   * Tests support for different cache items with different request formats
-   * specified via a query parameter.
+   * Tests support for different cache items with different Accept headers.
    */
-  function testQueryParameterFormatRequests() {
+  function testAcceptHeaderRequests() {
     $config = $this->config('system.performance');
     $config->set('cache.page.max_age', 300);
     $config->save();
 
     $accept_header_cache_url = Url::fromRoute('system_test.page_cache_accept_header');
-    $accept_header_cache_url_with_json = Url::fromRoute('system_test.page_cache_accept_header', ['_format' => 'json']);
+    $json_accept_header = array('Accept: application/json');
 
     $this->drupalGet($accept_header_cache_url);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'HTML page was not yet cached.');
@@ -96,9 +95,9 @@ function testQueryParameterFormatRequests() {
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'HTML page was cached.');
     $this->assertRaw('<p>oh hai this is html.</p>', 'The correct HTML response was returned.');
 
-    $this->drupalGet($accept_header_cache_url_with_json);
+    $this->drupalGet($accept_header_cache_url, array(), $json_accept_header);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Json response was not yet cached.');
-    $this->drupalGet($accept_header_cache_url_with_json);
+    $this->drupalGet($accept_header_cache_url, array(), $json_accept_header);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Json response was cached.');
     $this->assertRaw('{"content":"oh hai this is json"}', 'The correct Json response was returned.');
 
@@ -106,8 +105,8 @@ function testQueryParameterFormatRequests() {
     \Drupal::service('module_installer')->install(['node', 'rest', 'hal']);
     $this->drupalCreateContentType(['type' => 'article']);
     $node = $this->drupalCreateNode(['type' => 'article']);
-    $node_uri = $node->urlInfo();
-    $node_url_with_hal_json_format = $node->urlInfo('canonical')->setRouteParameter('_format', 'hal_json');
+    $node_uri = 'node/' . $node->id();
+    $hal_json_accept_header = ['Accept: application/hal+json'];
     /** @var \Drupal\user\RoleInterface $role */
     $role = Role::load('anonymous');
     $role->grantPermission('restful get entity:node');
@@ -122,20 +121,20 @@ function testQueryParameterFormatRequests() {
 
     // Now request a HAL page, we expect that the first request is a cache miss
     // and it serves HTML.
-    $this->drupalGet($node_url_with_hal_json_format);
+    $this->drupalGet($node_uri, [], $hal_json_accept_header);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
     $this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
-    $this->drupalGet($node_url_with_hal_json_format);
+    $this->drupalGet($node_uri, [], $hal_json_accept_header);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
     $this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
 
     // Clear the page cache. After that request a HAL request, followed by an
     // ordinary HTML one.
     \Drupal::cache('render')->deleteAll();
-    $this->drupalGet($node_url_with_hal_json_format);
+    $this->drupalGet($node_uri, [], $hal_json_accept_header);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
     $this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
-    $this->drupalGet($node_url_with_hal_json_format);
+    $this->drupalGet($node_uri, [], $hal_json_accept_header);
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
     $this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
 
@@ -188,7 +187,7 @@ function testConditionalRequests() {
     $this->drupalLogin($user);
     $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
     $this->assertResponse(200, 'Conditional request returned 200 OK for authenticated user.');
-    $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Absence of Page was not cached.');
+    $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Absense of Page was not cached.');
   }
 
   /**
diff --git a/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php b/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php
index 81eaa97..467a66c 100644
--- a/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php
+++ b/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php
@@ -181,7 +181,7 @@ public function testAutocompleteQuickEdit() {
 
       // Save the entity.
       $post = array('nocssjs' => 'true');
-      $response = $this->drupalPostWithFormat('quickedit/entity/node/' . $this->node->id(), 'json', $post);
+      $response = $this->drupalPost('quickedit/entity/node/' . $this->node->id(), 'application/json', $post);
       $this->assertResponse(200);
 
       // The full node display should now link to all entities, with the new
diff --git a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
index 1747b19..6cb0924 100644
--- a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
+++ b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
@@ -12,8 +12,7 @@
 use Drupal\block_content\Entity\BlockContent;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
-use Drupal\Core\Url;
+use Drupal\file\Entity\File;
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
 use Drupal\simpletest\WebTestBase;
@@ -107,7 +106,7 @@ public function testUserWithoutPermission() {
 
     // Retrieving the metadata should result in an empty 403 response.
     $post = array('fields[0]' => 'node/1/body/en/full');
-    $response = $this->drupalPostWithFormat(Url::fromRoute('quickedit.metadata'), 'json', $post);
+    $response = $this->drupalPost('quickedit/metadata', 'application/json', $post);
     $this->assertIdentical('{"message":""}', $response);
     $this->assertResponse(403);
 
@@ -115,11 +114,11 @@ public function testUserWithoutPermission() {
     // was empty as above, but we need to make sure that malicious users aren't
     // able to use any of the other endpoints either.
     $post = array('editors[0]' => 'form') + $this->getAjaxPageStatePostData();
-    $response = $this->drupalPost('quickedit/attachments', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
+    $response = $this->drupalPost('quickedit/attachments', 'application/vnd.drupal-ajax', $post);
     $this->assertIdentical('{}', $response);
     $this->assertResponse(403);
     $post = array('nocssjs' => 'true') + $this->getAjaxPageStatePostData();
-    $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
+    $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', 'application/vnd.drupal-ajax', $post);
     $this->assertIdentical('{}', $response);
     $this->assertResponse(403);
     $edit = array();
@@ -130,11 +129,11 @@ public function testUserWithoutPermission() {
     $edit['body[0][value]'] = '<p>Malicious content.</p>';
     $edit['body[0][format]'] = 'filtered_html';
     $edit['op'] = t('Save');
-    $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', '', $edit, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
+    $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', 'application/vnd.drupal-ajax', $edit);
     $this->assertIdentical('{}', $response);
     $this->assertResponse(403);
     $post = array('nocssjs' => 'true');
-    $response = $this->drupalPostWithFormat('quickedit/entity/' . 'node/1', 'json', $post);
+    $response = $this->drupalPost('quickedit/entity/' . 'node/1', 'application/json', $post);
     $this->assertIdentical('{"message":""}', $response);
     $this->assertResponse(403);
   }
@@ -167,7 +166,7 @@ public function testUserWithPermission() {
     // Retrieving the metadata should result in a 200 JSON response.
     $htmlPageDrupalSettings = $this->drupalSettings;
     $post = array('fields[0]' => 'node/1/body/en/full');
-    $response = $this->drupalPostWithFormat('quickedit/metadata', 'json', $post);
+    $response = $this->drupalPost('quickedit/metadata', 'application/json', $post);
     $this->assertResponse(200);
     $expected = array(
       'node/1/body/en/full' => array(
@@ -240,7 +239,7 @@ public function testUserWithPermission() {
 
       // Save the entity by moving the PrivateTempStore values to entity storage.
       $post = array('nocssjs' => 'true');
-      $response = $this->drupalPostWithFormat('quickedit/entity/' . 'node/1', 'json', $post);
+      $response = $this->drupalPost('quickedit/entity/' . 'node/1', 'application/json', $post);
       $this->assertResponse(200);
       $ajax_commands = Json::decode($response);
       $this->assertIdentical(1, count($ajax_commands), 'The entity submission HTTP request results in one AJAX command.');
@@ -294,7 +293,7 @@ public function testUserWithPermission() {
 
       // Save the entity.
       $post = array('nocssjs' => 'true');
-      $response = $this->drupalPostWithFormat('quickedit/entity/' . 'node/1', 'json', $post);
+      $response = $this->drupalPost('quickedit/entity/' . 'node/1', 'application/json', $post);
       $this->assertResponse(200);
       $ajax_commands = Json::decode($response);
       $this->assertIdentical(1, count($ajax_commands));
@@ -326,7 +325,7 @@ public function testTitleBaseField() {
     // Retrieving the metadata should result in a 200 JSON response.
     $htmlPageDrupalSettings = $this->drupalSettings;
     $post = array('fields[0]' => 'node/1/title/en/full');
-    $response = $this->drupalPostWithFormat('quickedit/metadata', 'json', $post);
+    $response = $this->drupalPost('quickedit/metadata', 'application/json', $post);
     $this->assertResponse(200);
     $expected = array(
       'node/1/title/en/full' => array(
@@ -384,7 +383,7 @@ public function testTitleBaseField() {
 
       // Save the entity by moving the PrivateTempStore values to entity storage.
       $post = array('nocssjs' => 'true');
-      $response = $this->drupalPostWithFormat('quickedit/entity/' . 'node/1', 'json', $post);
+      $response = $this->drupalPost('quickedit/entity/' . 'node/1', 'application/json', $post);
       $this->assertResponse(200);
       $ajax_commands = Json::decode($response);
       $this->assertIdentical(1, count($ajax_commands), 'The entity submission HTTP request results in one AJAX command.');
diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php
index 247b60c..0bce1be 100644
--- a/core/modules/rest/src/Plugin/views/display/RestExport.php
+++ b/core/modules/rest/src/Plugin/views/display/RestExport.php
@@ -8,11 +8,15 @@
 namespace Drupal\rest\Plugin\views\display;
 
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Cache\CacheableResponse;
-use Drupal\views\Plugin\views\display\ResponseDisplayPluginInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\State\StateInterface;
+use Drupal\Core\Routing\RouteProviderInterface;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\PathPluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Routing\RouteCollection;
 
 /**
@@ -29,7 +33,7 @@
  *   returns_response = TRUE
  * )
  */
-class RestExport extends PathPluginBase implements ResponseDisplayPluginInterface {
+class RestExport extends PathPluginBase {
 
   /**
    * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::$usesAJAX.
@@ -71,6 +75,49 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
   protected $mimeType;
 
   /**
+   * The renderer
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * Constructs a Drupal\rest\Plugin\ResourceBase object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
+   *   The route provider
+   * @param \Drupal\Core\State\StateInterface $state
+   *   The state key value store.
+   * @param \Drupal\Core\Render\RendererInterface $renderer
+   *   The renderer.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, RendererInterface $renderer) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider, $state);
+
+    $this->renderer = $renderer;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('router.route_provider'),
+      $container->get('state'),
+      $container->get('renderer')
+    );
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
@@ -219,62 +266,25 @@ public function collectRoutes(RouteCollection $collection) {
       $route->setMethods(['GET']);
 
       // Format as a string using pipes as a delimiter.
-      if ($formats = $style_plugin->getFormats()) {
-        // Allow a REST Export View to be returned with an HTML-only accept
-        // format. That allows browsers or other non-compliant systems to access
-        // the view, as it is unlikely to have a conflicting HTML representation
-        // anyway.
-        $route->setRequirement('_format', implode('|', $formats + ['html']));
-      }
+      $requirements['_format'] = implode('|', $style_plugin->getFormats());
+
+      // Add the new requirements to the route.
+      $route->addRequirements($requirements);
     }
   }
 
   /**
    * {@inheritdoc}
    */
-  public static function buildResponse($view_id, $display_id, array $args = []) {
-    $build = static::buildBasicRenderable($view_id, $display_id, $args);
-
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-
-    $output = $renderer->renderRoot($build);
-
-    $response = new CacheableResponse($output, 200);
-    $cache_metadata = CacheableMetadata::createFromRenderArray($build);
-    $response->addCacheableDependency($cache_metadata);
-
-    $response->headers->set('Content-type', $build['#content_type']);
-
-    return $response;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function execute() {
     parent::execute();
 
-    return $this->view->render();
-  }
+    $output = $this->view->render();
 
-  /**
-   * {@inheritdoc}
-   */
-  public function render() {
-    $build = array();
-    $build['#markup'] = $this->view->style_plugin->render();
+    $header = [];
+    $header['Content-type'] = $this->getMimeType();
 
-    $this->view->element['#content_type'] = $this->getMimeType();
-    $this->view->element['#cache_properties'][] = '#content_type';
-
-      // Wrap the output in a pre tag if this is for a live preview.
-    if (!empty($this->view->live_preview)) {
-      $build['#prefix'] = '<pre>';
-      $build['#markup'] = SafeMarkup::checkPlain($build['#markup']);
-      $build['#suffix'] = '</pre>';
-    }
-    elseif ($this->view->getRequest()->getFormat($this->view->element['#content_type']) !== 'html') {
+    if ($this->view->getRequest()->getFormat($header['Content-type']) !== 'html') {
       // This display plugin is primarily for returning non-HTML formats.
       // However, we still invoke the renderer to collect cacheability metadata.
       // Because the renderer is designed for HTML rendering, it filters
@@ -285,10 +295,40 @@ public function render() {
       // executed by an HTML agent.
       // @todo Decide how to support non-HTML in the render API in
       //   https://www.drupal.org/node/2501313.
-      $build['#markup'] = SafeMarkup::set($build['#markup']);
+      $output['#markup'] = SafeMarkup::set($output['#markup']);
     }
 
-    parent::applyDisplayCachablityMetadata($build);
+    $response = new CacheableResponse($this->renderer->renderRoot($output), 200);
+    $cache_metadata = CacheableMetadata::createFromRenderArray($output);
+
+    $response->addCacheableDependency($cache_metadata);
+
+    return $response;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render() {
+    $build = array();
+    $build['#markup'] = $this->view->style_plugin->render();
+
+    // Wrap the output in a pre tag if this is for a live preview.
+    if (!empty($this->view->live_preview)) {
+      $build['#prefix'] = '<pre>';
+      $build['#markup'] = SafeMarkup::checkPlain($build['#markup']);
+      $build['#suffix'] = '</pre>';
+    }
+
+    // Defaults for bubbleable rendering metadata.
+    $build['#cache']['tags'] = isset($build['#cache']['tags']) ? $build['#cache']['tags'] : array();
+    $build['#cache']['max-age'] = isset($build['#cache']['max-age']) ? $build['#cache']['max-age'] : Cache::PERMANENT;
+
+    /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
+    $cache = $this->getPlugin('cache');
+
+    $build['#cache']['tags'] = Cache::mergeTags($build['#cache']['tags'], $cache->getCacheTags());
+    $build['#cache']['max-age'] = Cache::mergeMaxAges($build['#cache']['max-age'], $cache->getCacheMaxAge());
 
     return $build;
   }
diff --git a/core/modules/rest/src/Plugin/views/style/Serializer.php b/core/modules/rest/src/Plugin/views/style/Serializer.php
index 67a8364..ba3ca6f 100644
--- a/core/modules/rest/src/Plugin/views/style/Serializer.php
+++ b/core/modules/rest/src/Plugin/views/style/Serializer.php
@@ -8,7 +8,6 @@
 namespace Drupal\rest\Plugin\views\style;
 
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\Plugin\CacheablePluginInterface;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Plugin\views\style\StylePluginBase;
@@ -27,7 +26,7 @@
  *   display_types = {"data"}
  * )
  */
-class Serializer extends StylePluginBase implements CacheablePluginInterface {
+class Serializer extends StylePluginBase {
 
   /**
    * Overrides \Drupal\views\Plugin\views\style\StylePluginBase::$usesRowPlugin.
@@ -147,21 +146,11 @@ public function render() {
    *   An array of formats.
    */
   public function getFormats() {
-    return $this->options['formats'];
-  }
+    if (!empty($this->options['formats'])) {
+      return $this->options['formats'];
+    }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function isCacheable() {
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return ['request_format'];
+    return $this->formats;
   }
 
 }
diff --git a/core/modules/rest/src/Tests/AuthTest.php b/core/modules/rest/src/Tests/AuthTest.php
index 4552fc6..c222b26 100644
--- a/core/modules/rest/src/Tests/AuthTest.php
+++ b/core/modules/rest/src/Tests/AuthTest.php
@@ -38,7 +38,7 @@ public function testRead() {
     $entity->save();
 
     // Try to read the resource as an anonymous user, which should not work.
-    $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
+    $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse('401', 'HTTP response code is 401 when the request is not authenticated and the user is anonymous.');
     $this->assertRaw(json_encode(['message' => 'A fatal error occurred: No authentication credentials provided.']));
 
@@ -55,7 +55,7 @@ public function testRead() {
 
     // Try to read the resource with session cookie authentication, which is
     // not enabled and should not work.
-    $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
+    $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse('403', 'HTTP response code is 403 when the request was authenticated by the wrong authentication provider.');
 
     // Ensure that cURL settings/headers aren't carried over to next request.
@@ -63,7 +63,7 @@ public function testRead() {
 
     // Now read it with the Basic authentication which is enabled and should
     // work.
-    $this->basicAuthGet($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), $account->getUsername(), $account->pass_raw);
+    $this->basicAuthGet($entity->urlInfo(), $account->getUsername(), $account->pass_raw, $this->defaultMimeType);
     $this->assertResponse('200', 'HTTP response code is 200 for successfully authenticated requests.');
     $this->curlClose();
   }
diff --git a/core/modules/rest/src/Tests/NodeTest.php b/core/modules/rest/src/Tests/NodeTest.php
index 2c8de1e..7169102 100644
--- a/core/modules/rest/src/Tests/NodeTest.php
+++ b/core/modules/rest/src/Tests/NodeTest.php
@@ -51,14 +51,14 @@ public function testNodes() {
 
     $node = $this->entityCreate('node');
     $node->save();
-    $this->httpRequest($node->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
+    $this->httpRequest($node->urlInfo(), 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse(200);
     $this->assertHeader('Content-type', $this->defaultMimeType);
 
     // Also check that JSON works and the routing system selects the correct
     // REST route.
     $this->enableService('entity:node', 'GET', 'json');
-    $this->httpRequest($node->urlInfo()->setRouteParameter('_format', 'json'), 'GET');
+    $this->httpRequest($node->urlInfo(), 'GET', NULL, 'application/json');
     $this->assertResponse(200);
     $this->assertHeader('Content-type', 'application/json');
 
diff --git a/core/modules/rest/src/Tests/PageCacheTest.php b/core/modules/rest/src/Tests/PageCacheTest.php
index 573238f..9cf2859 100644
--- a/core/modules/rest/src/Tests/PageCacheTest.php
+++ b/core/modules/rest/src/Tests/PageCacheTest.php
@@ -35,14 +35,14 @@ public function testConfigChangePageCache() {
     $entity = $this->entityCreate('entity_test');
     $entity->save();
     // Read it over the REST API.
-    $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET', NULL, $this->defaultMimeType);
+    $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse(200, 'HTTP response code is correct.');
     $this->assertHeader('x-drupal-cache', 'MISS');
     $this->assertCacheTag('config:rest.settings');
     $this->assertCacheTag('entity_test:1');
 
     // Read it again, should be page-cached now.
-    $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET', NULL, $this->defaultMimeType);
+    $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse(200, 'HTTP response code is correct.');
     $this->assertHeader('x-drupal-cache', 'HIT');
     $this->assertCacheTag('config:rest.settings');
@@ -51,7 +51,7 @@ public function testConfigChangePageCache() {
     // Trigger a config save which should clear the page cache, so we should get
     // a cache miss now for the same request.
     $this->config('rest.settings')->save();
-    $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET', NULL, $this->defaultMimeType);
+    $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
     $this->assertResponse(200, 'HTTP response code is correct.');
     $this->assertHeader('x-drupal-cache', 'MISS');
     $this->assertCacheTag('config:rest.settings');
diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php
index f31ac53..ff382d5 100644
--- a/core/modules/rest/src/Tests/RESTTestBase.php
+++ b/core/modules/rest/src/Tests/RESTTestBase.php
@@ -261,6 +261,29 @@ protected function rebuildCache() {
   }
 
   /**
+   * Check if a HTTP response header exists and has the expected value.
+   *
+   * @param string $header
+   *   The header key, example: Content-Type
+   * @param string $value
+   *   The header value.
+   * @param string $message
+   *   (optional) A message to display with the assertion.
+   * @param string $group
+   *   (optional) The group this message is in, which is displayed in a column
+   *   in test output. Use 'Debug' to indicate this is debugging output. Do not
+   *   translate this string. Defaults to 'Other'; most tests do not override
+   *   this default.
+   *
+   * @return bool
+   *   TRUE if the assertion succeeded, FALSE otherwise.
+   */
+  protected function assertHeader($header, $value, $message = '', $group = 'Browser') {
+    $header_value = $this->drupalGetHeader($header);
+    return $this->assertTrue($header_value == $value, $message ? $message : 'HTTP response header ' . $header . ' with value ' . $value . ' found.', $group);
+  }
+
+  /**
    * {@inheritdoc}
    *
    * This method is overridden to deal with a cURL quirk: the usage of
diff --git a/core/modules/rest/src/Tests/ReadTest.php b/core/modules/rest/src/Tests/ReadTest.php
index 983b547..3be342e 100644
--- a/core/modules/rest/src/Tests/ReadTest.php
+++ b/core/modules/rest/src/Tests/ReadTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\rest\Tests;
 
 use Drupal\Component\Serialization\Json;
-use Drupal\Core\Url;
 use Drupal\rest\Tests\RESTTestBase;
 
 /**
@@ -45,7 +44,7 @@ public function testRead() {
       $entity = $this->entityCreate($entity_type);
       $entity->save();
       // Read it over the REST API.
-      $response = $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
+      $response = $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
       $this->assertResponse('200', 'HTTP response code is correct.');
       $this->assertHeader('content-type', $this->defaultMimeType);
       $data = Json::decode($response);
@@ -54,12 +53,12 @@ public function testRead() {
       $this->assertEqual($data['uuid'][0]['value'], $entity->uuid(), 'Entity UUID is correct');
 
       // Try to read the entity with an unsupported mime format.
-      $response = $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', 'wrongformat'), 'GET');
-      $this->assertResponse(406);
-      $this->assertHeader('Content-type', 'application/json');
+      $response = $this->httpRequest($entity->urlInfo(), 'GET', NULL, 'application/wrongformat');
+      $this->assertResponse(200);
+      $this->assertHeader('Content-type', 'text/html; charset=UTF-8');
 
       // Try to read an entity that does not exist.
-      $response = $this->httpRequest(Url::fromUri('base://' . $entity_type . '/9999', ['query' => ['_format' => $this->defaultFormat]]), 'GET');
+      $response = $this->httpRequest($entity_type . '/9999', 'GET', NULL, $this->defaultMimeType);
       $this->assertResponse(404);
       $path = $entity_type == 'node' ? '/node/{node}' : '/entity_test/{entity_test}';
       $expected_message = Json::encode(['message' => 'The "' . $entity_type . '" parameter was not converted for the path "' . $path . '" (route name: "rest.entity.' . $entity_type . '.GET.hal_json")']);
@@ -71,7 +70,7 @@ public function testRead() {
       if ($entity_type == 'entity_test') {
         $entity->field_test_text->value = 'no access value';
         $entity->save();
-        $response = $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
+        $response = $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
         $this->assertResponse(200);
         $this->assertHeader('content-type', $this->defaultMimeType);
         $data = Json::decode($response);
@@ -80,19 +79,18 @@ public function testRead() {
 
       // Try to read an entity without proper permissions.
       $this->drupalLogout();
-      $response = $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
+      $response = $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
       $this->assertResponse(403);
       $this->assertIdentical('{"message":""}', $response);
     }
     // Try to read a resource which is not REST API enabled.
     $account = $this->drupalCreateUser();
     $this->drupalLogin($account);
-    $response = $this->httpRequest($account->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
-    // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
-    // non-REST route a match, but a lower quality one: no format restrictions
-    // means there's always a match and hence when there is no matching REST
-    // route, the non-REST route is used, but can't render into
-    // application/hal+json, so it returns a 406.
+    $response = $this->httpRequest($account->urlInfo(), 'GET', NULL, $this->defaultMimeType);
+    // AcceptHeaderMatcher considers the canonical, non-REST route a match, but
+    // a lower quality one: no format restrictions means there's always a match,
+    // and hence when there is no matching REST route, the non-REST route is
+    // used, but it can't render into application/hal+json, so it returns a 406.
     $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
     $this->assertEqual($response, Json::encode([
       'message' => 'Not acceptable',
@@ -117,7 +115,7 @@ public function testResourceStructure() {
     $entity->save();
 
     // Read it over the REST API.
-    $response = $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', 'json'), 'GET');
+    $response = $this->httpRequest($entity->urlInfo(), 'GET', NULL, 'application/json');
     $this->assertResponse('200', 'HTTP response code is correct.');
   }
 
diff --git a/core/modules/rest/src/Tests/ResourceTest.php b/core/modules/rest/src/Tests/ResourceTest.php
index af22085..5144ae3 100644
--- a/core/modules/rest/src/Tests/ResourceTest.php
+++ b/core/modules/rest/src/Tests/ResourceTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\rest\Tests;
 
+use Drupal\rest\Tests\RESTTestBase;
+
 /**
  * Tests the structure of a REST resource.
  *
@@ -22,13 +24,6 @@ class ResourceTest extends RESTTestBase {
   public static $modules = array('hal', 'rest', 'entity_test');
 
   /**
-   * The entity.
-   *
-   * @var \Drupal\Core\Entity\EntityInterface
-   */
-  protected $entity;
-
-  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -60,12 +55,11 @@ public function testFormats() {
     $this->rebuildCache();
 
     // Verify that accessing the resource returns 406.
-    $response = $this->httpRequest($this->entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
-    // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
-    // non-REST route a match, but a lower quality one: no format restrictions
-    // means there's always a match and hence when there is no matching REST
-    // route, the non-REST route is used, but can't render into
-    // application/hal+json, so it returns a 406.
+    $response = $this->httpRequest($this->entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
+    // AcceptHeaderMatcher considers the canonical, non-REST route a match, but
+    // a lower quality one: no format restrictions means there's always a match,
+    // and hence when there is no matching REST route, the non-REST route is
+    // used, but it can't render into application/hal+json, so it returns a 406.
     $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
     $this->curlClose();
   }
@@ -90,12 +84,11 @@ public function testAuthentication() {
     $this->rebuildCache();
 
     // Verify that accessing the resource returns 401.
-    $response = $this->httpRequest($this->entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
-    // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
-    // non-REST route a match, but a lower quality one: no format restrictions
-    // means there's always a match and hence when there is no matching REST
-    // route, the non-REST route is used, but can't render into
-    // application/hal+json, so it returns a 406.
+    $response = $this->httpRequest($this->entity->urlInfo(), 'GET', NULL, $this->defaultMimeType);
+    // AcceptHeaderMatcher considers the canonical, non-REST route a match, but
+    // a lower quality one: no format restrictions means there's always a match,
+    // and hence when there is no matching REST route, the non-REST route is
+    // used, but it can't render into application/hal+json, so it returns a 406.
     $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
     $this->curlClose();
   }
diff --git a/core/modules/rest/src/Tests/Views/StyleSerializerTest.php b/core/modules/rest/src/Tests/Views/StyleSerializerTest.php
index 1eca0d2..0a14c3c 100644
--- a/core/modules/rest/src/Tests/Views/StyleSerializerTest.php
+++ b/core/modules/rest/src/Tests/Views/StyleSerializerTest.php
@@ -9,10 +9,7 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Cache\Cache;
-use Drupal\entity_test\Entity\EntityTest;
 use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
-use Drupal\views\Entity\View;
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Views;
 use Drupal\views\Tests\Plugin\PluginTestBase;
 use Drupal\views\Tests\ViewTestData;
@@ -79,10 +76,9 @@ public function testSerializerResponses() {
     $view->initDisplay();
     $this->executeView($view);
 
-    $actual_json = $this->drupalGetWithFormat('test/serialize/field', 'json');
+    $actual_json = $this->drupalGet('test/serialize/field', array(), array('Accept: application/json'));
     $this->assertResponse(200);
     $this->assertCacheTags($view->getCacheTags());
-    $this->assertCacheContexts(['languages:language_interface', 'theme', 'request_format']);
     // @todo Due to https://www.drupal.org/node/2352009 we can't yet test the
     // propagation of cache max-age.
 
@@ -129,7 +125,7 @@ public function testSerializerResponses() {
 
     $expected = $serializer->serialize($entities, 'json');
 
-    $actual_json = $this->drupalGetWithFormat('test/serialize/entity', 'json');
+    $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/json'));
     $this->assertResponse(200);
     $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.');
     $expected_cache_tags = $view->getCacheTags();
@@ -139,10 +135,9 @@ public function testSerializerResponses() {
       $expected_cache_tags = Cache::mergeTags($expected_cache_tags, $entity->getCacheTags());
     }
     $this->assertCacheTags($expected_cache_tags);
-    $this->assertCacheContexts(['languages:language_interface', 'theme', 'entity_test_view_grants', 'request_format']);
 
     $expected = $serializer->serialize($entities, 'hal_json');
-    $actual_json = $this->drupalGetWithFormat('test/serialize/entity', 'hal_json');
+    $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/hal+json'));
     $this->assertIdentical($actual_json, $expected, 'The expected HAL output was found.');
     $this->assertCacheTags($expected_cache_tags);
 
@@ -161,7 +156,6 @@ public function testSerializerResponses() {
     $expected = $serializer->serialize($entities, 'xml');
     $actual_xml = $this->drupalGet('test/serialize/entity');
     $this->assertIdentical($actual_xml, $expected, 'The expected XML output was found.');
-    $this->assertCacheContexts(['languages:language_interface', 'theme', 'entity_test_view_grants', 'request_format']);
 
     // Allow multiple formats.
     $view->setDisplay('rest_export_1');
@@ -177,119 +171,14 @@ public function testSerializerResponses() {
     ));
     $view->save();
     $expected = $serializer->serialize($entities, 'json');
-    $actual_json = $this->drupalGetWithFormat('test/serialize/entity', 'json');
+    $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/json'));
     $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.');
     $expected = $serializer->serialize($entities, 'xml');
-    $actual_xml = $this->drupalGetWithFormat('test/serialize/entity', 'xml');
+    $actual_xml = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/xml'));
     $this->assertIdentical($actual_xml, $expected, 'The expected XML output was found.');
   }
 
   /**
-   * Sets up a request on the request stack with a specified format.
-   *
-   * @param string $format
-   *   The new request format.
-   */
-  protected function addRequestWithFormat($format) {
-    $request = \Drupal::request();
-    $request = clone $request;
-    $request->setRequestFormat($format);
-
-    \Drupal::requestStack()->push($request);
-  }
-
-  /**
-   * Tests REST export with views render caching enabled.
-   */
-  public function testRestRenderCaching() {
-    $this->drupalLogin($this->adminUser);
-    /** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
-    $render_cache = \Drupal::service('render_cache');
-
-    // Enable render caching for the views.
-    /** @var \Drupal\views\ViewEntityInterface $storage */
-    $storage = View::load('test_serializer_display_entity');
-    $options = &$storage->getDisplay('default');
-    $options['display_options']['cache'] = [
-      'type' => 'tag',
-    ];
-    $storage->save();
-
-    $original = DisplayPluginBase::buildBasicRenderable('test_serializer_display_entity', 'rest_export_1');
-
-    // Ensure that there is no corresponding render cache item yet.
-    $original['#cache'] += ['contexts' => []];
-    $original['#cache']['contexts'] = Cache::mergeContexts($original['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
-
-    $cache_tags = [
-      'config:views.view.test_serializer_display_entity',
-      'entity_test:1',
-      'entity_test:10',
-      'entity_test:2',
-      'entity_test:3',
-      'entity_test:4',
-      'entity_test:5',
-      'entity_test:6',
-      'entity_test:7',
-      'entity_test:8',
-      'entity_test:9',
-      'entity_test_list'
-    ];
-    $cache_contexts = [
-      'entity_test_view_grants',
-      'languages:language_interface',
-      'theme',
-      'request_format',
-    ];
-
-    $this->assertFalse($render_cache->get($original));
-
-    // Request the page, once in XML and once in JSON to ensure that the caching
-    // varies by it.
-    $result1 = $this->drupalGetJSON('test/serialize/entity');
-    $this->addRequestWithFormat('json');
-    $this->assertHeader('content-type', 'application/json');
-    $this->assertCacheContexts($cache_contexts);
-    $this->assertCacheTags($cache_tags);
-    $this->assertTrue($render_cache->get($original));
-
-    $result_xml = $this->drupalGetWithFormat('test/serialize/entity', 'xml');
-    $this->addRequestWithFormat('xml');
-    $this->assertHeader('content-type', 'text/xml; charset=UTF-8');
-    $this->assertCacheContexts($cache_contexts);
-    $this->assertCacheTags($cache_tags);
-    $this->assertTrue($render_cache->get($original));
-
-    // Ensure that the XML output is different from the JSON one.
-    $this->assertNotEqual($result1, $result_xml);
-
-    // Ensure that the cached page works.
-    $result2 = $this->drupalGetJSON('test/serialize/entity');
-    $this->addRequestWithFormat('json');
-    $this->assertHeader('content-type', 'application/json');
-    $this->assertEqual($result2, $result1);
-    $this->assertCacheContexts($cache_contexts);
-    $this->assertCacheTags($cache_tags);
-    $this->assertTrue($render_cache->get($original));
-
-    // Create a new entity and ensure that the cache tags are taken over.
-    EntityTest::create(['name' => 'test_11', 'user_id' => $this->adminUser->id()])->save();
-    $result3 = $this->drupalGetJSON('test/serialize/entity');
-    $this->addRequestWithFormat('json');
-    $this->assertHeader('content-type', 'application/json');
-    $this->assertNotEqual($result3, $result2);
-
-    // Add the new entity cache tag and remove the first one, because we just
-    // show 10 items in total.
-    $cache_tags[] = 'entity_test:11';
-    unset($cache_tags[array_search('entity_test:1', $cache_tags)]);
-
-    $this->assertCacheContexts($cache_contexts);
-    $this->assertCacheTags($cache_tags);
-    $this->assertTrue($render_cache->get($original));
-  }
-
-  /**
    * Tests the response format configuration.
    */
   public function testResponseFormatConfiguration() {
@@ -302,12 +191,10 @@ public function testResponseFormatConfiguration() {
     $this->drupalPostForm(NULL, array(), t('Save'));
 
     // Should return a 406.
-    $this->drupalGetWithFormat('test/serialize/field', 'json');
-    $this->assertHeader('content-type', 'application/json');
+    $this->drupalGet('test/serialize/field', array(), array('Accept: application/json'));
     $this->assertResponse(406, 'A 406 response was returned when JSON was requested.');
      // Should return a 200.
-    $this->drupalGetWithFormat('test/serialize/field', 'xml');
-    $this->assertHeader('content-type', 'text/xml; charset=UTF-8');
+    $this->drupalGet('test/serialize/field', array(), array('Accept: application/xml'));
     $this->assertResponse(200, 'A 200 response was returned when XML was requested.');
 
     // Add 'json' as an accepted format, so we have multiple.
@@ -316,51 +203,22 @@ public function testResponseFormatConfiguration() {
 
     // Should return a 200.
     // @todo This should be fixed when we have better content negotiation.
-    $this->drupalGet('test/serialize/field');
-    $this->assertHeader('content-type', 'application/json');
+    $this->drupalGet('test/serialize/field', array(), array('Accept: */*'));
     $this->assertResponse(200, 'A 200 response was returned when any format was requested.');
 
     // Should return a 200. Emulates a sample Firefox header.
     $this->drupalGet('test/serialize/field', array(), array('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
-    $this->assertHeader('content-type', 'application/json');
     $this->assertResponse(200, 'A 200 response was returned when a browser accept header was requested.');
 
     // Should return a 200.
-    $this->drupalGetWithFormat('test/serialize/field', 'json');
-    $this->assertHeader('content-type', 'application/json');
+    $this->drupalGet('test/serialize/field', array(), array('Accept: application/json'));
     $this->assertResponse(200, 'A 200 response was returned when JSON was requested.');
-    $headers = $this->drupalGetHeaders();
-    $this->assertEqual($headers['content-type'], 'application/json', 'The header Content-type is correct.');
     // Should return a 200.
-    $this->drupalGetWithFormat('test/serialize/field', 'xml');
-    $this->assertHeader('content-type', 'text/xml; charset=UTF-8');
+    $this->drupalGet('test/serialize/field', array(), array('Accept: application/xml'));
     $this->assertResponse(200, 'A 200 response was returned when XML was requested');
-    $headers = $this->drupalGetHeaders();
-    $this->assertTrue(strpos($headers['content-type'], 'text/xml') !== FALSE, 'The header Content-type is correct.');
     // Should return a 406.
-    $this->drupalGetWithFormat('test/serialize/field', 'html');
-    // We want to show the first format by default, see
-    // \Drupal\rest\Plugin\views\style\Serializer::render.
-    $this->assertHeader('content-type', 'application/json');
-    $this->assertResponse(200, 'A 200 response was returned when HTML was requested.');
-
-    // Now configure now format, so all of them should be allowed.
-    $this->drupalPostForm($style_options, array('style_options[formats][json]' => '0', 'style_options[formats][xml]' => '0'), t('Apply'));
-
-    // Should return a 200.
-    $this->drupalGetWithFormat('test/serialize/field', 'json');
-    $this->assertHeader('content-type', 'application/json');
-    $this->assertResponse(200, 'A 200 response was returned when JSON was requested.');
-    // Should return a 200.
-    $this->drupalGetWithFormat('test/serialize/field', 'xml');
-    $this->assertHeader('content-type', 'text/xml; charset=UTF-8');
-    $this->assertResponse(200, 'A 200 response was returned when XML was requested');
-    // Should return a 200.
-    $this->drupalGetWithFormat('test/serialize/field', 'html');
-    // We want to show the first format by default, see
-    // \Drupal\rest\Plugin\views\style\Serializer::render.
-    $this->assertHeader('content-type', 'application/json');
-    $this->assertResponse(200, 'A 200 response was returned when HTML was requested.');
+    $this->drupalGet('test/serialize/field', array(), array('Accept: application/html'));
+    $this->assertResponse(406, 'A 406 response was returned when HTML was requested.');
   }
 
   /**
@@ -510,7 +368,7 @@ public function testLivePreview() {
   }
 
   /**
-   * Tests the views interface for REST export displays.
+   * Tests the views interface for rest export displays.
    */
   public function testSerializerViewsUI() {
     $this->drupalLogin($this->adminUser);
diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml
index 2a5818e..eef38d3 100644
--- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml
+++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
index 7f7769d..49673d5 100644
--- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
+++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_node_display_field.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_node_display_field.yml
index ab50920..7032875 100644
--- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_node_display_field.yml
+++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_node_display_field.yml
@@ -29,7 +29,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 94e12e9..82ee88d 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -469,7 +469,7 @@ function simpletest_log_read($test_id, $database_prefix, $test_class) {
  *     $groups['Block'] => array(
  *       'BlockTestCase' => array(
  *         'name' => 'Block functionality',
- *         'description' => 'Add, edit and delete custom block.',
+ *         'description' => 'Add, edit and delete custom block...',
  *         'group' => 'Block',
  *       ),
  *     );
diff --git a/core/modules/simpletest/src/BrowserTestBase.php b/core/modules/simpletest/src/BrowserTestBase.php
index cd77a98..06ae369 100644
--- a/core/modules/simpletest/src/BrowserTestBase.php
+++ b/core/modules/simpletest/src/BrowserTestBase.php
@@ -1258,9 +1258,6 @@ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_serv
     $server = array_merge($server, $override_server_vars);
 
     $request = Request::create($request_path, 'GET', array(), array(), array(), $server);
-    // Ensure the the request time is REQUEST_TIME to ensure that API calls
-    // in the test use the right timestamp.
-    $request->server->set('REQUEST_TIME', REQUEST_TIME);
     $this->container->get('request_stack')->push($request);
 
     // The request context is normally set by the router_listener from within
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index 5471ed6..9078d39 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -1136,8 +1136,7 @@ private function prepareEnvironment() {
     }
 
     // Backup current in-memory configuration.
-    $site_path = \Drupal::service('site.path');
-    $this->originalSite = $site_path;
+    $this->originalSite = conf_path();
     $this->originalSettings = Settings::getAll();
     $this->originalConfig = $GLOBALS['config'];
     // @todo Remove all remnants of $GLOBALS['conf'].
@@ -1152,7 +1151,7 @@ private function prepareEnvironment() {
     // Save further contextual information.
     // Use the original files directory to avoid nesting it within an existing
     // simpletest directory if a test is executed within a test.
-    $this->originalFileDirectory = Settings::get('file_public_path', $site_path . '/files');
+    $this->originalFileDirectory = Settings::get('file_public_path', conf_path() . '/files');
     $this->originalProfile = drupal_get_profile();
     $this->originalUser = isset($user) ? clone $user : NULL;
 
@@ -1222,6 +1221,7 @@ private function prepareEnvironment() {
     // After preparing the environment and changing the database prefix, we are
     // in a valid test environment.
     drupal_valid_test_ua($this->databasePrefix);
+    conf_path(FALSE, TRUE);
 
     // Reset settings.
     new Settings(array(
@@ -1335,6 +1335,7 @@ private function restoreEnvironment() {
     else {
       drupal_valid_test_ua(FALSE);
     }
+    conf_path(TRUE, TRUE);
 
     // Restore original shutdown callbacks.
     $callbacks = &drupal_register_shutdown_function();
diff --git a/core/modules/simpletest/src/Tests/SimpleTestTest.php b/core/modules/simpletest/src/Tests/SimpleTestTest.php
index 2514d9d..c650eef 100644
--- a/core/modules/simpletest/src/Tests/SimpleTestTest.php
+++ b/core/modules/simpletest/src/Tests/SimpleTestTest.php
@@ -161,7 +161,6 @@ function stubTest() {
     // @see drupal_generate_test_ua();
     $key_file = DRUPAL_ROOT . '/sites/simpletest/' . substr($this->databasePrefix, 10) . '/.htkey';
     $private_key = Crypt::randomBytesBase64(55);
-    $site_path = $this->container->get('site.path');
     file_put_contents($key_file, $private_key);
 
     // This causes the first of the fifteen passes asserted in
@@ -193,7 +192,7 @@ function stubTest() {
 
     // These cause the eleventh to fourteenth of the fifteen passes asserted in
     // confirmStubResults().
-    $this->assertTrue(file_exists($site_path . '/settings.testing.php'));
+    $this->assertTrue(file_exists(conf_path() . '/settings.testing.php'));
     // Check the settings.testing.php file got included.
     $this->assertTrue(function_exists('simpletest_test_stub_settings_function'));
     // Check that the test-specific service file got loaded.
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 3616888..2cf859a 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -1395,27 +1395,8 @@ protected function drupalGet($path, array $options = array(), array $headers = a
    * Requests a Drupal path in JSON format, and JSON decodes the response.
    */
   protected function drupalGetJSON($path, array $options = array(), array $headers = array()) {
-    return Json::decode($this->drupalGetWithFormat($path, 'json', $options, $headers));
-  }
-
-  /**
-   * Retrieves a Drupal path or an absolute path for a given format.
-   *
-   * @param string $path
-   *   Path to request AJAX from.
-   * @param string $format
-   *   The wanted request format.
-   * @param array $options
-   *   Array of URL options.
-   * @param array $headers
-   *   Array of headers.
-   *
-   * @return mixed
-   *   The result of the request.
-   */
-  protected function drupalGetWithFormat($path, $format, array $options = [], array $headers = []) {
-    $options += ['query' => ['_format' => $format]];
-    return $this->drupalGet($path, $options, $headers);
+    $headers[] = 'Accept: application/json';
+    return Json::decode($this->drupalGet($path, $options, $headers));
   }
 
   /**
@@ -1910,34 +1891,6 @@ protected function drupalPost($path, $accept, array $post, $options = array()) {
   }
 
   /**
-   * Performs a POST HTTP request with a specific format.
-   *
-   * @param string $path
-   *   Drupal path where the request should be POSTed to. Will be transformed
-   *   into an absolute path automatically.
-   * @param string $format
-   *   The request format.
-   * @param array $post
-   *   The POST data. When making a 'application/vnd.drupal-ajax' request, the
-   *   Ajax page state data should be included. Use getAjaxPageStatePostData()
-   *   for that.
-   * @param array $options
-   *   (optional) Options to be forwarded to the url generator. The 'absolute'
-   *   option will automatically be enabled.
-   *
-   * @return string
-   *   The content returned from the call to curl_exec().
-   *
-   * @see WebTestBase::drupalPost
-   * @see WebTestBase::getAjaxPageStatePostData()
-   * @see WebTestBase::curlExec()
-   */
-  protected function drupalPostWithFormat($path, $format, array $post, $options = []) {
-    $options['query']['_format'] = $format;
-    return $this->drupalPost($path, '', $post, $options);
-  }
-
-  /**
    * Get the Ajax page state from drupalSettings and prepare it for POSTing.
    *
    * @return array
@@ -2368,29 +2321,6 @@ protected function drupalGetHeader($name, $all_requests = FALSE) {
   }
 
   /**
-   * Check if a HTTP response header exists and has the expected value.
-   *
-   * @param string $header
-   *   The header key, example: Content-Type
-   * @param string $value
-   *   The header value.
-   * @param string $message
-   *   (optional) A message to display with the assertion.
-   * @param string $group
-   *   (optional) The group this message is in, which is displayed in a column
-   *   in test output. Use 'Debug' to indicate this is debugging output. Do not
-   *   translate this string. Defaults to 'Other'; most tests do not override
-   *   this default.
-   *
-   * @return bool
-   *   TRUE if the assertion succeeded, FALSE otherwise.
-   */
-  protected function assertHeader($header, $value, $message = '', $group = 'Browser') {
-    $header_value = $this->drupalGetHeader($header);
-    return $this->assertTrue($header_value == $value, $message ? $message : 'HTTP response header ' . $header . ' with value ' . $value . ' found, actual value: ' . $header_value, $group);
-  }
-
-  /**
    * Gets an array containing all emails sent during this test case.
    *
    * @param $filter
@@ -2662,9 +2592,6 @@ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_serv
     $server = array_merge($server, $override_server_vars);
 
     $request = Request::create($request_path, 'GET', array(), array(), array(), $server);
-    // Ensure the the request time is REQUEST_TIME to ensure that API calls
-    // in the test use the right timestamp.
-    $request->server->set('REQUEST_TIME', REQUEST_TIME);
     $this->container->get('request_stack')->push($request);
 
     // The request context is normally set by the router_listener from within
@@ -2689,9 +2616,6 @@ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_serv
    */
   protected function buildUrl($path, array $options = array()) {
     if ($path instanceof Url) {
-      $url_options = $path->getOptions();
-      $options = $url_options + $options;
-      $path->setOptions($options);
       return $path->setAbsolute()->toString();
     }
     // The URL generator service is not necessarily available yet; e.g., in
diff --git a/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml b/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
index a320c4f..b8d3c4a 100644
--- a/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
+++ b/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php
index 3c68a57..e60550f 100644
--- a/core/modules/system/entity.api.php
+++ b/core/modules/system/entity.api.php
@@ -1516,7 +1516,7 @@ function hook_entity_build_defaults_alter(array &$build, \Drupal\Core\Entity\Ent
  *   An associative array containing:
  *   - entity_type: The entity type, e.g., 'node' or 'user'.
  *   - bundle: The bundle, e.g., 'page' or 'article'.
- *   - view_mode: The view mode, e.g., 'full', 'teaser', etc.
+ *   - view_mode: The view mode, e.g. 'full', 'teaser'...
  *
  * @ingroup entity_crud
  */
@@ -1625,7 +1625,7 @@ function hook_ENTITY_TYPE_prepare_form(\Drupal\Core\Entity\EntityInterface $enti
  *   An associative array containing:
  *   - entity_type: The entity type, e.g., 'node' or 'user'.
  *   - bundle: The bundle, e.g., 'page' or 'article'.
- *   - form_mode: The form mode; e.g., 'default', 'profile', 'register', etc.
+ *   - form_mode: The form mode, e.g. 'default', 'profile', 'register'...
  *
  * @ingroup entity_crud
  */
diff --git a/core/modules/system/module.api.php b/core/modules/system/module.api.php
index 63f81b2..24fb741 100644
--- a/core/modules/system/module.api.php
+++ b/core/modules/system/module.api.php
@@ -761,7 +761,7 @@ function hook_requirements($phase) {
     $cron_last = \Drupal::state()->get('system.cron_last');
 
     if (is_numeric($cron_last)) {
-      $requirements['cron']['value'] = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
+      $requirements['cron']['value'] = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $cron_last)));
     }
     else {
       $requirements['cron'] = array(
diff --git a/core/modules/system/src/Form/CronForm.php b/core/modules/system/src/Form/CronForm.php
index c57ceae..9df9414 100644
--- a/core/modules/system/src/Form/CronForm.php
+++ b/core/modules/system/src/Form/CronForm.php
@@ -101,7 +101,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#value' => t('Run cron'),
       '#submit' => array('::submitCron'),
     );
-    $status = '<p>' . $this->t('Last run: %time ago.', array('%time' => $this->dateFormatter->formatTimeDiffSince($this->state->get('system.cron_last')))) . '</p>';
+
+    $status = '<p>' . t('Last run: %cron-last ago.', array('%cron-last' => $this->dateFormatter->formatInterval(REQUEST_TIME - $this->state->get('system.cron_last')))) . '</p>';
     $form['status'] = array(
       '#markup' => $status,
     );
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 173fcc7..35d5693 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -255,17 +255,17 @@ protected function buildRow(array $modules, Extension $module, $distribution) {
     $row['description']['#markup'] = $this->t($module->info['description']);
     $row['version']['#markup'] = $module->info['version'];
 
-    // Generate link for module's help page. Assume that if a hook_help()
-    // implementation exists then the module provides an overview page, rather
-    // than checking to see if the page exists, which is costly.
+    // Generate link for module's help page, if there is one.
     $row['links']['help'] = array();
     if ($this->moduleHandler->moduleExists('help') && $module->status && in_array($module->getName(), $this->moduleHandler->getImplementations('help'))) {
-      $row['links']['help'] = array(
-        '#type' => 'link',
-        '#title' => $this->t('Help'),
-        '#url' => Url::fromRoute('help.page', ['name' => $module->getName()]),
-        '#options' => array('attributes' => array('class' =>  array('module-link', 'module-link-help'), 'title' => $this->t('Help'))),
-      );
+      if ($this->moduleHandler->invoke($module->getName(), 'help', array('help.page.' . $module->getName(), $this->routeMatch))) {
+        $row['links']['help'] = array(
+          '#type' => 'link',
+          '#title' => $this->t('Help'),
+          '#url' => Url::fromRoute('help.page', ['name' => $module->getName()]),
+          '#options' => array('attributes' => array('class' =>  array('module-link', 'module-link-help'), 'title' => $this->t('Help'))),
+        );
+      }
     }
 
     // Generate link for module's permission, if the user has access to it.
diff --git a/core/modules/system/src/Plugin/views/field/BulkForm.php b/core/modules/system/src/Plugin/views/field/BulkForm.php
index 609d4c0..1579436 100644
--- a/core/modules/system/src/Plugin/views/field/BulkForm.php
+++ b/core/modules/system/src/Plugin/views/field/BulkForm.php
@@ -11,11 +11,8 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\RevisionableInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\Routing\RedirectDestinationTrait;
 use Drupal\Core\TypedData\TranslatableInterface;
-use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
-use Drupal\views\Plugin\CacheablePluginInterface;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Plugin\views\field\FieldPluginBase;
 use Drupal\views\Plugin\views\field\UncacheableFieldHandlerTrait;
@@ -29,11 +26,10 @@
  *
  * @ViewsField("bulk_form")
  */
-class BulkForm extends FieldPluginBase implements CacheablePluginInterface {
+class BulkForm extends FieldPluginBase {
 
   use RedirectDestinationTrait;
   use UncacheableFieldHandlerTrait;
-  use EntityTranslationRenderTrait;
 
   /**
    * The entity manager.
@@ -57,13 +53,6 @@ class BulkForm extends FieldPluginBase implements CacheablePluginInterface {
   protected $actions = array();
 
   /**
-   * The language manager.
-   *
-   * @var \Drupal\Core\Language\LanguageManagerInterface
-   */
-  protected $languageManager;
-
-  /**
    * Constructs a new BulkForm object.
    *
    * @param array $configuration
@@ -74,28 +63,19 @@ class BulkForm extends FieldPluginBase implements CacheablePluginInterface {
    *   The plugin implementation definition.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager.
-   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
-   *   The language manager.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     $this->entityManager = $entity_manager;
     $this->actionStorage = $entity_manager->getStorage('action');
-    $this->languageManager = $language_manager;
   }
 
   /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('entity.manager'),
-      $container->get('language_manager')
-    );
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('entity.manager'));
   }
 
   /**
@@ -114,50 +94,6 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
   /**
    * {@inheritdoc}
    */
-  public function isCacheable() {
-    // @todo Consider making the bulk operation form cacheable. See
-    //   https://www.drupal.org/node/2503009.
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return $this->languageManager->isMultilingual() ? $this->getEntityTranslationRenderer()->getCacheContexts() : [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityTypeId() {
-    return $this->getEntityType();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEntityManager() {
-    return $this->entityManager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getLanguageManager() {
-    return $this->languageManager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getView() {
-    return $this->view;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   protected function defineOptions() {
     $options = parent::defineOptions();
     $options['action_title'] = array('default' => $this->t('With selection'));
@@ -242,20 +178,15 @@ public function getValue(ResultRow $row, $field = NULL) {
    *   The current state of the form.
    */
   public function viewsForm(&$form, FormStateInterface $form_state) {
-    // Make sure we do not accidentally cache this form.
-    // @todo Evaluate this again in https://www.drupal.org/node/2503009.
-    $form['#cache']['max-age'] = 0;
-
     // Add the tableselect javascript.
     $form['#attached']['library'][] = 'core/drupal.tableselect';
-    $use_revision = array_key_exists('revision', $this->view->getQuery()->getEntityTableInfo());
 
     // Only add the bulk form options and buttons if there are results.
     if (!empty($this->view->result)) {
       // Render checkboxes for all rows.
       $form[$this->options['id']]['#tree'] = TRUE;
       foreach ($this->view->result as $row_index => $row) {
-        $entity = $this->getEntityTranslation($this->getEntity($row), $row);
+        $entity = $this->getEntity($row);
 
         $form[$this->options['id']][$row_index] = array(
           '#type' => 'checkbox',
@@ -264,7 +195,7 @@ public function viewsForm(&$form, FormStateInterface $form_state) {
           '#title' => $this->t('Update this item'),
           '#title_display' => 'invisible',
           '#default_value' => !empty($form_state->getValue($this->options['id'])[$row_index]) ? 1 : NULL,
-          '#return_value' => $this->calculateEntityBulkFormKey($entity, $use_revision),
+          '#return_value' => $this->calculateEntityBulkFormKey($entity),
         );
       }
 
@@ -363,7 +294,7 @@ public function viewsFormSubmit(&$form, FormStateInterface $form_state) {
 
         $count++;
 
-        $entities[$bulk_form_key] = $entity;
+        $entities[$entity->id()] = $entity;
       }
 
       $action->execute($entities);
@@ -412,9 +343,6 @@ public function viewsFormValidate(&$form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function query() {
-    if ($this->languageManager->isMultilingual()) {
-      $this->getEntityTranslationRenderer()->query($this->query, $this->relationship);
-    }
   }
 
   /**
@@ -440,9 +368,6 @@ protected function drupalSetMessage($message = NULL, $type = 'status', $repeat =
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity to calculate a bulk form key for.
-   * @param bool $use_revision
-   *   Whether the revision id should be added to the bulk form key. This should
-   *   be set to TRUE only if the view is listing entity revisions.
    *
    * @return string
    *   The bulk form key representing the entity's id, language and revision (if
@@ -450,10 +375,10 @@ protected function drupalSetMessage($message = NULL, $type = 'status', $repeat =
    *
    * @see self::loadEntityFromBulkFormKey()
    */
-  protected function calculateEntityBulkFormKey(EntityInterface $entity, $use_revision) {
+  protected function calculateEntityBulkFormKey(EntityInterface $entity) {
     $key_parts = [$entity->language()->getId(), $entity->id()];
 
-    if ($entity instanceof RevisionableInterface && $use_revision) {
+    if ($entity instanceof RevisionableInterface) {
       $key_parts[] = $entity->getRevisionId();
     }
 
@@ -473,20 +398,23 @@ protected function calculateEntityBulkFormKey(EntityInterface $entity, $use_revi
    */
   protected function loadEntityFromBulkFormKey($bulk_form_key) {
     $key_parts = explode('-', $bulk_form_key);
-    $revision_id = NULL;
+    $vid = NULL;
 
     // If there are 3 items, vid will be last.
     if (count($key_parts) === 3) {
-      $revision_id = array_pop($key_parts);
+      $vid = array_pop($key_parts);
     }
 
     // The first two items will always be langcode and ID.
     $id = array_pop($key_parts);
     $langcode = array_pop($key_parts);
 
-    // Load the entity or a specific revision depending on the given key.
-    $storage = $this->entityManager->getStorage($this->getEntityType());
-    $entity = $revision_id ? $storage->loadRevision($revision_id) : $storage->load($id);
+    if ($vid) {
+      $entity = $this->entityManager->getStorage($this->getEntityType())->loadRevision($vid);
+    }
+    else {
+      $entity = $this->entityManager->getStorage($this->getEntityType())->load($id);
+    }
 
     if ($entity instanceof TranslatableInterface) {
       $entity = $entity->getTranslation($langcode);
diff --git a/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php b/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php
index 44aeda6..4893c54 100644
--- a/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php
+++ b/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php
@@ -76,21 +76,9 @@ protected function assertPageCacheContextsAndTags(Url $url, array $expected_cont
     $cache_entry = \Drupal::cache('render')->get($cid);
     sort($cache_entry->tags);
     $this->assertEqual($cache_entry->tags, $expected_tags);
-    $this->debugCacheTags($cache_entry->tags, $expected_tags);
-  }
-
-  /**
-   * Provides debug information for cache tags.
-   *
-   * @param string[] $actual_tags
-   *   The actual cache tags.
-   * @param string[] $expected_tags
-   *   The expected cache tags.
-   */
-  protected function debugCacheTags(array $actual_tags, array $expected_tags) {
-    if ($actual_tags !== $expected_tags) {
-      debug('Missing cache tags: ' . implode(',', array_diff($expected_tags, $actual_tags)));
-      debug('Unwanted cache tags: ' . implode(',', array_diff($actual_tags, $expected_tags)));
+    if ($cache_entry->tags !== $expected_tags) {
+      debug('Missing cache tags: ' . implode(',', array_diff($cache_entry->tags, $expected_tags)));
+      debug('Unwanted cache tags: ' . implode(',', array_diff($expected_tags, $cache_entry->tags)));
     }
   }
 
@@ -102,10 +90,11 @@ protected function debugCacheTags(array $actual_tags, array $expected_tags) {
    */
   protected function assertCacheTags(array $expected_tags) {
     $actual_tags = $this->getCacheHeaderValues('X-Drupal-Cache-Tags');
-    sort($expected_tags);
-    sort($actual_tags);
     $this->assertIdentical($actual_tags, $expected_tags);
-    $this->debugCacheTags($actual_tags, $expected_tags);
+    if ($actual_tags !== $expected_tags) {
+      debug('Missing cache tags: ' . implode(',', array_diff($actual_tags, $expected_tags)));
+      debug('Unwanted cache tags: ' . implode(',', array_diff($expected_tags, $actual_tags)));
+    }
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Field/FieldModuleUninstallValidatorTest.php b/core/modules/system/src/Tests/Field/FieldModuleUninstallValidatorTest.php
index 0bed70b..f427ade 100644
--- a/core/modules/system/src/Tests/Field/FieldModuleUninstallValidatorTest.php
+++ b/core/modules/system/src/Tests/Field/FieldModuleUninstallValidatorTest.php
@@ -83,7 +83,7 @@ public function testUninstallingModule() {
     }
     catch (ModuleUninstallValidatorException $e) {
       $this->pass($message);
-      $this->assertEqual($e->getMessage(), 'The following reasons prevents the modules from being uninstalled: There is data for the field extra_base_field on entity type Test entity');
+      $this->assertEqual($e->getMessage(), 'The following reasons prevents the modules from being uninstalled: There is data for the field extra_base_field on entity type Test entity.');
     }
 
     // Verify uninstalling entity_test is not possible when there is content for
diff --git a/core/modules/system/src/Tests/File/DirectoryTest.php b/core/modules/system/src/Tests/File/DirectoryTest.php
index 50d498a..0822063 100644
--- a/core/modules/system/src/Tests/File/DirectoryTest.php
+++ b/core/modules/system/src/Tests/File/DirectoryTest.php
@@ -19,8 +19,7 @@ class DirectoryTest extends FileTestBase {
    * Test local directory handling functions.
    */
   function testFileCheckLocalDirectoryHandling() {
-    $site_path = $this->container->get('site.path');
-    $directory = $site_path . '/files';
+    $directory = conf_path() . '/files';
 
     // Check a new recursively created local directory for correct file system
     // permissions.
diff --git a/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php b/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php
index d4e7e31..242a378 100644
--- a/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php
+++ b/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php
@@ -34,8 +34,7 @@ class ReadOnlyStreamWrapperTest extends FileTestBase {
   function testReadOnlyBehavior() {
     // Generate a test file
     $filename = $this->randomMachineName();
-    $site_path = $this->container->get('site.path');
-    $filepath = $site_path . '/files/' . $filename;
+    $filepath = conf_path() . '/files/' . $filename;
     file_put_contents($filepath, $filename);
 
     // Generate a read-only stream wrapper instance
@@ -80,7 +79,7 @@ function testReadOnlyBehavior() {
 
     // Test the mkdir() function by attempting to create a directory.
     $dirname = $this->randomMachineName();
-    $dir = $site_path . '/files/' . $dirname;
+    $dir = conf_path() . '/files/' . $dirname;
     $readonlydir = $this->scheme . '://' . $dirname;
     $this->assertFalse(@drupal_mkdir($readonlydir, 0775, 0), 'Unable to create directory with read-only stream wrapper.');
     // Create a temporary directory for testing purposes
diff --git a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php b/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php
index 08ae978..25be1ef 100644
--- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php
@@ -9,8 +9,6 @@
 
 use Drupal\simpletest\InstallerTestBase;
 use Drupal\Core\Database\Database;
-use Drupal\Core\DrupalKernel;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Tests the installer with an existing settings file.
@@ -50,17 +48,14 @@ protected function setUp() {
       'required' => TRUE,
     );
 
-    // Use the kernel to find the site path because the site.path service should
-    // not be available at this point in the install process.
-    $site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
     // Pre-configure config directories.
     $this->settings['config_directories'] = array(
       CONFIG_ACTIVE_DIRECTORY => (object) array(
-        'value' => $site_path . '/files/config_active',
+        'value' => conf_path() . '/files/config_active',
         'required' => TRUE,
       ),
       CONFIG_STAGING_DIRECTORY => (object) array(
-        'value' => $site_path . '/files/config_staging',
+        'value' => conf_path() . '/files/config_staging',
         'required' => TRUE,
       ),
     );
diff --git a/core/modules/system/src/Tests/Module/DependencyTest.php b/core/modules/system/src/Tests/Module/DependencyTest.php
index 13a722d..88d959a 100644
--- a/core/modules/system/src/Tests/Module/DependencyTest.php
+++ b/core/modules/system/src/Tests/Module/DependencyTest.php
@@ -168,8 +168,8 @@ function testUninstallDependents() {
 
     // Check that the comment module cannot be uninstalled.
     $this->drupalGet('admin/modules/uninstall');
-    $checkbox = $this->xpath('//input[@type="checkbox" and @name="uninstall[comment]" and @disabled="disabled"]');
-    $this->assert(count($checkbox) == 1, 'Checkbox for uninstalling the comment module is disabled.');
+    $checkbox = $this->xpath('//input[@type="checkbox" and @name="uninstall[comment]"]');
+    $this->assert(count($checkbox) == 0, 'Checkbox for uninstalling the comment module not found.');
 
     // Delete any forum terms.
     $vid = $this->config('forum.settings')->get('vocabulary');
diff --git a/core/modules/system/src/Tests/Module/UninstallTest.php b/core/modules/system/src/Tests/Module/UninstallTest.php
index aa8a169..e43a674 100644
--- a/core/modules/system/src/Tests/Module/UninstallTest.php
+++ b/core/modules/system/src/Tests/Module/UninstallTest.php
@@ -56,8 +56,7 @@ function testUninstallPage() {
     $this->drupalGet('admin/modules/uninstall');
     $this->assertTitle(t('Uninstall') . ' | Drupal');
 
-    $this->assertText(\Drupal::translation()->translate('The following reason prevents Node from being uninstalled:'));
-    $this->assertText(\Drupal::translation()->translate('There is content for the entity type: Content'));
+    $this->assertText(\Drupal::translation()->translate('The following reasons prevents Node from being uninstalled: There is content for the entity type: Content'), 'Content prevents uninstalling node module.');
     // Delete the node to allow node to be uninstalled.
     $node->delete();
 
diff --git a/core/modules/system/src/Tests/Routing/ContentNegotiationRoutingTest.php b/core/modules/system/src/Tests/Routing/ContentNegotiationRoutingTest.php
deleted file mode 100644
index e9430b0..0000000
--- a/core/modules/system/src/Tests/Routing/ContentNegotiationRoutingTest.php
+++ /dev/null
@@ -1,157 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\conneg_test\Tests\ContentNegotiationRoutingTest.
- */
-
-namespace Drupal\system\Tests\Routing;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\simpletest\KernelTestBase;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-
-/**
- * Tests content negotiation routing variations.
- *
- * @group ContentNegotiation
- */
-class ContentNegotiationRoutingTest extends KernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['system', 'conneg_test'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    \Drupal::unsetContainer();
-    parent::setUp();
-
-    $this->installSchema('system', ['router', 'url_alias']);
-    \Drupal::service('router.builder')->rebuild();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function containerBuild(ContainerBuilder $container) {
-    parent::containerBuild($container);
-
-    // \Drupal\simpletest\KernelTestBase::containerBuild() removes the alias path
-    // processor.
-    if ($container->hasDefinition('path_processor_alias')) {
-      $definition = $container->getDefinition('path_processor_alias');
-      $definition->addTag('path_processor_inbound', ['priority' => 100])->addTag('path_processor_outbound', ['priority' => 300]);
-    }
-  }
-
-  /**
-   * Tests the content negotiation aspect of routing.
-   */
-  function testContentRouting() {
-    /** @var \Drupal\Core\Path\AliasStorageInterface $path_alias_storage */
-    $path_alias_storage = $this->container->get('path.alias_storage');
-    // Alias with extension pointing to no extension/constant content-type.
-    $path_alias_storage->save('conneg/html', 'alias.html');
-
-    // Alias with extension pointing to dynamic extension/linked content-type.
-    $path_alias_storage->save('conneg/html?_format=json', 'alias.json');
-
-    $tests = [
-      // ['path', 'accept', 'content-type'],
-
-      // Extension is part of the route path. Constant Content-type.
-      ['conneg/simple.json', '', 'application/json'],
-      ['conneg/simple.json', 'application/xml', 'application/json'],
-      ['conneg/simple.json', 'application/json', 'application/json'],
-      // No extension. Constant Content-type.
-      ['conneg/html', '', 'text/html'],
-      ['conneg/html', '*/*', 'text/html'],
-      ['conneg/html', 'application/xml', 'text/html'],
-      ['conneg/html', 'text/xml', 'text/html'],
-      ['conneg/html', 'text/html', 'text/html'],
-      // Dynamic extension. Linked Content-type.
-      ['conneg/html?_format=json', '', 'application/json'],
-      ['conneg/html?_format=json', '*/*', 'application/json'],
-      ['conneg/html?_format=json', 'application/xml', 'application/json'],
-      ['conneg/html?_format=json', 'application/json', 'application/json'],
-      ['conneg/html?_format=xml', '', 'application/xml'],
-      ['conneg/html?_format=xml', '*/*', 'application/xml'],
-      ['conneg/html?_format=xml', 'application/json', 'application/xml'],
-      ['conneg/html?_format=xml', 'application/xml', 'application/xml'],
-
-      // Path with a variable. Variable contains a period.
-      ['conneg/plugin/plugin.id', '', 'text/html'],
-      ['conneg/plugin/plugin.id', '*/*', 'text/html'],
-      ['conneg/plugin/plugin.id', 'text/xml', 'text/html'],
-      ['conneg/plugin/plugin.id', 'text/html', 'text/html'],
-
-      // Alias with extension pointing to no extension/constant content-type.
-      ['alias.html', '', 'text/html'],
-      ['alias.html', '*/*', 'text/html'],
-      ['alias.html', 'text/xml', 'text/html'],
-      ['alias.html', 'text/html', 'text/html'],
-    ];
-
-    foreach ($tests as $test) {
-      $path = $test[0];
-      $accept_header = $test[1];
-      $content_type = $test[2];
-      $message = "Testing path:$path Accept:$accept_header Content-type:$content_type";
-      $request = Request::create($path);
-      if ($accept_header) {
-        $request->headers->set('Accept', $accept_header);
-      }
-
-      /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
-      $kernel = \Drupal::getContainer()->get('http_kernel');
-      $response = $kernel->handle($request);
-      // Verbose message since simpletest doesn't let us provide a message and
-      // see the error.
-      $this->assertTrue(TRUE, $message);
-      $this->assertEqual($response->getStatusCode(), Response::HTTP_OK);
-      $this->assertTrue(strpos($response->headers->get('Content-type'), $content_type) !== FALSE);
-    }
-  }
-
-  /**
-   * Full negotiation by header only.
-   */
-  public function testFullNegotiation() {
-    $this->enableModules(['accept_header_routing_test']);
-    \Drupal::service('router.builder')->rebuild();
-    $tests = [
-      // ['path', 'accept', 'content-type'],
-
-      ['conneg/negotiate', '', 'text/html'], // 406?
-      ['conneg/negotiate', '', 'text/html'], // 406?
-      // ['conneg/negotiate', '*/*', '??'],
-      ['conneg/negotiate', 'application/json', 'application/json'],
-      ['conneg/negotiate', 'application/xml', 'application/xml'],
-      ['conneg/negotiate', 'application/json', 'application/json'],
-      ['conneg/negotiate', 'application/xml', 'application/xml'],
-    ];
-
-    foreach ($tests as $test) {
-      $path = $test[0];
-      $accept_header = $test[1];
-      $content_type = $test[2];
-      $message = "Testing path:$path Accept:$accept_header Content-type:$content_type";
-      $request = Request::create($path);
-      $request->headers->set('Accept', $accept_header);
-
-      /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
-      $kernel = \Drupal::getContainer()->get('http_kernel');
-      $response = $kernel->handle($request);
-      // Verbose message since simpletest doesn't let us provide a message and
-      // see the error.
-      $this->pass($message);
-      $this->assertEqual($response->getStatusCode(), Response::HTTP_OK);
-    }
-  }
-
-}
diff --git a/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php b/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php
index ee3c763..401420c 100644
--- a/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php
+++ b/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php
@@ -39,8 +39,8 @@ protected function setUp() {
    */
   public function testJson403() {
     $request = Request::create('/router_test/test15');
-    $request->query->set('_format', 'json');
-    $request->setRequestFormat('json');
+    $request->headers->set('Accept', 'application/json');
+    $request->setFormat('json', ['application/json']);
 
     /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
     $kernel = \Drupal::getContainer()->get('http_kernel');
@@ -56,8 +56,8 @@ public function testJson403() {
    */
   public function testJson404() {
     $request = Request::create('/not-found');
-    $request->query->set('_format', 'json');
-    $request->setRequestFormat('json');
+    $request->headers->set('Accept', 'application/json');
+    $request->setFormat('json', ['application/json']);
 
     /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
     $kernel = \Drupal::getContainer()->get('http_kernel');
@@ -73,6 +73,7 @@ public function testJson404() {
    */
   public function testHtml403() {
     $request = Request::create('/router_test/test15');
+    $request->headers->set('Accept', 'text/html');
     $request->setFormat('html', ['text/html']);
 
     /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
@@ -88,6 +89,7 @@ public function testHtml403() {
    */
   public function testHtml404() {
     $request = Request::create('/not-found');
+    $request->headers->set('Accept', 'text/html');
     $request->setFormat('html', ['text/html']);
 
     /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
@@ -106,6 +108,7 @@ public function testBacktraceEscaping() {
     $this->config('system.logging')->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save();
 
     $request = Request::create('/router_test/test17');
+    $request->headers->set('Accept', 'text/html');
     $request->setFormat('html', ['text/html']);
 
     /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $kernel */
diff --git a/core/modules/system/src/Tests/System/InfoAlterTest.php b/core/modules/system/src/Tests/System/InfoAlterTest.php
index 2af3d05..02cdd17 100644
--- a/core/modules/system/src/Tests/System/InfoAlterTest.php
+++ b/core/modules/system/src/Tests/System/InfoAlterTest.php
@@ -26,15 +26,15 @@ class InfoAlterTest extends KernelTestBase {
    * return freshly altered info.
    */
   function testSystemInfoAlter() {
-    \Drupal::state()->set('module_required_test.hook_system_info_alter', TRUE);
+    \Drupal::state()->set('module_test.hook_system_info_alter', TRUE);
     $info = system_rebuild_module_data();
-    $this->assertFalse(isset($info['node']->info['required']), 'Before the module_required_test is installed the node module is not required.');
+    $this->assertFalse(isset($info['node']->info['required']), 'Before the module_test is installed the node module is not required.');
 
     // Enable the test module.
-    \Drupal::service('module_installer')->install(array('module_required_test'), FALSE);
-    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('module_required_test'), 'Test required module is enabled.');
+    \Drupal::service('module_installer')->install(array('module_test'), FALSE);
+    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('module_test'), 'Test module is enabled.');
 
     $info = system_rebuild_module_data();
-    $this->assertTrue($info['node']->info['required'], 'After the module_required_test is installed the node module is required.');
+    $this->assertTrue($info['node']->info['required'], 'After the module_test is installed the node module is required.');
   }
 }
diff --git a/core/modules/system/src/Tests/System/ResponseGeneratorTest.php b/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
index 8684624..061f7f9 100644
--- a/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
+++ b/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
@@ -62,7 +62,7 @@ function testGeneratorHeaderAdded() {
     $this->enableService('entity:node', 'GET', 'json');
 
     // Tests to see if this also works for a non-html request
-    $this->httpRequest($node->urlInfo()->setOption('query', ['_format' => 'json']), 'GET');
+    $this->httpRequest($node->urlInfo(), 'GET', NULL, 'application/json');
     $this->assertResponse(200);
     $this->assertEqual('application/json', $this->drupalGetHeader('Content-Type'));
     $this->assertEqual($expectedGeneratorHeader, $this->drupalGetHeader('X-Generator'));
diff --git a/core/modules/system/src/Tests/System/SettingsRewriteTest.php b/core/modules/system/src/Tests/System/SettingsRewriteTest.php
index 1446cbd..70b4043 100644
--- a/core/modules/system/src/Tests/System/SettingsRewriteTest.php
+++ b/core/modules/system/src/Tests/System/SettingsRewriteTest.php
@@ -21,7 +21,6 @@ class SettingsRewriteTest extends KernelTestBase {
    */
   function testDrupalRewriteSettings() {
     include_once \Drupal::root() . '/core/includes/install.inc';
-    $site_path = $this->container->get('site.path');
     $tests = array(
       array(
         'original' => '$no_index_value_scalar = TRUE;',
@@ -100,7 +99,7 @@ function testDrupalRewriteSettings() {
       ),
     );
     foreach ($tests as $test) {
-      $filename = Settings::get('file_public_path', $site_path . '/files') . '/mock_settings.php';
+      $filename = Settings::get('file_public_path', conf_path() . '/files') . '/mock_settings.php';
       file_put_contents(\Drupal::root() . '/' . $filename, "<?php\n" . $test['original'] . "\n");
       drupal_rewrite_settings($test['settings'], $filename);
       $this->assertEqual(file_get_contents(\Drupal::root() . '/' . $filename), "<?php\n" . $test['expected'] . "\n");
@@ -118,7 +117,7 @@ function testDrupalRewriteSettings() {
       'expected' => '$no_index = true;'
     );
     // Make an empty file.
-    $filename = Settings::get('file_public_path', $site_path . '/files') . '/mock_settings.php';
+    $filename = Settings::get('file_public_path', conf_path() . '/files') . '/mock_settings.php';
     file_put_contents(\Drupal::root() . '/' . $filename, "");
 
     // Write the setting to the file.
diff --git a/core/modules/system/src/Tests/System/TokenReplaceUnitTest.php b/core/modules/system/src/Tests/System/TokenReplaceUnitTest.php
index f98c373..6cf92ef 100644
--- a/core/modules/system/src/Tests/System/TokenReplaceUnitTest.php
+++ b/core/modules/system/src/Tests/System/TokenReplaceUnitTest.php
@@ -154,7 +154,7 @@ public function testSystemDateTokenReplacement() {
     $tests['[date:medium]'] = $date_formatter->format($date, 'medium', '', NULL, $this->interfaceLanguage->getId());
     $tests['[date:long]'] = $date_formatter->format($date, 'long', '', NULL, $this->interfaceLanguage->getId());
     $tests['[date:custom:m/j/Y]'] = $date_formatter->format($date, 'custom', 'm/j/Y', NULL, $this->interfaceLanguage->getId());
-    $tests['[date:since]'] = $date_formatter->formatTimeDiffSince($date, array('langcode' => $this->interfaceLanguage->getId()));
+    $tests['[date:since]'] = $date_formatter->formatInterval(REQUEST_TIME - $date, 2, $this->interfaceLanguage->getId());
     $tests['[date:raw]'] = Xss::filter($date);
 
     // Test to make sure that we generated something for each token.
diff --git a/core/modules/system/src/Tests/Update/DbDumpTest.php b/core/modules/system/src/Tests/Update/DbDumpTest.php
deleted file mode 100644
index eed79cd..0000000
--- a/core/modules/system/src/Tests/Update/DbDumpTest.php
+++ /dev/null
@@ -1,277 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\system\Tests\Update\DbDumpTest.
- */
-
-namespace Drupal\system\Tests\Update;
-
-use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Core\Command\DbDumpApplication;
-use Drupal\Core\Config\DatabaseStorage;
-use Drupal\Core\Database\Database;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\simpletest\KernelTestBase;
-use Symfony\Component\Console\Tester\CommandTester;
-use Symfony\Component\DependencyInjection\Reference;
-
-/**
- * Tests for the database dump commands.
- *
- * @group Update
- */
-class DbDumpTest extends KernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['system', 'config', 'dblog', 'menu_link_content', 'link', 'block_content', 'file', 'user'];
-
-  /**
-   * Test data to write into config.
-   *
-   * @var array
-   */
-  protected $data;
-
-  /**
-   * Flag to skip these tests, which are database-backend dependent (MySQL).
-   *
-   * @see \Drupal\Core\Command\DbDumpCommand
-   *
-   * @var bool
-   */
-  protected $skipTests = FALSE;
-
-  /**
-   * An array of original table schemas.
-   *
-   * @var array
-   */
-  protected $originalTableSchemas = [];
-
-  /**
-   * An array of original table indexes (including primary and unique keys).
-   *
-   * @var array
-   */
-  protected $originalTableIndexes = [];
-
-  /**
-   * Tables that should be part of the exported script.
-   *
-   * @var array
-   */
-  protected $tables;
-
-  /**
-   * {@inheritdoc}
-   *
-   * Register a database cache backend rather than memory-based.
-   */
-  public function containerBuild(ContainerBuilder $container) {
-    parent::containerBuild($container);
-    $container->register('cache_factory', 'Drupal\Core\Cache\DatabaseBackendFactory')
-      ->addArgument(new Reference('database'))
-      ->addArgument(new Reference('cache_tags.invalidator.checksum'));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setUp() {
-    parent::setUp();
-
-    // Determine what database backend is running, and set the skip flag.
-    $this->skipTests = Database::getConnection()->databaseType() !== 'mysql';
-
-    // Create some schemas so our export contains tables.
-    $this->installSchema('system', [
-      'key_value_expire',
-      'semaphore',
-      'sessions',
-      'url_alias',
-    ]);
-    $this->installSchema('dblog', ['watchdog']);
-    $this->installEntitySchema('block_content');
-    $this->installEntitySchema('user');
-    $this->installEntitySchema('file');
-    $this->installEntitySchema('menu_link_content');
-
-    // Place some sample config to test for in the export.
-    $this->data = [
-      'foo' => $this->randomMachineName(),
-      'bar' => $this->randomMachineName()
-    ];
-    $storage = new DatabaseStorage(Database::getConnection(), 'config');
-    $storage->write('test_config', $this->data);
-
-    // Create a cache table (this will create 'cache_discovery').
-    \Drupal::cache('discovery')->set('test', $this->data);
-
-    // These are all the tables that should now be in place.
-    $this->tables = [
-      'block_content',
-      'block_content_field_data',
-      'block_content_field_revision',
-      'block_content_revision',
-      'cachetags',
-      'config',
-      'cache_discovery',
-      'cache_bootstrap',
-      'cache_default',
-      'file_managed',
-      'key_value_expire',
-      'menu_link_content',
-      'menu_link_content_data',
-      'semaphore',
-      'sessions',
-      'url_alias',
-      'user__roles',
-      'users',
-      'users_field_data',
-      'watchdog',
-    ];
-  }
-
-  /**
-   * Test the command directly.
-   */
-  public function testDbDumpCommand() {
-    if ($this->skipTests) {
-      $this->pass("Skipping test since the DbDumpCommand is currently only compatible with MySql");
-      return;
-    }
-
-    $application = new DbDumpApplication(Database::getConnection(), $this->container->get('module_handler'));
-    $command = $application->find('dump-database-d8-mysql');
-    $command_tester = new CommandTester($command);
-    $command_tester->execute([]);
-
-    // The enabled modules should be present in the docblock.
-    $modules = static::$modules;
-    asort($modules);
-    $pattern = preg_quote(implode("\n *  - ", $modules));
-    $this->assertTrue(preg_match('/' . $pattern . '/', $command_tester->getDisplay()), 'Module list is contained in the docblock of the script.');
-
-    // A module that is not enabled should not be listed.
-    $pattern = preg_quote(" *  - telephone");
-    $this->assertFalse(preg_match('/' . $pattern . '/', $command_tester->getDisplay()), 'Disabled modules do not appear in the docblock of the script.');
-
-    // Tables that are schema-only should not have data exported.
-    $pattern = preg_quote("\$connection->insert('sessions')");
-    $this->assertFalse(preg_match('/' . $pattern . '/', $command_tester->getDisplay()), 'Tables defined as schema-only do not have data exported to the script.');
-
-    // Table data is exported.
-    $pattern = preg_quote("\$connection->insert('config')");
-    $this->assertTrue(preg_match('/' . $pattern . '/', $command_tester->getDisplay()), 'Table data is properly exported to the script.');
-
-    // The test data are in the dump (serialized).
-    $pattern = preg_quote(serialize($this->data));
-    $this->assertTrue(preg_match('/' . $pattern . '/', $command_tester->getDisplay()), 'Generated data is found in the exported script.');
-  }
-
-  /**
-   * Test loading the script back into the database.
-   */
-  public function testScriptLoad() {
-    if ($this->skipTests) {
-      $this->pass("Skipping test since the DbDumpCommand is currently only compatible with MySql");
-      return;
-    }
-
-    // Generate the script.
-    $application = new DbDumpApplication(Database::getConnection(), $this->container->get('module_handler'));
-    $command = $application->find('dump-database-d8-mysql');
-    $command_tester = new CommandTester($command);
-    $command_tester->execute([]);
-    $script = $command_tester->getDisplay();
-
-    // Store original schemas and drop tables to avoid errors.
-    foreach ($this->tables as $table) {
-      $this->originalTableSchemas[$table] = $this->getTableSchema($table);
-      $this->originalTableIndexes[$table] = $this->getTableIndexes($table);
-      Database::getConnection()->schema()->dropTable($table);
-    }
-
-    // This will load the data.
-    $file = sys_get_temp_dir() . '/' . $this->randomMachineName();
-    file_put_contents($file, $script);
-    require_once $file;
-
-    // The tables should now exist and the schemas should match the originals.
-    foreach ($this->tables as $table) {
-      $this->assertTrue(Database::getConnection()
-        ->schema()
-        ->tableExists($table), SafeMarkup::format('Table @table created by the database script.', ['@table' => $table]));
-      $this->assertIdentical($this->originalTableSchemas[$table], $this->getTableSchema($table), SafeMarkup::format('The schema for @table was properly restored.', ['@table' => $table]));
-      $this->assertIdentical($this->originalTableIndexes[$table], $this->getTableIndexes($table), SafeMarkup::format('The indexes for @table were properly restored.', ['@table' => $table]));
-    }
-
-    // Ensure the test config has been replaced.
-    $config = unserialize(db_query("SELECT data FROM {config} WHERE name = 'test_config'")->fetchField());
-    $this->assertIdentical($config, $this->data, 'Script has properly restored the config table data.');
-
-    // Ensure the cache data was not exported.
-    $this->assertFalse(\Drupal::cache('discovery')
-      ->get('test'), 'Cache data was not exported to the script.');
-  }
-
-  /**
-   * Helper function to get a simplified schema for a given table.
-   *
-   * @param string $table
-   *
-   * @return array
-   *   Array keyed by field name, with the values being the field type.
-   */
-  protected function getTableSchema($table) {
-    // Verify the field type on the data column in the cache table.
-    // @todo this is MySQL specific.
-    $query = db_query("SHOW COLUMNS FROM {" . $table . "}");
-    $definition = [];
-    while ($row = $query->fetchAssoc()) {
-      $definition[$row['Field']] = $row['Type'];
-    }
-    return $definition;
-  }
-
-  /**
-   * Returns indexes for a given table.
-   *
-   * @param string $table
-   *   The table to find indexes for.
-   *
-   * @return array
-   *   The 'primary key', 'unique keys', and 'indexes' portion of the Drupal
-   *   table schema.
-   */
-  protected function getTableIndexes($table) {
-    $query = db_query("SHOW INDEX FROM {" . $table . "}");
-    $definition = [];
-    while ($row = $query->fetchAssoc()) {
-      $index_name = $row['Key_name'];
-      $column = $row['Column_name'];
-      // Key the arrays by the index sequence for proper ordering (start at 0).
-      $order = $row['Seq_in_index'] - 1;
-
-      // If specified, add length to the index.
-      if ($row['Sub_part']) {
-        $column = [$column, $row['Sub_part']];
-      }
-
-      if ($index_name === 'PRIMARY') {
-        $definition['primary key'][$order] = $column;
-      }
-      elseif ($row['Non_unique'] == 0) {
-        $definition['unique keys'][$index_name][$order] = $column;
-      }
-      else {
-        $definition['indexes'][$index_name][$order] = $column;
-      }
-    }
-    return $definition;
-  }
-
-}
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 276e393..81fa6af 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -303,22 +303,16 @@ function theme_system_modules_uninstall($variables) {
   // Display table.
   $rows = array();
   foreach (Element::children($form['modules']) as $module) {
-    $disabled_header = '';
-    $disabled_reasons = '';
+    $disabled_message = '';
     // Add the modules requiring the module in question as a validation reason.
     if (!empty($form['modules'][$module]['#required_by'])) {
       $form['modules'][$module]['#validation_reasons'][] = \Drupal::translation()->translate('Required by: @modules', array('@modules' => implode(', ',$form['modules'][$module]['#required_by'])));
     }
     if (!empty($form['modules'][$module]['#validation_reasons'])) {
-      $disabled_reasons = [
-        '#theme' => 'item_list',
-        '#items' => $form['modules'][$module]['#validation_reasons'],
-      ];
-      $disabled_reasons = drupal_render($disabled_reasons);
-      $disabled_header = \Drupal::translation()->formatPlural(count($form['modules'][$module]['#validation_reasons']),
-        'The following reason prevents @module from being uninstalled:',
-        'The following reasons prevents @module from being uninstalled:',
-        array('@module' => $form['modules'][$module]['#module_name']));
+      $disabled_message = \Drupal::translation()->formatPlural(count($form['modules'][$module]['#validation_reasons']),
+        'The following reason prevents @module from being uninstalled: @reasons',
+        'The following reasons prevents @module from being uninstalled: @reasons',
+        array('@module' => $form['modules'][$module]['#module_name'], '@reasons' => implode('; ', $form['modules'][$module]['#validation_reasons'])));
     }
     $rows[] = array(
       array('data' => drupal_render($form['uninstall'][$module]), 'align' => 'center'),
@@ -332,11 +326,10 @@ function theme_system_modules_uninstall($variables) {
       array(
         'data' => array(
           '#type' => 'inline_template',
-          '#template' => '{{ module_description }} {% if disabled_header is not empty %} <div class="admin-requirements">{{ disabled_header }}{{ disabled_reasons }}</div> {% endif %}',
+          '#template' => '{{ module_description }} {% if disabled_message is not empty %} <div class="admin-requirements">{{ disabled_message }}</div> {% endif %}',
           '#context' => array(
             'module_description' => drupal_render($form['modules'][$module]['description']),
-            'disabled_header' => $disabled_header,
-            'disabled_reasons' => $disabled_reasons,
+            'disabled_message' => $disabled_message,
           ),
         ),
         'class' => array('description'),
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index a0849b1..66308e3 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -10,13 +10,11 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Url;
 use Drupal\Core\Database\Database;
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\StreamWrapper\PrivateStream;
 use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\system\SystemRequirements;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Implements hook_requirements().
@@ -252,19 +250,12 @@ function system_requirements($phase) {
   // Test configuration files and directory for writability.
   if ($phase == 'runtime') {
     $conf_errors = array();
-    // Find the site path. Kernel service is not always available at this point,
-    // but is preferred, when available.
-    if (\Drupal::hasService('kernel')) {
-      $site_path = \Drupal::service('site.path');
-    }
-    else {
-      $site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
-    }
-    if (!drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir')) {
-      $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $site_path));
+    $conf_path = conf_path();
+    if (!drupal_verify_install_file($conf_path, FILE_NOT_WRITABLE, 'dir')) {
+      $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $conf_path));
     }
     foreach (array('settings.php', 'settings.local.php', 'services.yml') as $conf_file) {
-      $full_path = $site_path . '/' . $conf_file;
+      $full_path = $conf_path . '/' . $conf_file;
       if (file_exists($full_path) && !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE)) {
         $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array('%file' => $full_path));
       }
@@ -359,7 +350,7 @@ function system_requirements($phase) {
     }
 
     // Set summary and description based on values determined above.
-    $summary = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
+    $summary = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $cron_last)));
     $description = '';
     if ($severity != REQUIREMENT_INFO) {
       $description = t('Cron has not run recently.') . ' ' . $help;
@@ -400,9 +391,7 @@ function system_requirements($phase) {
     else {
       // If we are installing Drupal, the settings.php file might not exist yet
       // in the intended site directory, so don't require it.
-      $request = Request::createFromGlobals();
-      $site_path = DrupalKernel::findSitePath($request);
-      $directories[] = $site_path . '/files';
+      $directories[] = conf_path(FALSE) . '/files';
     }
     if ($file_private_path = Settings::get('file_private_path')) {
       $directories[] = $file_private_path;
@@ -429,7 +418,7 @@ function system_requirements($phase) {
     $requirements['config directories'] = array(
       'title' => t('Configuration directories'),
       'value' => t('Not present'),
-      'description' => t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => $site_path . '/settings.php')),
+      'description' => t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => conf_path() . '/settings.php')),
       'severity' => REQUIREMENT_ERROR,
     );
   }
diff --git a/core/modules/system/system.tokens.inc b/core/modules/system/system.tokens.inc
index 20d5ec1..8ce5825 100644
--- a/core/modules/system/system.tokens.inc
+++ b/core/modules/system/system.tokens.inc
@@ -68,7 +68,7 @@ function system_token_info() {
   );
   $date['since'] = array(
     'name' => t("Time-since"),
-    'description' => t("A date in 'time-since' format. (%date)", array('%date' => \Drupal::service('date.formatter')->formatTimeDiffSince(REQUEST_TIME - 360))),
+    'description' => t("A date in 'time-since' format. (%date)", array('%date' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - 360, 2))),
   );
   $date['raw'] = array(
     'name' => t("Raw timestamp"),
@@ -157,7 +157,7 @@ function system_tokens($type, $tokens, array $data = array(), array $options = a
           break;
 
         case 'since':
-          $replacements[$original] = \Drupal::service('date.formatter')->formatTimeDiffSince($date, array('langcode' => $langcode));
+          $replacements[$original] = \Drupal::service('date.formatter')->formatInterval((REQUEST_TIME - $date), 2, $langcode);
           break;
 
         case 'raw':
diff --git a/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.info.yml b/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.info.yml
deleted file mode 100644
index d93e67b..0000000
--- a/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.info.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-name: Accept header based routing test
-core: 8.x
-type: module
diff --git a/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml b/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml
deleted file mode 100644
index dc0ce10..0000000
--- a/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-services:
-  accept_header_matcher:
-    class: Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher
-    tags:
-      - { name: route_filter }
diff --git a/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php b/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php
deleted file mode 100644
index 51daedb..0000000
--- a/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\accept_header_routing_test\AcceptHeaderMiddleware.
- */
-
-namespace Drupal\accept_header_routing_test;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-
-/**
- * Example implementation of accept header based content negotation.
- */
-class AcceptHeaderMiddleware implements HttpKernelInterface {
-
-  /**
-   * Constructs a new AcceptHeaderMiddleware instance.
-   *
-   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $app
-   *   The app.
-   */
-  public function __construct(HttpKernelInterface $app) {
-    $this->app = $app;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
-    $mapping = [
-      'application/json' => 'json',
-      'application/hal+json' => 'hal_json',
-      'application/xml' => 'xml',
-      'text/html' => 'html',
-    ];
-
-    $accept = $request->headers->get('Accept') ?: ['text/html'];
-    if (isset($mapping[$accept[0]])) {
-      $request->setRequestFormat($mapping[$accept[0]]);
-    }
-
-    return $this->app->handle($request, $type, $catch);
-  }
-
-}
diff --git a/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php b/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php
deleted file mode 100644
index e1cab64..0000000
--- a/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\accept_header_routing_test\AcceptHeaderRoutingTestServiceProvider.
- */
-
-namespace Drupal\accept_header_routing_test;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceModifierInterface;
-
-/**
- * Service provider for the accept_header_routing_test module.
- */
-class AcceptHeaderRoutingTestServiceProvider implements ServiceModifierInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    // Remove the basic content negotation middleware and replace it with a
-    // basic header based one.
-    $container->register('http_middleware.negotiation', 'Drupal\accept_header_routing_test\AcceptHeaderMiddleware')
-      ->addTag('http_middleware', ['priority' => 400]);
-  }
-
-}
diff --git a/core/modules/system/tests/modules/conneg_test/conneg_test.info.yml b/core/modules/system/tests/modules/conneg_test/conneg_test.info.yml
deleted file mode 100644
index 07f4600..0000000
--- a/core/modules/system/tests/modules/conneg_test/conneg_test.info.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-name: Content negotiation test
-type: module
-description: 'Support testing content negotiation variations.'
-package: Core
-version: VERSION
-core: 8.x
diff --git a/core/modules/system/tests/modules/conneg_test/conneg_test.routing.yml b/core/modules/system/tests/modules/conneg_test/conneg_test.routing.yml
deleted file mode 100644
index bedd52e..0000000
--- a/core/modules/system/tests/modules/conneg_test/conneg_test.routing.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Tests
-conneg.simpletest:
-  path: conneg/simple.json
-  defaults:
-    _controller: '\Drupal\conneg_test\Controller\TestController::simple'
-  requirements:
-    _access: 'TRUE'
-conneg.html:
-  path: conneg/html
-  defaults:
-    _controller: '\Drupal\conneg_test\Controller\TestController::html'
-  requirements:
-    _access: 'TRUE'
-conneg.simple_conneg:
-  path: conneg/html
-  defaults:
-    _controller: '\Drupal\conneg_test\Controller\TestController::format'
-  requirements:
-    _access: 'TRUE'
-    _format: 'json|xml'
-conneg.variable_with_period:
-  path: conneg/plugin/{plugin_id}
-  defaults:
-    _controller: '\Drupal\conneg_test\Controller\TestController::variable'
-  requirements:
-    _access: 'TRUE'
-conneg.full_content_negotiation:
-  path: conneg/negotiate
-  defaults:
-    _controller: '\Drupal\conneg_test\Controller\TestController::format'
-  requirements:
-    _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php b/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php
deleted file mode 100644
index c93a5a1..0000000
--- a/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\conneg_test\Controller\Test.
- */
-
-namespace Drupal\conneg_test\Controller;
-
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-
-/**
- * Test controller for content negotation tests.
- */
-class TestController {
-
-  /**
-   * Returns a json response.
-   *
-   * @return \Symfony\Component\HttpFoundation\JsonResponse
-   */
-  public function simple() {
-    return new JsonResponse(['some' => 'data']);
-  }
-
-  /**
-   * Returns a simple render array.
-   *
-   * @return array
-   */
-  public function html() {
-    return [
-      '#markup' => 'here',
-    ];
-  }
-
-  /**
-   * Returns different responses dependening on the request format.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request
-   *
-   * @return \Symfony\Component\HttpFoundation\Response
-   *   The response.
-   */
-  public function format(Request $request) {
-    switch ($request->getRequestFormat()) {
-      case 'json':
-        return new JsonResponse(['some' => 'data']);
-
-      case 'xml':
-        return new Response('<xml></xml>', Response::HTTP_OK, ['Content-Type' => 'application/xml']);
-
-      default:
-        return new Response($request->getRequestFormat());
-    }
-  }
-
-  /**
-   * Returns a render array depending on some passed in value.
-   *
-   * @param string $plugin_id
-   *   The plugin ID.
-   *
-   * @return array
-   *   The render array
-   */
-  public function variable($plugin_id) {
-    return [
-      '#markup' => $plugin_id,
-    ];
-  }
-
-}
diff --git a/core/modules/system/tests/modules/entity_test/src/Cache/EntityTestViewGrantsCacheContext.php b/core/modules/system/tests/modules/entity_test/src/Cache/EntityTestViewGrantsCacheContext.php
index 53649f5..ede6410 100644
--- a/core/modules/system/tests/modules/entity_test/src/Cache/EntityTestViewGrantsCacheContext.php
+++ b/core/modules/system/tests/modules/entity_test/src/Cache/EntityTestViewGrantsCacheContext.php
@@ -27,9 +27,7 @@ public static function getLabel() {
    * {@inheritdoc}
    */
   public function getContext() {
-    // Return a constant value, so we can fetch render cache both in actual
-    // requests and test code itself.
-    return '299792458';
+    return hash('sha256', REQUEST_TIME);
   }
 
 }
diff --git a/core/modules/system/tests/modules/module_required_test/module_required_test.info.yml b/core/modules/system/tests/modules/module_required_test/module_required_test.info.yml
deleted file mode 100644
index f424d95..0000000
--- a/core/modules/system/tests/modules/module_required_test/module_required_test.info.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-name: 'Module required test'
-type: module
-description: 'Support module for module system testing.'
-package: Testing
-version: VERSION
-core: 8.x
-# Depends on the Node module to test making a module required using
-# hook_system_info_alter() and ensuring that its dependencies also become
-# required.
-dependencies:
-  - drupal:node (>=8.x)
diff --git a/core/modules/system/tests/modules/module_required_test/module_required_test.module b/core/modules/system/tests/modules/module_required_test/module_required_test.module
deleted file mode 100644
index fbb6f10..0000000
--- a/core/modules/system/tests/modules/module_required_test/module_required_test.module
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-use Drupal\Core\Extension\Extension;
-
-/**
- * Implements hook_system_info_alter().
- *
- * Manipulate module dependencies to test dependency chains.
- */
-function module_required_test_system_info_alter(&$info, Extension $file, $type) {
-  if ($file->getName() == 'module_required_test' && \Drupal::state()->get('module_required_test.hook_system_info_alter')) {
-    $info['required'] = TRUE;
-    $info['explanation'] = 'Testing hook_system_info_alter()';
-  }
-}
diff --git a/core/modules/system/tests/modules/module_test/module_test.info.yml b/core/modules/system/tests/modules/module_test/module_test.info.yml
index 5c63da2..241c3ad 100644
--- a/core/modules/system/tests/modules/module_test/module_test.info.yml
+++ b/core/modules/system/tests/modules/module_test/module_test.info.yml
@@ -4,3 +4,8 @@ description: 'Support module for module system testing.'
 package: Testing
 version: VERSION
 core: 8.x
+# Depends on the Node module to test making a module required using
+# hook_system_info_alter() and ensuring that its dependencies also become
+# required.
+dependencies:
+  - drupal:node (>=8.x)
diff --git a/core/modules/system/tests/modules/module_test/module_test.module b/core/modules/system/tests/modules/module_test/module_test.module
index cead329..92f038b 100644
--- a/core/modules/system/tests/modules/module_test/module_test.module
+++ b/core/modules/system/tests/modules/module_test/module_test.module
@@ -49,6 +49,10 @@ function module_test_system_info_alter(&$info, Extension $file, $type) {
   if ($file->getName() == 'seven' && $type == 'theme') {
     $info['regions']['test_region'] = t('Test region');
   }
+  if ($file->getName() == 'module_test' && \Drupal::state()->get('module_test.hook_system_info_alter')) {
+    $info['required'] = TRUE;
+    $info['explanation'] = 'Testing hook_system_info_alter()';
+  }
 }
 
 /**
diff --git a/core/modules/system/tests/modules/system_test/src/Controller/PageCacheAcceptHeaderController.php b/core/modules/system/tests/modules/system_test/src/Controller/PageCacheAcceptHeaderController.php
index c24d7c5..43cded1 100644
--- a/core/modules/system/tests/modules/system_test/src/Controller/PageCacheAcceptHeaderController.php
+++ b/core/modules/system/tests/modules/system_test/src/Controller/PageCacheAcceptHeaderController.php
@@ -25,7 +25,7 @@ class PageCacheAcceptHeaderController {
    * @return mixed
    */
   public function content(Request $request) {
-    if ($request->getRequestFormat() === 'json') {
+    if ($request->headers->get('Accept') == 'application/json') {
       return new JsonResponse(array('content' => 'oh hai this is json'));
     }
     else {
diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php
index fdba136..92a8342 100644
--- a/core/modules/system/theme.api.php
+++ b/core/modules/system/theme.api.php
@@ -847,26 +847,22 @@ function hook_js_settings_alter(array &$settings, \Drupal\Core\Asset\AttachedAss
 }
 
 /**
- * Alter libraries provided by an extension.
+ * Alters the JavaScript/CSS library registry.
  *
- * Allows modules and themes to change libraries' definitions; mostly used to
- * update a library to a newer version, while ensuring backward compatibility.
- * In general, such manipulations should only be done to extend the library's
- * functionality in a backward-compatible way, to avoid breaking other modules
- * and themes that may be using the library.
+ * Allows certain, contributed modules to update libraries to newer versions
+ * while ensuring backwards compatibility. In general, such manipulations should
+ * only be done by designated modules, since most modules that integrate with a
+ * certain library also depend on the API of a certain library version.
  *
- * @param array $libraries
- *   An associative array of libraries registered by $extension. Keyed by
- *   internal library name and passed by reference.
- * @param string $extension
- *   Can either be 'core' or the machine name of the extension that registered
- *   the libraries.
- *
- * @see \Drupal\Core\Asset\LibraryDiscoveryParser::parseLibraryInfo()
+ * @param $libraries
+ *   The JavaScript/CSS libraries provided by $module. Keyed by internal library
+ *   name and passed by reference.
+ * @param $module
+ *   The name of the module that registered the libraries.
  */
-function hook_library_info_alter(&$libraries, $extension) {
+function hook_library_info_alter(&$libraries, $module) {
   // Update Farbtastic to version 2.0.
-  if ($extension == 'core' && isset($libraries['jquery.farbtastic'])) {
+  if ($module == 'core' && isset($libraries['jquery.farbtastic'])) {
     // Verify existing version is older than the one we are updating to.
     if (version_compare($libraries['jquery.farbtastic']['version'], '2.0', '<')) {
       // Update the existing Farbtastic to version 2.0.
diff --git a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml
index e1086d1..a343b9f 100644
--- a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml
+++ b/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml
@@ -35,7 +35,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       exposed_form:
         type: basic
diff --git a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
index 526e4c3..b439c06 100644
--- a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
+++ b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
@@ -211,6 +211,13 @@ public function getArgument() {
         }
       }
     }
+
+    // If the current page is a view that takes tid as an argument,
+    // find the tid argument and return it.
+    $views_page = views_get_page_view();
+    if ($views_page && isset($views_page->argument['tid'])) {
+      return $views_page->argument['tid']->argument;
+    }
   }
 
   /**
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index eedc761..7ed0d38 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -179,7 +179,7 @@ function taxonomy_check_vocabulary_hierarchy(VocabularyInterface $vocabulary, $c
  * @param \Drupal\taxonomy\Entity\Term $term
  *   A taxonomy term object.
  * @param string $view_mode
- *   View mode; e.g., 'full', 'teaser', etc.
+ *   View mode, e.g. 'full', 'teaser'...
  * @param string $langcode
  *   (optional) A language code to use for rendering. Defaults to the global
  *   content language of the current request.
@@ -197,7 +197,7 @@ function taxonomy_term_view(Term $term, $view_mode = 'full', $langcode = NULL) {
  * @param array $terms
  *   An array of taxonomy terms as returned by Term::loadMultiple().
  * @param string $view_mode
- *   View mode; e.g., 'full', 'teaser', etc.
+ *   View mode, e.g. 'full', 'teaser'...
  * @param string $langcode
  *   (optional) A language code to use for rendering. Defaults to the global
  *   content language of the current request.
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.taxonomy_default_argument_test.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.taxonomy_default_argument_test.yml
index 615972b..dcb0bc4 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.taxonomy_default_argument_test.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.taxonomy_default_argument_test.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml
index b2a7c9e..baa59ff 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
index 32a5a8b..b32e452 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml
index b564d69..500e8b9 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml
index a802762..c4e18a0 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml
index beb3c63..0623f98 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_node_term_data.yml
@@ -48,7 +48,7 @@ display:
           entity_type: taxonomy_term
           entity_field: tid
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_parent.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_parent.yml
index fbb97fd..eb6d298 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_parent.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_parent.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_name.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_name.yml
index cdcec2c..6fae130 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_name.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_name.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_relationship.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_relationship.yml
index 22521bc..eb561c6 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_relationship.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_term_relationship.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml
index 35ad6de..6fab886 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/tour/css/tour.module.css b/core/modules/tour/css/tour.module.css
index 18d8aa0..4230a56 100644
--- a/core/modules/tour/css/tour.module.css
+++ b/core/modules/tour/css/tour.module.css
@@ -10,16 +10,45 @@
 [dir="rtl"] .toolbar .toolbar-bar .tour-toolbar-tab.toolbar-tab {
   float: left;
 }
+.toolbar .tour-toolbar-tab button {
+  padding-bottom: 1em;
+  padding-top: 1em;
+  color: #fff;
+  font-weight: bold;
+}
+.toolbar .tour-toolbar-tab button.is-active {
+  background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
+  background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
+}
+.tour-toolbar-tab button:focus {
+  outline: thin dotted;
+}
+
+/* @todo Remove once https://www.drupal.org/node/1916690 is resolved. */
+.toolbar .tour-toolbar-tab.toolbar-tab.hidden {
+  display: none;
+}
 
 /* Override placement of the tour progress indicator. */
 .tour-progress {
   position: absolute;
-  bottom: 20px;
-  right: 20px; /* LTR */
+  /* Equals paddings from .joyride-content-wrapper */
+  bottom: 0;
+  right: 0; /* LTR */
 }
 [dir="rtl"] .tour-progress {
   right: auto;
-  left: 20px;
+  left: 0;
+}
+
+/* @todo Remove once https://www.drupal.org/node/1916690 is resolved. */
+.toolbar .tour-toolbar-tab.toolbar-tab.hidden {
+  display: none;
+}
+
+/* JoyRide Styles. */
+#joyRideTipContent {
+  display: none;
 }
 
 /* Default styles for the container */
@@ -29,9 +58,25 @@
   background: #fff;
   width: 300px;
   z-index: 101;
-  top: 0;
+  top: 0; /* keeps the page from scrolling when calculating position. */
   left: 0;
+  padding: 1em 1em 1.5em 1.5em; /* LTR */
 }
+[dir="rtl"] .joyride-tip-guide {
+  padding: 1em 1.5em 1.5em 1em;
+}
+
+.joyride-content-wrapper {
+  /* Apply padding from parent .joyride-tip-guide to absolutely positioned children. */
+  position: relative;
+  padding-right: 1em; /* LTR */
+}
+[dir="rtl"] .joyride-content-wrapper {
+  padding-right: 0;
+  padding-left: 1em;
+}
+
+/* Mobile */
 @media only screen and (max-width: 767px) {
   .joyride-tip-guide {
     width: 85%;
@@ -39,14 +84,6 @@
   }
 }
 
-.joyride-content-wrapper {
-  position: relative;
-  padding: 20px 50px 20px 20px;  /* LTR */
-}
-[dir="rtl"] .joyride-content-wrapper {
-  padding: 20px 20px 20px 50px;
-}
-
 /* Add a little css triangle pip, older browser just miss out on the fanciness of it. */
 .joyride-tip-guide .joyride-nub {
   display: block;
@@ -86,10 +123,6 @@
   right: 28px;
 }
 
-.joyride-tip-guide .tour-tip-label {
-  margin-top: 0;
-}
-
 .joyride-tip-guide p {
   margin: 0 0 1.4em;
 }
@@ -109,12 +142,11 @@
 
 .joyride-close-tip {
   position: absolute;
-  line-height: 1em;
-  right: 20px; /* LTR */
-  top: 20px;
+  right: 0; /* LTR */
+  top: 0;
 }
 [dir="rtl"] .joyride-close-tip {
-  left: 20px;
+  left: 0;
   right: auto;
 }
 
diff --git a/core/modules/tracker/src/Tests/TrackerTest.php b/core/modules/tracker/src/Tests/TrackerTest.php
index bc2f564..c5c8500 100644
--- a/core/modules/tracker/src/Tests/TrackerTest.php
+++ b/core/modules/tracker/src/Tests/TrackerTest.php
@@ -91,7 +91,7 @@ function testTrackerAll() {
 
     $this->drupalGet('activity');
     $this->assertText($node->label(), 'Published node shows up in the tracker listing.');
-    $this->assertText(\Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime()), 'The changed time was displayed on the tracker listing.');
+    $this->assertText(\Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->getChangedTime()), 'The changed time was displayed on the tracker listing.');
   }
 
   /**
diff --git a/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml b/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml
index 04bdd4d..7b11ddc 100644
--- a/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml
+++ b/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml
@@ -23,7 +23,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index 4ce372d..5eac748 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -114,7 +114,7 @@ function tracker_page($account = NULL) {
         ),
         'last updated' => array(
           'data' => t('!time ago', array(
-            '!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($node->last_activity),
+            '!time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->last_activity),
           )),
         ),
       );
diff --git a/core/modules/update/src/Form/UpdateManagerInstall.php b/core/modules/update/src/Form/UpdateManagerInstall.php
index b37f246..e957358 100644
--- a/core/modules/update/src/Form/UpdateManagerInstall.php
+++ b/core/modules/update/src/Form/UpdateManagerInstall.php
@@ -34,26 +34,16 @@ class UpdateManagerInstall extends FormBase {
   protected $root;
 
   /**
-   * The site path.
-   *
-   * @var string
-   */
-  protected $sitePath;
-
-  /**
    * Constructs a new UpdateManagerInstall.
    *
    * @param string $root
    *   The app root.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
-   * @param string $site_path
-   *   The site path.
    */
-  public function __construct($root, ModuleHandlerInterface $module_handler, $site_path) {
+  public function __construct($root, ModuleHandlerInterface $module_handler) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
-    $this->sitePath = $site_path;
   }
 
   /**
@@ -69,8 +59,7 @@ public function getFormId() {
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('app.root'),
-      $container->get('module_handler'),
-      $container->get('site.path')
+      $container->get('module_handler')
     );
   }
 
@@ -228,7 +217,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     // install the code, there's no need to prompt for FTP/SSH credentials.
     // Instead, we instantiate a Drupal\Core\FileTransfer\Local and invoke
     // update_authorize_run_install() directly.
-    if (fileowner($project_real_location) == fileowner($this->sitePath)) {
+    if (fileowner($project_real_location) == fileowner(conf_path())) {
       $this->moduleHandler->loadInclude('update', 'inc', 'update.authorize');
       $filetransfer = new Local($this->root);
       call_user_func_array('update_authorize_run_install', array_merge(array($filetransfer), $arguments));
diff --git a/core/modules/update/src/Form/UpdateReady.php b/core/modules/update/src/Form/UpdateReady.php
index 1162c71..309229f 100644
--- a/core/modules/update/src/Form/UpdateReady.php
+++ b/core/modules/update/src/Form/UpdateReady.php
@@ -42,13 +42,6 @@ class UpdateReady extends FormBase {
   protected $state;
 
   /**
-   * The Site path.
-   *
-   * @var string
-   */
-   protected $sitePath;
-
-  /**
    * Constructs a new UpdateReady object.
    *
    * @param string $root
@@ -57,14 +50,11 @@ class UpdateReady extends FormBase {
    *   The object that manages enabled modules in a Drupal installation.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state key value store.
-   * @param string $site_path
-   *   The site path.
    */
-  public function __construct($root, ModuleHandlerInterface $module_handler, StateInterface $state, $site_path) {
+  public function __construct($root, ModuleHandlerInterface $module_handler, StateInterface $state) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->state = $state;
-    $this->sitePath = $site_path;
   }
 
   /**
@@ -81,8 +71,7 @@ public static function create(ContainerInterface $container) {
     return new static(
       $container->get('app.root'),
       $container->get('module_handler'),
-      $container->get('state'),
-      $container->get('site.path')
+      $container->get('state')
     );
   }
 
@@ -153,7 +142,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       // trying to install the code, there's no need to prompt for FTP/SSH
       // credentials. Instead, we instantiate a Drupal\Core\FileTransfer\Local
       // and invoke update_authorize_run_update() directly.
-      if (fileowner($project_real_location) == fileowner($this->sitePath)) {
+      if (fileowner($project_real_location) == fileowner(conf_path())) {
         $this->moduleHandler->loadInclude('update', 'inc', 'update.authorize');
         $filetransfer = new Local($this->root);
         update_authorize_run_update($filetransfer, $updates);
diff --git a/core/modules/update/src/Tests/UpdateContribTest.php b/core/modules/update/src/Tests/UpdateContribTest.php
index a18a547..8197944 100644
--- a/core/modules/update/src/Tests/UpdateContribTest.php
+++ b/core/modules/update/src/Tests/UpdateContribTest.php
@@ -341,9 +341,9 @@ function testUpdateBrokenFetchURL() {
     // It should say we failed to get data, not that we're missing an update.
     $this->assertNoText(t('Update available'));
 
-    // We need to check that this string is found as part of a project row, not
-    // just in the "Failed to get available update data" message at the top of
-    // the page.
+    // We need to check that this string is found as part of a project row,
+    // not just in the "Failed to get available update data for ..." message
+    // at the top of the page.
     $this->assertRaw('<div class="project-update__status">' . t('Failed to get available update data'));
 
     // We should see the output messages from fetching manually.
diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc
index af86a9f..7d9b9a2 100644
--- a/core/modules/update/update.manager.inc
+++ b/core/modules/update/update.manager.inc
@@ -306,8 +306,7 @@ function update_manager_local_transfers_allowed() {
   // the configuration directory to determine if local transfers will be
   // allowed.
   $temporary_file = drupal_tempnam('temporary://', 'update_');
-  $site_path = \Drupal::service('site.path');
-  $local_transfers_allowed = fileowner($temporary_file) === fileowner($site_path);
+  $local_transfers_allowed = fileowner($temporary_file) === fileowner(conf_path());
 
   // Clean up. If this fails, we can ignore it (since this is just a temporary
   // file anyway).
diff --git a/core/modules/update/update.module b/core/modules/update/update.module
index 4aed1ef..63ed8d0 100644
--- a/core/modules/update/update.module
+++ b/core/modules/update/update.module
@@ -574,7 +574,7 @@ function _update_project_status_sort($a, $b) {
  * @see theme_update_report()
  */
 function template_preprocess_update_last_check(&$variables) {
-  $variables['time'] = \Drupal::service('date.formatter')->formatTimeDiffSince($variables['last']);
+  $variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $variables['last']);
   $variables['link'] = \Drupal::l(t('Check manually'), new Url('update.manual_status', array(), array('query' => \Drupal::destination()->getAsArray())));
 }
 
diff --git a/core/modules/user/config/optional/views.view.user_admin_people.yml b/core/modules/user/config/optional/views.view.user_admin_people.yml
index 3ae6695..004471c 100644
--- a/core/modules/user/config/optional/views.view.user_admin_people.yml
+++ b/core/modules/user/config/optional/views.view.user_admin_people.yml
@@ -23,7 +23,7 @@ display:
         options:
           perm: 'administer users'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
         options:
@@ -741,44 +741,6 @@ display:
           plugin_id: boolean
           entity_type: user
           entity_field: status
-        default_langcode:
-          id: default_langcode
-          table: users_field_data
-          field: default_langcode
-          relationship: none
-          group_type: group
-          admin_label: ''
-          operator: '='
-          value: true
-          group: 1
-          exposed: false
-          expose:
-            operator_id: ''
-            label: ''
-            description: ''
-            use_operator: false
-            operator: ''
-            identifier: ''
-            required: false
-            remember: false
-            multiple: false
-            remember_roles:
-              authenticated: authenticated
-          is_grouped: false
-          group_info:
-            label: ''
-            description: ''
-            identifier: ''
-            optional: true
-            widget: select
-            multiple: false
-            remember: false
-            default_group: All
-            default_group_multiple: {  }
-            group_items: {  }
-          entity_type: user
-          entity_field: default_langcode
-          plugin_id: boolean
         uid_raw:
           id: uid_raw
           table: users_field_data
diff --git a/core/modules/user/config/optional/views.view.who_s_new.yml b/core/modules/user/config/optional/views.view.who_s_new.yml
index dc7cde7..7905b35 100644
--- a/core/modules/user/config/optional/views.view.who_s_new.yml
+++ b/core/modules/user/config/optional/views.view.who_s_new.yml
@@ -23,7 +23,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/user/config/optional/views.view.who_s_online.yml b/core/modules/user/config/optional/views.view.who_s_online.yml
index e48c0d3..d34de2a 100644
--- a/core/modules/user/config/optional/views.view.who_s_online.yml
+++ b/core/modules/user/config/optional/views.view.who_s_online.yml
@@ -23,7 +23,7 @@ display:
         options:
           perm: 'access user profiles'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/user/src/AccountSettingsForm.php b/core/modules/user/src/AccountSettingsForm.php
index 99b2a7a..df65cb8 100644
--- a/core/modules/user/src/AccountSettingsForm.php
+++ b/core/modules/user/src/AccountSettingsForm.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ModuleHandler;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -22,7 +22,7 @@ class AccountSettingsForm extends ConfigFormBase {
   /**
    * The module handler.
    *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   * @var \Drupal\Core\Extension\ModuleHandler
    */
   protected $moduleHandler;
 
@@ -38,12 +38,12 @@ class AccountSettingsForm extends ConfigFormBase {
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The factory for configuration objects.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   * @param \Drupal\Core\Extension\ModuleHandler $module_handler
    *   The module handler.
    * @param \Drupal\user\RoleStorageInterface $role_storage
    *   The role storage.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, RoleStorageInterface $role_storage) {
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandler $module_handler, RoleStorageInterface $role_storage) {
     parent::__construct($config_factory);
     $this->moduleHandler = $module_handler;
     $this->roleStorage = $role_storage;
diff --git a/core/modules/user/src/Form/UserMultipleCancelConfirm.php b/core/modules/user/src/Form/UserMultipleCancelConfirm.php
index 8386c9f..87e9e12 100644
--- a/core/modules/user/src/Form/UserMultipleCancelConfirm.php
+++ b/core/modules/user/src/Form/UserMultipleCancelConfirm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\user\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -108,27 +109,24 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       return $this->redirect('entity.user.collection');
     }
 
-    $root = NULL;
     $form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
-    foreach ($accounts as $account) {
-      $uid = $account->id();
+    foreach ($accounts as $uid => $account) {
       // Prevent user 1 from being canceled.
       if ($uid <= 1) {
-        $root = intval($uid) === 1 ? $account : $root;
         continue;
       }
       $form['accounts'][$uid] = array(
         '#type' => 'hidden',
         '#value' => $uid,
         '#prefix' => '<li>',
-        '#suffix' => $account->label() . "</li>\n",
+        '#suffix' => SafeMarkup::checkPlain($account->label()) . "</li>\n",
       );
     }
 
     // Output a notice that user 1 cannot be canceled.
-    if (isset($root)) {
+    if (isset($accounts[1])) {
       $redirect = (count($accounts) == 1);
-      $message = $this->t('The user account %name cannot be canceled.', array('%name' => $root->label()));
+      $message = $this->t('The user account %name cannot be canceled.', array('%name' => $accounts[1]->label()));
       drupal_set_message($message, $redirect ? 'error' : 'warning');
       // If only user 1 was selected, redirect to the overview.
       if ($redirect) {
diff --git a/core/modules/user/src/Plugin/views/access/Permission.php b/core/modules/user/src/Plugin/views/access/Permission.php
index 18f0275..4caab18 100644
--- a/core/modules/user/src/Plugin/views/access/Permission.php
+++ b/core/modules/user/src/Plugin/views/access/Permission.php
@@ -12,7 +12,6 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\user\PermissionHandlerInterface;
-use Drupal\views\Plugin\CacheablePluginInterface;
 use Drupal\views\Plugin\views\access\AccessPluginBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Routing\Route;
@@ -28,7 +27,7 @@
  *   help = @Translation("Access will be granted to users with the specified permission string.")
  * )
  */
-class Permission extends AccessPluginBase implements CacheablePluginInterface {
+class Permission extends AccessPluginBase {
 
   /**
    * Overrides Drupal\views\Plugin\Plugin::$usesOptions.
@@ -133,18 +132,4 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     );
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function isCacheable() {
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return ['user.permissions'];
-  }
-
 }
diff --git a/core/modules/user/src/Plugin/views/access/Role.php b/core/modules/user/src/Plugin/views/access/Role.php
index 9686d08..6a106de 100644
--- a/core/modules/user/src/Plugin/views/access/Role.php
+++ b/core/modules/user/src/Plugin/views/access/Role.php
@@ -10,7 +10,6 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\user\RoleStorageInterface;
-use Drupal\views\Plugin\CacheablePluginInterface;
 use Drupal\views\Plugin\views\access\AccessPluginBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Routing\Route;
@@ -27,7 +26,7 @@
  *   help = @Translation("Access will be granted to users with any of the specified roles.")
  * )
  */
-class Role extends AccessPluginBase implements CacheablePluginInterface {
+class Role extends AccessPluginBase {
 
   /**
    * Overrides Drupal\views\Plugin\Plugin::$usesOptions.
@@ -146,19 +145,4 @@ public function calculateDependencies() {
     return $dependencies;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function isCacheable() {
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return ['user.roles'];
-  }
-
 }
-
diff --git a/core/modules/user/src/Plugin/views/argument_default/User.php b/core/modules/user/src/Plugin/views/argument_default/User.php
index 16daae7..269be4e 100644
--- a/core/modules/user/src/Plugin/views/argument_default/User.php
+++ b/core/modules/user/src/Plugin/views/argument_default/User.php
@@ -103,6 +103,13 @@ public function getArgument() {
         return $node->getOwnerId();
       }
     }
+
+    // If the current page is a view that takes uid as an argument.
+    $view = views_get_page_view();
+
+    if ($view && isset($view->argument['uid'])) {
+      return $view->argument['uid']->argument;
+    }
   }
 
   /**
diff --git a/core/modules/user/src/Tests/UserAdminListingTest.php b/core/modules/user/src/Tests/UserAdminListingTest.php
index 76fc674..fbf3197 100644
--- a/core/modules/user/src/Tests/UserAdminListingTest.php
+++ b/core/modules/user/src/Tests/UserAdminListingTest.php
@@ -91,7 +91,7 @@ public function testUserListing() {
     $expected_roles = array('custom_role_1', 'custom_role_2');
     $this->assertEqual($result_accounts[$role_account_name]['roles'], $expected_roles, 'Ensure roles are listed properly.');
 
-    $this->assertEqual($result_accounts[$timestamp_user]['member_for'], \Drupal::service('date.formatter')->formatTimeDiffSince($accounts[$timestamp_user]->created->value), 'Ensure the right member time is displayed.');
+    $this->assertEqual($result_accounts[$timestamp_user]['member_for'], \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $accounts[$timestamp_user]->created->value), 'Ensure the right member time is displayed.');
   }
 
 }
diff --git a/core/modules/user/src/Tests/UserFieldsTest.php b/core/modules/user/src/Tests/UserFieldsTest.php
deleted file mode 100644
index 50564d0..0000000
--- a/core/modules/user/src/Tests/UserFieldsTest.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Tests\UserFieldsTest.
- */
-
-namespace Drupal\user\Tests;
-
-use Drupal\user\Entity\User;
-use Drupal\simpletest\KernelTestBase;
-
-/**
- * Tests available user fields in twig.
- *
- * @group user
- */
-class UserFieldsTest extends KernelTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['user', 'system'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->installEntitySchema('user');
-
-    // Set up a test theme that prints the user's mail field.
-    \Drupal::service('theme_handler')->install(array('user_test_theme'));
-    \Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('user_test_theme'));
-    // Clear the theme registry.
-    $this->container->set('theme.registry', NULL);
-  }
-
-  /**
-   * Tests account's available fields.
-   */
-  function testUserFields() {
-    // Create the user to test the user fields.
-    $user = User::create([
-      'name' => 'foobar',
-      'mail' => 'foobar@example.com',
-    ]);
-    $build = user_view($user);
-    $output = \Drupal::service('renderer')->render($build);
-    $this->setRawContent($output);
-    $userEmail = $user->getEmail();
-    $this->assertText($userEmail, "User's mail field is found in the twig template");
-  }
-
-}
diff --git a/core/modules/user/src/Tests/Views/AccessPermissionTest.php b/core/modules/user/src/Tests/Views/AccessPermissionTest.php
index 3e77e2a..aaa1daf 100644
--- a/core/modules/user/src/Tests/Views/AccessPermissionTest.php
+++ b/core/modules/user/src/Tests/Views/AccessPermissionTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\user\Tests\Views;
 
 use Drupal\user\Plugin\views\access\Permission;
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Views;
 
 /**
@@ -41,32 +40,4 @@ function testAccessPerm() {
     $this->assertTrue($view->display_handler->access($this->normalUser));
   }
 
-  /**
-   * Tests access on render caching.
-   */
-  public function testRenderCaching() {
-    $view = Views::getView('test_access_perm');
-    $display = &$view->storage->getDisplay('default');
-    $display['display_options']['cache'] = [
-      'type' => 'tag',
-    ];
-
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    /** @var \Drupal\Core\Session\AccountSwitcherInterface $account_switcher */
-    $account_switcher = \Drupal::service('account_switcher');
-
-    // First access as user without access.
-    $build = DisplayPluginBase::buildBasicRenderable('test_access_perm', 'default');
-    $account_switcher->switchTo($this->normalUser);
-    $result = $renderer->renderPlain($build);
-    $this->assertNotEqual($result, '');
-
-    // Then with access.
-    $build = DisplayPluginBase::buildBasicRenderable('test_access_perm', 'default');
-    $account_switcher->switchTo($this->webUser);
-    $result = $renderer->renderPlain($build);
-    $this->assertEqual($result, '');
-  }
-
 }
diff --git a/core/modules/user/src/Tests/Views/AccessRoleTest.php b/core/modules/user/src/Tests/Views/AccessRoleTest.php
index efca3e2..f79e86e 100644
--- a/core/modules/user/src/Tests/Views/AccessRoleTest.php
+++ b/core/modules/user/src/Tests/Views/AccessRoleTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\user\Tests\Views;
 
 use Drupal\user\Plugin\views\access\Role;
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Views;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -93,37 +92,4 @@ function testAccessRole() {
     $this->assertResponse(200);
   }
 
-  /**
-   * Tests access on render caching.
-   */
-  public function testRenderCaching() {
-    $view = Views::getView('test_access_role');
-    $display = &$view->storage->getDisplay('default');
-    $display['display_options']['cache'] = [
-      'type' => 'tag',
-    ];
-    $display['display_options']['access']['options']['role'] = array(
-      $this->normalRole => $this->normalRole,
-    );
-    $view->save();
-
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    /** @var \Drupal\Core\Session\AccountSwitcherInterface $account_switcher */
-    $account_switcher = \Drupal::service('account_switcher');
-
-
-    // First access as user without access.
-    $build = DisplayPluginBase::buildBasicRenderable('test_access_role', 'default');
-    $account_switcher->switchTo($this->normalUser);
-    $result = $renderer->renderPlain($build);
-    $this->assertNotEqual($result, '');
-
-    // Then with access.
-    $build = DisplayPluginBase::buildBasicRenderable('test_access_role', 'default');
-    $account_switcher->switchTo($this->webUser);
-    $result = $renderer->renderPlain($build);
-    $this->assertEqual($result, '');
-  }
-
 }
diff --git a/core/modules/user/src/UserListBuilder.php b/core/modules/user/src/UserListBuilder.php
index 7575b86..fc7daee 100644
--- a/core/modules/user/src/UserListBuilder.php
+++ b/core/modules/user/src/UserListBuilder.php
@@ -151,8 +151,10 @@ public function buildRow(EntityInterface $entity) {
       '#theme' => 'item_list',
       '#items' => $users_roles,
     );
-    $row['member_for'] = $this->dateFormatter->formatTimeDiffSince($entity->getCreatedTime());
-    $row['access'] = $entity->access ? $this->t('@time ago', array('@time' => $this->dateFormatter->formatTimeDiffSince($entity->getLastAccessedTime()))) : t('never');
+    $row['member_for'] = $this->dateFormatter->formatInterval(REQUEST_TIME - $entity->getCreatedTime());
+    $row['access'] = $entity->access ? $this->t('@time ago', array(
+      '@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $entity->getLastAccessedTime()),
+    )) : t('never');
     return $row + parent::buildRow($entity);
   }
 
diff --git a/core/modules/user/templates/user.html.twig b/core/modules/user/templates/user.html.twig
index 45c4ea0..b00a744 100644
--- a/core/modules/user/templates/user.html.twig
+++ b/core/modules/user/templates/user.html.twig
@@ -17,7 +17,6 @@
  *   e.g. account.field_example.en, thus overriding any language negotiation
  *   rule that was previously applied.
  * - attributes: HTML attributes for the container element.
- * - user: A Drupal User entity.
  *
  * @see template_preprocess_user()
  *
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_perm.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_perm.yml
index 7862066..a5c11e8 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_perm.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_perm.yml
@@ -19,7 +19,7 @@ display:
         options:
           perm: 'views_test_data test permission'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml
index f07b429..f089b5e 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml
@@ -23,7 +23,7 @@ display:
       access:
         type: role
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml
index 04948cd..7ddb9d2 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml
index a389464..53c2355 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml
index 789dffe..99db821 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml
@@ -20,7 +20,7 @@ display:
           perm: 'access user profiles'
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml
index a080e26..4c8c708 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml
@@ -26,7 +26,7 @@ display:
           table: views
           plugin_id: 'null'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml
index 65c9899..d929079 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_changed.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_data.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_data.yml
index c33be6f..9bdb32a 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_data.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_data.yml
@@ -23,7 +23,7 @@ display:
         options:
           perm: 'access user profiles'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_name.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_name.yml
index 55b5d1a..33706cd 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_name.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_name.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml
index 6926bb1..7e44245 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_user.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_user.yml
index 60f9bf8..fe9b4f5 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_user.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_user.yml
@@ -25,7 +25,7 @@ display:
             type: 'entity:user'
           plugin_id: 'null'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_username.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_username.yml
index d7fc245..b3b962f 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_username.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_view_argument_validate_username.yml
@@ -25,7 +25,7 @@ display:
             type: user_name
           plugin_id: 'null'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml
index 9e72554..7cfbca9 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml
@@ -23,7 +23,7 @@ display:
         options:
           perm: 'access user profiles'
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml
index 13f5959..c0c3e94 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php b/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php
index 8eb26d8..0eefa5a 100644
--- a/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php
+++ b/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php
@@ -57,8 +57,6 @@ public function testConstructor() {
       ->with('action')
       ->will($this->returnValue($entity_storage));
 
-    $language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
-
     $views_data = $this->getMockBuilder('Drupal\views\ViewsData')
       ->disableOriginalConstructor()
       ->getMock();
@@ -89,7 +87,7 @@ public function testConstructor() {
     $definition['title'] = '';
     $options = array();
 
-    $user_bulk_form = new UserBulkForm(array(), 'user_bulk_form', $definition, $entity_manager, $language_manager);
+    $user_bulk_form = new UserBulkForm(array(), 'user_bulk_form', $definition, $entity_manager);
     $user_bulk_form->init($executable, $display, $options);
 
     $this->assertAttributeEquals(array_slice($actions, 0, -1, TRUE), 'actions', $user_bulk_form);
diff --git a/core/modules/user/tests/themes/user_test_theme/user.html.twig b/core/modules/user/tests/themes/user_test_theme/user.html.twig
deleted file mode 100644
index 715a79e..0000000
--- a/core/modules/user/tests/themes/user_test_theme/user.html.twig
+++ /dev/null
@@ -1,32 +0,0 @@
-{#
-/**
- * @file
- * Theme override for testing the presence of all user data.
- *
- * This template is used when viewing a registered user's page,
- * e.g., example.com/user/123. 123 being the user's ID.
- *
- * Available variables:
- * - content: A list of content items. Use 'content' to print all content, or
- *   print a subset such as 'content.field_example'.
- * - Field variables: For each field attached to the user a corresponding
- *   variable is defined; e.g., account.field_example has a variable
- *   'field_example' defined. When needing to access a field's raw values,
- *   developers/themers are strongly encouraged to use these variables.
- *   Otherwise they will have to explicitly specify the desired field language,
- *   e.g. account.field_example.en, thus overriding any language negotiation
- *   rule that was previously applied.
- * - attributes: HTML attributes for the container element.
- * - user: A Drupal User entity.
- *
- * @see template_preprocess_user()
- */
-#}
-<article{{ attributes.addClass('profile') }}>
-  {% if content %}
-    {{ content }}
-  {% endif %}
-  {% if user %}
-    <p>{{ user.mail.value }}</p>
-  {% endif  %}
-</article>
diff --git a/core/modules/user/tests/themes/user_test_theme/user_test_theme.info.yml b/core/modules/user/tests/themes/user_test_theme/user_test_theme.info.yml
deleted file mode 100644
index 79a62e8..0000000
--- a/core/modules/user/tests/themes/user_test_theme/user_test_theme.info.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-name: 'User Test theme'
-type: theme
-description: 'Theme for testing the available fields in user twig template'
-version: VERSION
-core: 8.x
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 1d59201..1e6de88 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -370,7 +370,7 @@ function user_user_view(array &$build, UserInterface $account, EntityViewDisplay
   if ($display->getComponent('member_for')) {
     $build['member_for'] = array(
       '#type' => 'item',
-      '#markup' => '<h4 class="label">' . t('Member for') . '</h4> ' . \Drupal::service('date.formatter')->formatTimeDiffSince($account->getCreatedTime()),
+      '#markup' => '<h4 class="label">' . t('Member for') . '</h4> ' . \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $account->getCreatedTime()),
     );
   }
 }
@@ -883,7 +883,7 @@ function user_view($account, $view_mode = 'full', $langcode = NULL) {
  * @param \Drupal\user\UserInterface[] $account
  *   An array of user accounts as returned by User::loadMultiple().
  * @param string $view_mode
- *   (optional) View mode, e.g., 'full', 'teaser', etc. Defaults to 'teaser.'
+ *   (optional) View mode, e.g., 'full', 'teaser'... Defaults to 'teaser'.
  * @param string|null $langcode
  *   (optional) A language code to use for rendering. Defaults to the global
  *   content language of the current request.
@@ -1428,7 +1428,6 @@ function user_logout() {
  *   - attributes: HTML attributes for the containing element.
  */
 function template_preprocess_user(&$variables) {
-  $variables['user'] = $variables['elements']['#user'];
   // Helpful $content variable for templates.
   foreach (Element::children($variables['elements']) as $key) {
     $variables['content'][$key] = $variables['elements'][$key];
diff --git a/core/modules/views/src/Element/View.php b/core/modules/views/src/Element/View.php
index 676f6d0..9c11d3b 100644
--- a/core/modules/views/src/Element/View.php
+++ b/core/modules/views/src/Element/View.php
@@ -23,6 +23,7 @@ class View extends RenderElement {
   public function getInfo() {
     $class = get_class($this);
     return array(
+      '#theme_wrappers' => array('container'),
       '#pre_render' => array(
         array($class, 'preRenderViewElement'),
       ),
@@ -30,7 +31,6 @@ public function getInfo() {
       '#display_id' => 'default',
       '#arguments' => array(),
       '#embed' => TRUE,
-      '#cache' => [],
     );
   }
 
@@ -38,6 +38,8 @@ public function getInfo() {
    * View element pre render callback.
    */
   public static function preRenderViewElement($element) {
+    $element['#attributes']['class'][] = 'views-element-container';
+
     if (!isset($element['#view'])) {
       $view = Views::getView($element['#name']);
     }
@@ -45,17 +47,6 @@ public static function preRenderViewElement($element) {
       $view = $element['#view'];
     }
 
-    $view->element = &$element;
-    // Mark the element as being prerendered, so other code like
-    // \Drupal\views\ViewExecutable::setCurrentPage knows that its no longer
-    // possible to manipulate the $element.
-    $view->element['#pre_rendered'] = TRUE;
-
-
-    if (isset($element['#response'])) {
-      $view->setResponse($element['#response']);
-    }
-
     if ($view && $view->access($element['#display_id'])) {
       if (!empty($element['#embed'])) {
         $element += $view->preview($element['#display_id'], $element['#arguments']);
@@ -79,18 +70,7 @@ public static function preRenderViewElement($element) {
           $element['#title'] = &$element['view_build']['#title'];
         }
 
-        if (empty($view->display_handler->getPluginDefinition()['returns_response'])) {
-          // views_add_contextual_links() needs the following information in
-          // order to be attached to the view.
-          $element['#view_id'] = $view->storage->id();
-          $element['#view_display_show_admin_links'] = $view->getShowAdminLinks();
-          $element['#view_display_plugin_id'] = $view->display_handler->getPluginId();
-          views_add_contextual_links($element, 'view', $view->current_display);
-        }
-      }
-      if (empty($view->display_handler->getPluginDefinition()['returns_response'])) {
-        $element['#attributes']['class'][] = 'views-element-container';
-        $element['#theme_wrappers'] = array('container');
+        views_add_contextual_links($element, 'view', $view, $view->current_display);
       }
     }
 
diff --git a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
index b00a572..8865a5f 100644
--- a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
+++ b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
@@ -263,4 +263,24 @@ protected function getRenderableFieldIds() {
     return $field_ids;
   }
 
+  /**
+   * Returns the entity translation matching the configured row language.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity object the field value being processed is attached to.
+   * @param \Drupal\views\ResultRow $row
+   *   The result row the field value being processed belongs to.
+   *
+   * @return \Drupal\Core\Entity\FieldableEntityInterface
+   *   The entity translation object for the specified row.
+   */
+  public function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
+    // We assume the same language should be used for all entity fields
+    // belonging to a single row, even if they are attached to different entity
+    // types. Below we apply language fallback to ensure a valid value is always
+    // picked.
+    $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
+    return $this->entityManager->getTranslationFromContext($entity, $langcode);
+  }
+
 }
diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
index 7f9f44c..f874c75 100644
--- a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
+++ b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
@@ -7,10 +7,7 @@
 
 namespace Drupal\views\Entity\Render;
 
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\views\Plugin\views\PluginBase;
-use Drupal\views\ResultRow;
 
 /**
  * Trait used to instantiate the view's entity translation renderer.
@@ -61,30 +58,6 @@ protected function getEntityTranslationRenderer() {
   }
 
   /**
-   * Returns the entity translation matching the configured row language.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity object the field value being processed is attached to.
-   * @param \Drupal\views\ResultRow $row
-   *   The result row the field value being processed belongs to.
-   *
-   * @return \Drupal\Core\Entity\FieldableEntityInterface
-   *   The entity translation object for the specified row.
-   */
-  public function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
-    // We assume the same language should be used for all entity fields
-    // belonging to a single row, even if they are attached to different entity
-    // types. Below we apply language fallback to ensure a valid value is always
-    // picked.
-    $translation = $entity;
-    if ($entity instanceof TranslatableInterface && count($entity->getTranslationLanguages()) > 1) {
-      $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
-      $translation = $this->getEntityManager()->getTranslationFromContext($entity, $langcode);
-    }
-    return $translation;
-  }
-
-  /**
    * Returns the entity type identifier.
    *
    * @return string
diff --git a/core/modules/views/src/EventSubscriber/RouteSubscriber.php b/core/modules/views/src/EventSubscriber/RouteSubscriber.php
index db07140..abc5bb6 100644
--- a/core/modules/views/src/EventSubscriber/RouteSubscriber.php
+++ b/core/modules/views/src/EventSubscriber/RouteSubscriber.php
@@ -101,8 +101,9 @@ protected function getViewsDisplayIDsWithRoute() {
       // @todo Convert this method to some service.
       $views = $this->getApplicableViews();
       foreach ($views as $data) {
-        list($view_id, $display_id) = $data;
-        $this->viewsDisplayPairs[] = $view_id . '.' . $display_id;
+        list($view, $display_id) = $data;
+        $id = $view->storage->id();
+        $this->viewsDisplayPairs[] = $id . '.' . $display_id;
       }
       $this->viewsDisplayPairs = array_combine($this->viewsDisplayPairs, $this->viewsDisplayPairs);
     }
diff --git a/core/modules/views/src/Form/ViewsForm.php b/core/modules/views/src/Form/ViewsForm.php
index 39ff499..8a9a3e6 100644
--- a/core/modules/views/src/Form/ViewsForm.php
+++ b/core/modules/views/src/Form/ViewsForm.php
@@ -130,8 +130,7 @@ public function buildForm(array $form, FormStateInterface $form_state, ViewExecu
 
     $options = array('query' => $query);
     $form['#action'] = $view->hasUrl() ? $view->getUrl()->setOptions($options)->toString() : Url::fromRoute('<current>')->setOptions($options)->toString();
-    // Tell the preprocessor whether it should hide the header, footer, pager,
-    // etc.
+    // Tell the preprocessor whether it should hide the header, footer, pager...
     $form['show_view_elements'] = array(
       '#type' => 'value',
       '#value' => ($step == 'views_form_views_form') ? TRUE : FALSE,
diff --git a/core/modules/views/src/Plugin/Block/ViewsBlock.php b/core/modules/views/src/Plugin/Block/ViewsBlock.php
index 8762c32..1e25133 100644
--- a/core/modules/views/src/Plugin/Block/ViewsBlock.php
+++ b/core/modules/views/src/Plugin/Block/ViewsBlock.php
@@ -29,7 +29,7 @@ class ViewsBlock extends ViewsBlockBase {
   public function build() {
     $this->view->display_handler->preBlockBuild($this);
 
-    if ($output = $this->view->buildRenderable($this->displayID, [], FALSE)) {
+    if ($output = $this->view->buildRenderable($this->displayID)) {
       // Override the label to the dynamic title configured in the view.
       if (empty($this->configuration['views_label']) && $this->view->getTitle()) {
         $output['#title'] = Xss::filterAdmin($this->view->getTitle());
diff --git a/core/modules/views/src/Plugin/Block/ViewsBlockBase.php b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
index d79e4eb..b87711f 100644
--- a/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
+++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
@@ -201,13 +201,8 @@ protected function addContextualLinks(&$output, $block_type = 'block') {
       if (is_string($output)) {
         $output = array('#markup' => $output);
       }
-
-      // views_add_contextual_links() needs the following information in
-      // order to be attached to the view.
-      $output['#view_id'] = $this->view->storage->id();
-      $output['#view_display_show_admin_links'] = $this->view->getShowAdminLinks();
-      $output['#view_display_plugin_id'] = $this->view->display_handler->getPluginId();
-      views_add_contextual_links($output, $block_type, $this->displayID);
+      // Add the contextual links.
+      views_add_contextual_links($output, $block_type, $this->view, $this->displayID);
     }
   }
 
diff --git a/core/modules/views/src/Plugin/Derivative/ViewsLocalTask.php b/core/modules/views/src/Plugin/Derivative/ViewsLocalTask.php
index 343dc76..434a503 100644
--- a/core/modules/views/src/Plugin/Derivative/ViewsLocalTask.php
+++ b/core/modules/views/src/Plugin/Derivative/ViewsLocalTask.php
@@ -7,12 +7,10 @@
 
 namespace Drupal\views\Plugin\Derivative;
 
-use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Component\Plugin\Derivative\DeriverBase;
 use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
-use Drupal\views\ViewEntityInterface;
 use Drupal\views\Views;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -36,26 +34,16 @@ class ViewsLocalTask extends DeriverBase implements ContainerDeriverInterface {
   protected $state;
 
   /**
-   * The view storage.
-   *
-   * @var \Drupal\Core\Entity\EntityStorageInterface
-   */
-  protected $viewStorage;
-
-  /**
    * Constructs a \Drupal\views\Plugin\Derivative\ViewsLocalTask instance.
    *
    * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
    *   The route provider.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state key value store.
-   * @param \Drupal\Core\Entity\EntityStorageInterface $view_storage
-   *   The view storage.
    */
-  public function __construct(RouteProviderInterface $route_provider, StateInterface $state, EntityStorageInterface $view_storage) {
+  public function __construct(RouteProviderInterface $route_provider, StateInterface $state) {
     $this->routeProvider = $route_provider;
     $this->state = $state;
-    $this->viewStorage = $view_storage;
   }
 
   /**
@@ -64,8 +52,7 @@ public function __construct(RouteProviderInterface $route_provider, StateInterfa
   public static function create(ContainerInterface $container, $base_plugin_id) {
     return new static(
       $container->get('router.route_provider'),
-      $container->get('state'),
-      $container->get('entity.manager')->getStorage('view')
+      $container->get('state')
     );
   }
 
@@ -78,8 +65,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
     $view_route_names = $this->state->get('views.view_route_names');
     foreach ($this->getApplicableMenuViews() as $pair) {
       /** @var $executable \Drupal\views\ViewExecutable */
-      list($view_id, $display_id) = $pair;
-      $executable = $this->viewStorage->load($view_id)->getExecutable();
+      list($executable, $display_id) = $pair;
 
       $executable->setDisplay($display_id);
       $menu = $executable->display_handler->getOption('menu');
@@ -115,9 +101,8 @@ public function alterLocalTasks(&$local_tasks) {
     $view_route_names = $this->state->get('views.view_route_names');
 
     foreach ($this->getApplicableMenuViews() as $pair) {
-      list($view_id, $display_id) = $pair;
       /** @var $executable \Drupal\views\ViewExecutable */
-      $executable = $this->viewStorage->load($view_id)->getExecutable();
+      list($executable, $display_id) = $pair;
 
       $executable->setDisplay($display_id);
       $menu = $executable->display_handler->getOption('menu');
diff --git a/core/modules/views/src/Plugin/Derivative/ViewsMenuLink.php b/core/modules/views/src/Plugin/Derivative/ViewsMenuLink.php
index 27bf9cc..06b1725 100644
--- a/core/modules/views/src/Plugin/Derivative/ViewsMenuLink.php
+++ b/core/modules/views/src/Plugin/Derivative/ViewsMenuLink.php
@@ -8,43 +8,14 @@
 namespace Drupal\views\Plugin\Derivative;
 
 use Drupal\Component\Plugin\Derivative\DeriverBase;
-use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
 use Drupal\views\Views;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides menu links for Views.
  *
  * @see \Drupal\views\Plugin\Menu\ViewsMenuLink
  */
-class ViewsMenuLink extends DeriverBase implements ContainerDeriverInterface {
-
-  /**
-   * The view storage.
-   *
-   * @var \Drupal\Core\Entity\EntityStorageInterface
-   */
-  protected $viewStorage;
-
-  /**
-   * Constructs a \Drupal\views\Plugin\Derivative\ViewsLocalTask instance.
-   *
-   * @param \Drupal\Core\Entity\EntityStorageInterface $view_storage
-   *   The view storage.
-   */
-  public function __construct(EntityStorageInterface $view_storage) {
-    $this->viewStorage = $view_storage;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, $base_plugin_id) {
-    return new static(
-      $container->get('entity.manager')->getStorage('view')
-    );
-  }
+class ViewsMenuLink extends DeriverBase {
 
   /**
    * {@inheritdoc}
@@ -52,13 +23,10 @@ public static function create(ContainerInterface $container, $base_plugin_id) {
   public function getDerivativeDefinitions($base_plugin_definition) {
     $links = array();
     $views = Views::getApplicableViews('uses_menu_links');
-
     foreach ($views as $data) {
-      list($view_id, $display_id) = $data;
-      /** @var \Drupal\views\ViewExecutable $executable */
-      $executable = $this->viewStorage->load($view_id)->getExecutable();
-
-      if ($result = $executable->getMenuLinks($display_id)) {
+      /** @var \Drupal\views\ViewExecutable $view */
+      list($view, $display_id) = $data;
+      if ($result = $view->getMenuLinks($display_id)) {
         foreach ($result as $link_id => $link) {
           $links[$link_id] = $link + $base_plugin_definition;
         }
diff --git a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
index 7b4d424..bcff63b 100644
--- a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
+++ b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
@@ -107,15 +107,13 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
     // Filter views that list the entity type we want, and group the separate
     // displays by view.
     $entity_type = $this->entityManager->getDefinition($this->configuration['target_type']);
-    $view_storage = $this->entityManager->getStorage('view');
-
     $options = array();
     foreach ($displays as $data) {
-      list($view_id, $display_id) = $data;
-      $view = $view_storage->load($view_id);
-      if (in_array($view->get('base_table'), [$entity_type->getBaseTable(), $entity_type->getDataTable()])) {
-        $display = $view->get('display');
-        $options[$view_id . ':' . $display_id] = $view_id . ' - ' . $display[$display_id]['display_title'];
+      list($view, $display_id) = $data;
+      if (in_array($view->storage->get('base_table'), [$entity_type->getBaseTable(), $entity_type->getDataTable()])) {
+        $name = $view->storage->get('id');
+        $display = $view->storage->get('display');
+        $options[$name . ':' . $display_id] = $name . ' - ' . $display[$display_id]['display_title'];
       }
     }
 
diff --git a/core/modules/views/src/Plugin/views/area/Result.php b/core/modules/views/src/Plugin/views/area/Result.php
index 52ce7f2..5852c16 100644
--- a/core/modules/views/src/Plugin/views/area/Result.php
+++ b/core/modules/views/src/Plugin/views/area/Result.php
@@ -84,6 +84,7 @@ public function render($empty = FALSE) {
     // Calculate the page totals.
     $current_page = (int) $this->view->getCurrentPage() + 1;
     $per_page = (int) $this->view->getItemsPerPage();
+    $count = count($this->view->result);
     // @TODO: Maybe use a possible is views empty functionality.
     // Not every view has total_rows set, use view->result instead.
     $total = isset($this->view->total_rows) ? $this->view->total_rows : count($this->view->result);
diff --git a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php
index d49737c..2285c53 100644
--- a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php
+++ b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php
@@ -41,6 +41,13 @@
   var $storage = array();
 
   /**
+   * Which cache bin to store the rendered output in.
+   *
+   * @var string
+   */
+  protected $outputBin = 'render';
+
+  /**
    * Which cache bin to store query results in.
    *
    * @var string
@@ -59,6 +66,16 @@
   protected $resultsKey;
 
   /**
+   * Stores the cache ID used for the output cache, once generateOutputKey() got
+   * executed.
+   *
+   * @var string
+   *
+   * @see \Drupal\views\Plugin\views\cache\CachePluginBase::generateOutputKey()
+   */
+  protected $outputKey;
+
+  /**
    * The HTML renderer.
    *
    * @var \Drupal\Core\Render\RendererInterface
@@ -107,6 +124,16 @@ public static function create(ContainerInterface $container, array $configuratio
   }
 
   /**
+   * Returns the outputKey property.
+   *
+   * @return string
+   *   The outputKey property.
+   */
+  public function getOutputKey() {
+    return $this->outputKey;
+  }
+
+  /**
    * Returns the resultsKey property.
    *
    * @return string
@@ -130,7 +157,7 @@ public function summaryTitle() {
    * Plugins must override this to implement expiration.
    *
    * @param $type
-   *   The cache type, either 'query', 'result'.
+   *   The cache type, either 'query', 'result' or 'output'.
    */
   protected function cacheExpire($type) {
   }
@@ -142,9 +169,9 @@ protected function cacheExpire($type) {
    * Plugins must override this to implement expiration in the cache table.
    *
    * @param $type
-   *   The cache type, either 'query', 'result'.
+   *   The cache type, either 'query', 'result' or 'output'.
    */
-  protected function cacheSetMaxAge($type) {
+  protected function cacheSetExpire($type) {
     return Cache::PERMANENT;
   }
 
@@ -164,8 +191,20 @@ public function cacheSet($type) {
           'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0,
           'current_page' => $this->view->getCurrentPage(),
         );
-        $expire = ($this->cacheSetMaxAge($type) === Cache::PERMANENT) ? Cache::PERMANENT : (int) $this->view->getRequest()->server->get('REQUEST_TIME') + $this->cacheSetMaxAge($type);
-        \Drupal::cache($this->resultsBin)->set($this->generateResultsKey(), $data, $expire, $this->getCacheTags());
+        \Drupal::cache($this->resultsBin)->set($this->generateResultsKey(), $data, $this->cacheSetExpire($type), $this->getCacheTags());
+        break;
+      case 'output':
+        // Make a copy of the output so it is not modified. If we render the
+        // display output directly an empty string will be returned when the
+        // view is actually rendered. If we try to set '#printed' to FALSE there
+        // are problems with asset bubbling.
+        $output = $this->view->display_handler->output;
+        $this->renderer->render($output);
+        // Also assign the cacheable render array back to the display handler so
+        // that is used to render the view for this request and rendering does
+        // not happen twice.
+        $this->storage = $this->view->display_handler->output = $this->renderCache->getCacheableRenderArray($output);
+        \Drupal::cache($this->outputBin)->set($this->generateOutputKey(), $this->storage, $this->cacheSetExpire($type), Cache::mergeTags($this->storage['#cache']['tags'], ['rendered']));
         break;
     }
   }
@@ -196,6 +235,17 @@ public function cacheGet($type) {
           }
         }
         return FALSE;
+      case 'output':
+        if ($cache = \Drupal::cache($this->outputBin)->get($this->generateOutputKey())) {
+          if (!$cutoff || $cache->created > $cutoff) {
+            $this->storage = $cache->data;
+            $this->view->display_handler->output = $this->storage;
+            $this->view->element['#attached'] = &$this->view->display_handler->output['#attached'];
+            $this->view->element['#cache']['tags'] = &$this->view->display_handler->output['#cache']['tags'];
+            return TRUE;
+          }
+        }
+        return FALSE;
     }
   }
 
@@ -229,6 +279,11 @@ public function cacheFlush() {
   public function postRender(&$output) { }
 
   /**
+   * Start caching the html head.
+   */
+  public function cacheStart() { }
+
+  /**
    * Calculates and sets a cache ID used for the result cache.
    *
    * @return string
@@ -270,6 +325,30 @@ public function generateResultsKey() {
   }
 
   /**
+   * Calculates and sets a cache ID used for the output cache.
+   *
+   * @return string
+   *   The generated cache ID.
+   */
+  public function generateOutputKey() {
+    if (!isset($this->outputKey)) {
+      $user = \Drupal::currentUser();
+      $key_data = array(
+        'result' => $this->view->result,
+        'roles' => $user->getRoles(),
+        'super-user' => $user->id() == 1, // special caching for super user.
+        'theme' => \Drupal::theme()->getActiveTheme()->getName(),
+        'langcode' => \Drupal::languageManager()->getCurrentLanguage()->getId(),
+        'base_url' => $GLOBALS['base_url'],
+      );
+
+      $this->outputKey = $this->view->storage->id() . ':' . $this->displayHandler->display['id'] . ':output:' . hash('sha256', serialize($key_data));
+    }
+
+    return $this->outputKey;
+  }
+
+  /**
    * Gets an array of cache tags for the current view.
    *
    * @return string[]
@@ -279,7 +358,7 @@ public function getCacheTags() {
     $tags = $this->view->storage->getCacheTags();
 
     // The list cache tags for the entity types listed in this view.
-    $entity_information = $this->view->getQuery()->getEntityTableInfo();
+    $entity_information = $this->view->query->getEntityTableInfo();
 
     if (!empty($entity_information)) {
       // Add the list cache tags for each entity type used by this view.
diff --git a/core/modules/views/src/Plugin/views/cache/None.php b/core/modules/views/src/Plugin/views/cache/None.php
index 863cfe3..4ef83b5 100644
--- a/core/modules/views/src/Plugin/views/cache/None.php
+++ b/core/modules/views/src/Plugin/views/cache/None.php
@@ -20,6 +20,9 @@
  */
 class None extends CachePluginBase {
 
+  public function cacheStart() {
+  }
+
   public function summaryTitle() {
     return $this->t('None');
   }
diff --git a/core/modules/views/src/Plugin/views/cache/Time.php b/core/modules/views/src/Plugin/views/cache/Time.php
index 3925815..37c6cdd 100644
--- a/core/modules/views/src/Plugin/views/cache/Time.php
+++ b/core/modules/views/src/Plugin/views/cache/Time.php
@@ -101,7 +101,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     parent::buildOptionsForm($form, $form_state);
     $options = array(60, 300, 1800, 3600, 21600, 518400);
     $options = array_map(array($this->dateFormatter, 'formatInterval'), array_combine($options, $options));
-    $options = array(0 => $this->t('Never cache')) + $options + array('custom' => $this->t('Custom'));
+    $options = array(-1 => $this->t('Never cache')) + $options + array('custom' => $this->t('Custom'));
 
     $form['results_lifespan'] = array(
       '#type' => 'select',
@@ -177,13 +177,10 @@ protected function cacheExpire($type) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function cacheSetMaxAge($type) {
+  protected function cacheSetExpire($type) {
     $lifespan = $this->getLifespan($type);
     if ($lifespan) {
-      return $lifespan;
+      return time() + $lifespan;
     }
     else {
       return Cache::PERMANENT;
@@ -196,7 +193,7 @@ protected function cacheSetMaxAge($type) {
   protected function getDefaultCacheMaxAge() {
     // The max age, unless overridden by some other piece of the rendered code
     // is determined by the output time setting.
-    return (int) $this->cacheSetMaxAge('output');
+    return $this->cacheSetExpire('output');
   }
 
 }
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 3245bd2..8204bef 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -12,7 +12,6 @@
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Plugin\PluginDependencyTrait;
@@ -561,7 +560,7 @@ protected function defineOptions() {
       ),
       'cache' => array(
         'contains' => array(
-          'type' => array('default' => 'tag'),
+          'type' => array('default' => 'none'),
           'options' => array('default' => array()),
         ),
         'merge_defaults' => array($this, 'mergePlugin'),
@@ -2133,32 +2132,22 @@ public function render() {
       // Assigned by reference so anything added in $element['#attached'] will
       // be available on the view.
       '#attached' => &$this->view->element['#attached'],
+      '#cache' => &$this->view->element['#cache'],
     );
 
-    $this->applyDisplayCachablityMetadata($this->view->element);
+    if (!isset($element['#cache'])) {
+      $element['#cache'] = [];
+    }
+    $element['#cache'] += ['tags' => []];
+
+    // If the output is a render array, add cache tags, regardless of whether
+    // caching is enabled or not; cache tags must always be set.
+    $element['#cache']['tags'] = Cache::mergeTags($element['#cache']['tags'], $this->view->getCacheTags());
 
     return $element;
   }
 
   /**
-   * Applies the cacheability of the current display to the given render array.
-   *
-   * @param array $element
-   *   The render array with updated cacheability metadata.
-   */
-  protected function applyDisplayCachablityMetadata(array &$element) {
-    /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
-    $cache = $this->getPlugin('cache');
-
-    (new CacheableMetadata())
-      ->setCacheTags($this->view->getCacheTags())
-      ->setCacheContexts(isset($this->display['cache_metadata']['contexts']) ? $this->display['cache_metadata']['contexts'] : [])
-      ->setCacheMaxAge($cache->getCacheMaxAge())
-      ->merge(CacheableMetadata::createFromRenderArray($element))
-      ->applyTo($element);
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function elementPreRender(array $element) {
@@ -2311,7 +2300,7 @@ public function calculateCacheMetadata () {
    */
   public function getCacheMetadata() {
     if (!isset($this->display['cache_metadata'])) {
-      list($this->display['cache_metadata']['cacheable'], $this->display['cache_metadata']['contexts']) = $this->calculateCacheMetadata();
+      $this->display['cache_metadata'] = $this->calculateCacheMetadata();
     }
     return $this->display['cache_metadata'];
   }
@@ -2324,59 +2313,18 @@ public function execute() { }
   /**
    * {@inheritdoc}
    */
-  public function buildRenderable(array $args = [], $cache = TRUE) {
-    $this->view->element += [
+  public function buildRenderable(array $args = []) {
+    return [
       '#type' => 'view',
       '#name' => $this->view->storage->id(),
       '#display_id' => $this->display['id'],
       '#arguments' => $args,
       '#embed' => FALSE,
       '#view' => $this->view,
-      '#cache_properties' => ['#view_id', '#view_display_show_admin_links', '#view_display_plugin_id'],
-    ];
-
-    if ($cache) {
-      $this->view->element['#cache'] += ['keys' => []];
-      // Places like \Drupal\views\ViewExecutable::setCurrentPage() set up an
-      // additional cache context.
-      $this->view->element['#cache']['keys'] = array_merge(['views', 'display', $this->view->element['#name'], $this->view->element['#display_id']], $this->view->element['#cache']['keys']);
-
-      $this->applyDisplayCachablityMetadata($this->view->element);
-    }
-    else {
-      // Remove the cache keys, to ensure render caching is not triggered. We
-      // don't unset the other #cache values, to allow cacheability metadata to
-      // still be bubbled.
-      unset($this->view->element['#cache']['keys']);
-    }
-
-    return $this->view->element;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function buildBasicRenderable($view_id, $display_id, array $args = []) {
-    $build = [
-      '#type' => 'view',
-      '#name' => $view_id,
-      '#display_id' => $display_id,
-      '#arguments' => $args,
-      '#embed' => FALSE,
       '#cache' => [
-        'keys' => ['view', $view_id, 'display', $display_id],
+        'contexts' => isset($this->display['cache_metadata']['contexts']) ?  $this->display['cache_metadata']['contexts'] : [],
       ],
     ];
-
-    if ($args) {
-      $build['#cache']['keys'][] = 'args';
-      $build['#cache']['keys'][] = implode(',', $args);
-    }
-
-    $build['#cache_properties'] =  ['#view_id', '#view_display_show_admin_links', '#view_display_plugin_id'];
-
-    return $build;
-
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php b/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php
index c1aba0c..b82de15 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php
@@ -463,40 +463,16 @@ public function getCacheMetadata();
    */
   public function execute();
 
-
-  /**
-   * Builds a basic render array which can be properly render cached.
-   *
-   * In order to be rendered cached, it includes cache keys as well as the data
-   * required to load the view on cache misses.
-   *
-   * @param string $view_id
-   *   The view ID.
-   * @param string $display_id
-   *   The display ID.
-   * @param array $args
-   *   (optional) The view arguments.
-   *
-   * @return array
-   *   The view render array.
-   */
-  public static function buildBasicRenderable($view_id, $display_id, array $args = []);
-
   /**
    * Builds a renderable array of the view.
    *
    * Note: This does not yet contain the executed view, but just the loaded view
    * executable.
    *
-   * @param array $args
-   *   (optional) Arguments of the view.
-   * @param bool $cache
-   *   (optional) Specify FALSE in order to opt out of render caching.
-   *
    * @return array
    *   The render array of a view.
    */
-  public function buildRenderable(array $args = [], $cache = TRUE);
+  public function buildRenderable(array $args = []);
 
   /**
    * Renders the display for the purposes of a live preview.
diff --git a/core/modules/views/src/Plugin/views/display/Feed.php b/core/modules/views/src/Plugin/views/display/Feed.php
index eee69dd..baa5d6b 100644
--- a/core/modules/views/src/Plugin/views/display/Feed.php
+++ b/core/modules/views/src/Plugin/views/display/Feed.php
@@ -8,8 +8,6 @@
 namespace Drupal\views\Plugin\views\display;
 
 use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\CacheableResponse;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Views;
@@ -30,7 +28,7 @@
  *   returns_response = TRUE
  * )
  */
-class Feed extends PathPluginBase implements ResponseDisplayPluginInterface {
+class Feed extends PathPluginBase {
 
   /**
    * Whether the display allows the use of AJAX or not.
@@ -70,42 +68,24 @@ protected function getType() {
   }
 
   /**
-   * {@inheritdoc}
+   * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::execute().
    */
-  public static function buildResponse($view_id, $display_id, array $args = []) {
-    $build = static::buildBasicRenderable($view_id, $display_id, $args);
+  public function execute() {
+    parent::execute();
 
-    // Set up an empty response, so for example RSS can set the proper
-    // Content-Type header.
-    $response = new CacheableResponse('', 200);
-    $build['#response'] = $response;
-
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-
-    $output = $renderer->renderRoot($build);
+    $output = $this->view->render();
 
     if (empty($output)) {
       throw new NotFoundHttpException();
     }
 
-    $response->setContent($output);
-    $cache_metadata = CacheableMetadata::createFromRenderArray($build);
-    $response->addCacheableDependency($cache_metadata);
+    $response = $this->view->getResponse();
+
+    $response->setContent(drupal_render_root($output));
 
     return $response;
   }
 
-
-  /**
-   * {@inheritdoc}
-   */
-  public function execute() {
-    parent::execute();
-
-    return $this->view->render();
-  }
-
   /**
    * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::preview().
    */
@@ -127,11 +107,7 @@ public function preview() {
    * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::render().
    */
   public function render() {
-    $build = $this->view->style_plugin->render($this->view->result);
-
-    $this->applyDisplayCachablityMetadata($build);
-
-    return $build;
+    return $this->view->style_plugin->render($this->view->result);
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php
index 193979e..751b2fe6 100644
--- a/core/modules/views/src/Plugin/views/display/Page.php
+++ b/core/modules/views/src/Plugin/views/display/Page.php
@@ -15,7 +15,6 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-use Symfony\Component\Routing\Route;
 
 /**
  * The plugin that handles a full page.
@@ -36,13 +35,6 @@
 class Page extends PathPluginBase {
 
   /**
-   * The current page render array.
-   *
-   * @var array
-   */
-  protected static $pageRenderArray;
-
-  /**
    * Whether the display allows attachments.
    *
    * @var bool
@@ -92,34 +84,6 @@ public static function create(ContainerInterface $container, array $configuratio
   }
 
   /**
-   * Sets the current page views render array.
-   *
-   * @param array $element
-   *   (optional) A render array. If not specified the previous element is
-   *   returned.
-   *
-   * @return array
-   *   The page render array.
-   */
-  public static function &setPageRenderArray(array &$element = NULL) {
-    if (isset($element)) {
-      static::$pageRenderArray = &$element;
-    }
-
-    return static::$pageRenderArray;
-  }
-
-  /**
-   * Gets the current views page render array.
-   *
-   * @return array
-   *   The page render array.
-   */
-  public static function &getPageRenderArray() {
-    return static::$pageRenderArray;
-  }
-
-  /**
    * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::defineOptions().
    */
   protected function defineOptions() {
@@ -149,29 +113,14 @@ protected function defineOptions() {
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public static function buildBasicRenderable($view_id, $display_id, array $args = [], Route $route = NULL) {
-    $build = parent::buildBasicRenderable($view_id, $display_id, $args);
-
-    if ($route) {
-      $build['#view_id'] = $route->getDefault('view_id');
-      $build['#view_display_plugin_id'] = $route->getOption('_view_display_plugin_id');
-      $build['#view_display_show_admin_links'] = $route->getOption('_view_display_show_admin_links');
-    }
-    else {
-      throw new \BadFunctionCallException('Missing route parameters.');
-    }
-
-    return $build;
-  }
-
-  /**
    * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::execute().
    */
   public function execute() {
     parent::execute();
 
+    // Let the world know that this is the page view we're using.
+    views_set_page_view($this->view);
+
     // And now render the view.
     $render = $this->view->render();
 
diff --git a/core/modules/views/src/Plugin/views/display/PathPluginBase.php b/core/modules/views/src/Plugin/views/display/PathPluginBase.php
index d1aee85..415b704 100644
--- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php
@@ -138,7 +138,6 @@ protected function getRoute($view_id, $display_id) {
       '_controller' => 'Drupal\views\Routing\ViewPageController::handle',
       'view_id' => $view_id,
       'display_id' => $display_id,
-      '_view_display_show_admin_links' => $this->getOption('show_admin_links'),
     );
 
     // @todo How do we apply argument validation?
@@ -162,7 +161,6 @@ protected function getRoute($view_id, $display_id) {
         // handler.
         $arg_id = 'arg_' . $arg_counter++;
         $bits[$pos] = '{' . $arg_id . '}';
-        $argument_map[$arg_id] = $arg_id;
       }
       elseif (strpos($bit, '%') === 0) {
         // Use the name defined in the path.
@@ -180,7 +178,6 @@ protected function getRoute($view_id, $display_id) {
       // In contrast to the previous loop add the defaults here, as % was not
       // specified, which means the argument is optional.
       $defaults[$arg_id] = NULL;
-      $argument_map[$arg_id] = $arg_id;
       $bits[] = $bit;
     }
 
@@ -206,12 +203,6 @@ protected function getRoute($view_id, $display_id) {
 
     // Set the argument map, in order to support named parameters.
     $route->setOption('_view_argument_map', $argument_map);
-    $route->setOption('_view_display_plugin_id', $this->getPluginId());
-    $route->setOption('_view_display_plugin_class', get_called_class());
-    $route->setOption('_view_display_show_admin_links', $this->getOption('show_admin_links'));
-
-    // Store whether the view will return a response.
-    $route->setOption('returns_response', !empty($this->getPluginDefinition()['returns_response']));
 
     return $route;
   }
diff --git a/core/modules/views/src/Plugin/views/display/ResponseDisplayPluginInterface.php b/core/modules/views/src/Plugin/views/display/ResponseDisplayPluginInterface.php
deleted file mode 100644
index 4541572..0000000
--- a/core/modules/views/src/Plugin/views/display/ResponseDisplayPluginInterface.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\views\Plugin\views\display\ResponseDisplayPluginInterface.
- */
-
-namespace Drupal\views\Plugin\views\display;
-
-/**
- * Defines a display which returns a Response object.
- *
- * This interface is meant to be used for display plugins, which do return some
- * other format requiring to return a response directly.
- */
-interface ResponseDisplayPluginInterface extends DisplayPluginInterface {
-
-  /**
-   * Builds up a response with the rendered view as content.
-   *
-   * @param string $view_id
-   *   The view ID.
-   * @param string $display_id
-   *   The display ID.
-   * @param array $args
-   *   (optional) The arguments of the view.
-   *
-   * @return \Symfony\Component\HttpFoundation\Response
-   *   The built response.
-   */
-  public static function buildResponse($view_id, $display_id, array $args = []);
-
-}
diff --git a/core/modules/views/src/Plugin/views/field/Date.php b/core/modules/views/src/Plugin/views/field/Date.php
index 2a7886a..8857c1a 100644
--- a/core/modules/views/src/Plugin/views/field/Date.php
+++ b/core/modules/views/src/Plugin/views/field/Date.php
@@ -151,33 +151,24 @@ public function render(ResultRow $values) {
       $time_diff = REQUEST_TIME - $value; // will be positive for a datetime in the past (ago), and negative for a datetime in the future (hence)
       switch ($format) {
         case 'raw time ago':
-          return $this->dateFormatter->formatTimeDiffSince($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2));
-
+          return $this->dateFormatter->formatInterval($time_diff, is_numeric($custom_format) ? $custom_format : 2);
         case 'time ago':
-          return $this->t('%time ago', array('%time' => $this->dateFormatter->formatTimeDiffSince($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2))));
-
+          return $this->t('%time ago', array('%time' => $this->dateFormatter->formatInterval($time_diff, is_numeric($custom_format) ? $custom_format : 2)));
         case 'raw time hence':
-          return $this->dateFormatter->formatTimeDiffUntil($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2));
-
+          return $this->dateFormatter->formatInterval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2);
         case 'time hence':
-          return $this->t('%time hence', array('%time' => $this->dateFormatter->formatTimeDiffUntil($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2))));
-
+          return $this->t('%time hence', array('%time' => $this->dateFormatter->formatInterval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2)));
         case 'raw time span':
-          return ($time_diff < 0 ? '-' : '') . $this->dateFormatter->formatTimeDiffSince($value, array('strict' => FALSE, 'granularity' => is_numeric($custom_format) ? $custom_format : 2));
-
+          return ($time_diff < 0 ? '-' : '') . $this->dateFormatter->formatInterval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2);
         case 'inverse time span':
-          return ($time_diff > 0 ? '-' : '') . $this->dateFormatter->formatTimeDiffSince($value, array('strict' => FALSE, 'granularity' => is_numeric($custom_format) ? $custom_format : 2));
-
+          return ($time_diff > 0 ? '-' : '') . $this->dateFormatter->formatInterval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2);
         case 'time span':
-          $time = $this->dateFormatter->formatTimeDiffSince($value, array('strict' => FALSE, 'granularity' => is_numeric($custom_format) ? $custom_format : 2));
-          return ($time_diff < 0) ? $this->t('%time hence', array('%time' => $time)) : $this->t('%time ago', array('%time' => $time));
-
+          return $this->t(($time_diff < 0 ? '%time hence' : '%time ago'), array('%time' => $this->dateFormatter->formatInterval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2)));
         case 'custom':
           if ($custom_format == 'r') {
             return format_date($value, $format, $custom_format, $timezone, 'en');
           }
           return format_date($value, $format, $custom_format, $timezone);
-
         default:
           return format_date($value, $format, '', $timezone);
       }
diff --git a/core/modules/views/src/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php
index 5eaff38..4192719 100644
--- a/core/modules/views/src/Plugin/views/field/Field.php
+++ b/core/modules/views/src/Plugin/views/field/Field.php
@@ -232,6 +232,7 @@ public function query($use_groupby = FALSE) {
       unset($fields[$entity_type_key]);
     }
 
+    $field_definition = $this->getFieldDefinition();
     if ($use_groupby) {
       // Add the fields that we're actually grouping on.
       $options = array();
diff --git a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php
index 45418c9..051955e 100644
--- a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php
+++ b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php
@@ -294,6 +294,12 @@ public function buildJoin($select_query, $table, $view_query) {
           // Convert a single-valued array of values to the single-value case,
           // and transform from IN() notation to = notation
           if (is_array($info['value']) && count($info['value']) == 1) {
+            if (empty($info['operator'])) {
+              $operator = '=';
+            }
+            else {
+              $operator = $info['operator'] == 'NOT IN' ? '!=' : '=';
+            }
             $info['value'] = array_shift($info['value']);
           }
 
diff --git a/core/modules/views/src/Plugin/views/pager/SqlBase.php b/core/modules/views/src/Plugin/views/pager/SqlBase.php
index 4eda114..9c93a48 100644
--- a/core/modules/views/src/Plugin/views/pager/SqlBase.php
+++ b/core/modules/views/src/Plugin/views/pager/SqlBase.php
@@ -102,12 +102,13 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
       '#tree' => TRUE,
       '#title' => $this->t('Exposed options'),
       '#input' => TRUE,
-      '#description' => $this->t('Allow user to control selected display options for this view.'),
+      '#description' => $this->t('Exposing this options allows users to define their values in a exposed form when view is displayed'),
     );
 
     $form['expose']['items_per_page'] = array(
       '#type' => 'checkbox',
-      '#title' => $this->t('Allow user to control the number of items displayed in this view'),
+      '#title' => $this->t('Expose items per page'),
+      '#description' => $this->t('When checked, users can determine how many items per page show in a view'),
       '#default_value' => $this->options['expose']['items_per_page'],
     );
 
@@ -115,6 +116,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
       '#type' => 'textfield',
       '#title' => $this->t('Items per page label'),
       '#required' => TRUE,
+      '#description' => $this->t('Label to use in the exposed items per page form element.'),
       '#default_value' => $this->options['expose']['items_per_page_label'],
       '#states' => array(
         'invisible' => array(
@@ -139,13 +141,15 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
 
     $form['expose']['items_per_page_options_all'] = array(
       '#type' => 'checkbox',
-      '#title' => $this->t('Allow user to to display all items'),
+      '#title' => $this->t('Include all items option'),
+      '#description' => $this->t('If checked, an extra item will be included to items per page to display all items'),
       '#default_value' => $this->options['expose']['items_per_page_options_all'],
     );
 
     $form['expose']['items_per_page_options_all_label'] = array(
       '#type' => 'textfield',
       '#title' => $this->t('All items label'),
+      '#description' => $this->t('Which label will be used to display all items'),
       '#default_value' => $this->options['expose']['items_per_page_options_all_label'],
       '#states' => array(
         'invisible' => array(
@@ -156,7 +160,8 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
 
     $form['expose']['offset'] = array(
       '#type' => 'checkbox',
-      '#title' => $this->t('Allow user to specify number of items skipped from beginning of this view.'),
+      '#title' => $this->t('Expose Offset'),
+      '#description' => $this->t('When checked, users can determine how many items should be skipped at the beginning.'),
       '#default_value' => $this->options['expose']['offset'],
     );
 
@@ -164,6 +169,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
       '#type' => 'textfield',
       '#title' => $this->t('Offset label'),
       '#required' => TRUE,
+      '#description' => $this->t('Label to use in the exposed offset form element.'),
       '#default_value' => $this->options['expose']['offset_label'],
       '#states' => array(
         'invisible' => array(
diff --git a/core/modules/views/src/Plugin/views/query/QueryPluginBase.php b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
index 857c0c7..c9650ac 100644
--- a/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
+++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php
@@ -237,12 +237,15 @@ public function setupTimezone() {
    *   An appropriate query expression pointing to the date field.
    * @param string $format
    *   A format string for the result, like 'Y-m-d H:i:s'.
+   * @param boolean $string_date
+   *   For certain databases, date format functions vary depending on string or
+   *   numeric storage.
    *
    * @return string
    *   A string representing the field formatted as a date in the format
    *   specified by $format.
    */
-  public function getDateFormat($field, $format) {
+  public function getDateFormat($field, $format, $string_date = FALSE) {
     return $field;
   }
 
diff --git a/core/modules/views/src/Plugin/views/query/Sql.php b/core/modules/views/src/Plugin/views/query/Sql.php
index 2ddfd21..f03b494 100644
--- a/core/modules/views/src/Plugin/views/query/Sql.php
+++ b/core/modules/views/src/Plugin/views/query/Sql.php
@@ -1408,7 +1408,7 @@ function execute(ViewExecutable $view) {
       $count_query = $count_query->countQuery();
 
       // Add additional arguments as a fake condition.
-      // XXX: this doesn't work, because PDO mandates that all bound arguments
+      // XXX: this doesn't work... because PDO mandates that all bound arguments
       // are used on the query. TODO: Find a better way to do this.
       if (!empty($additional_arguments)) {
         // $query->where('1 = 1', $additional_arguments);
@@ -1748,9 +1748,9 @@ public function setupTimezone() {
   }
 
   /**
-   * Overrides \Drupal\views\Plugin\views\query\QueryPluginBase::getDateFormat().
+   * {@inheritdoc}
    */
-  public function getDateFormat($field, $format) {
+  public function getDateFormat($field, $format, $string_date = FALSE) {
     $db_type = Database::getConnection()->databaseType();
     switch ($db_type) {
       case 'mysql':
@@ -1797,7 +1797,13 @@ public function getDateFormat($field, $format) {
           'A' => 'AM',
         );
         $format = strtr($format, $replace);
-        return "TO_CHAR($field, '$format')";
+        if (!$string_date) {
+          return "TO_CHAR($field, '$format')";
+        }
+        // In order to allow for partials (eg, only the year), transform to a
+        // date, back to a string again.
+        // @todo this is very messy, and EXTRACT should probably be used.
+        return "TO_CHAR(TO_TIMESTAMP($field, 'YYYY-MM-DD HH24:MI:SS'), '$format')";
       case 'sqlite':
         $replace = array(
           'Y' => '%Y',
diff --git a/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php b/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php
index 6d04467..39f3bb9 100644
--- a/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php
+++ b/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php
@@ -269,7 +269,7 @@ protected function leftQuery($options) {
     // Not sure why, but our sort order clause doesn't have a table.
     // TODO: the call to addHandler() above to add the sort handler is probably
     // wrong -- needs attention from someone who understands it.
-    // In the meantime, this works, but with a leap of faith.
+    // In the meantime, this works, but with a leap of faith...
     $orders = &$subquery->getOrderBy();
     foreach ($orders as $order_key => $order) {
       // But if we're using a whole view, we don't know what we have!
diff --git a/core/modules/views/src/Plugin/views/row/RssFields.php b/core/modules/views/src/Plugin/views/row/RssFields.php
index 1d1e48c..b95b95f 100644
--- a/core/modules/views/src/Plugin/views/row/RssFields.php
+++ b/core/modules/views/src/Plugin/views/row/RssFields.php
@@ -147,8 +147,7 @@ public function render($row) {
     // @todo Views should expect and store a leading /. See:
     //   https://www.drupal.org/node/2423913
     $item->link = Url::fromUserInput('/' . $this->getField($row_index, $this->options['link_field']))->setAbsolute()->toString();
-    $field = $this->getField($row_index, $this->options['description_field']);
-    $item->description = is_array($field) ? $field : ['#markup' => $field];
+    $item->description = $this->getField($row_index, $this->options['description_field']);
     $item->elements = array(
       array('key' => 'pubDate', 'value' => $this->getField($row_index, $this->options['date_field'])),
       array(
@@ -186,8 +185,7 @@ public function render($row) {
       '#row' => $item,
       '#field_alias' => isset($this->field_alias) ? $this->field_alias : '',
     );
-
-    return $build;
+    return drupal_render_root($build);
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/sort/Random.php b/core/modules/views/src/Plugin/views/sort/Random.php
index 6f682e5..1cdfc03 100644
--- a/core/modules/views/src/Plugin/views/sort/Random.php
+++ b/core/modules/views/src/Plugin/views/sort/Random.php
@@ -26,8 +26,6 @@ public function usesGroupBy() {
 
   public function query() {
     $this->query->addOrderBy('rand');
-    // @todo Replace this once https://www.drupal.org/node/2464427 is in.
-    $this->view->element['#cache']['max-age'] = 0;
   }
 
   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
diff --git a/core/modules/views/src/Plugin/views/style/Rss.php b/core/modules/views/src/Plugin/views/style/Rss.php
index de0bce7..274c5be 100644
--- a/core/modules/views/src/Plugin/views/style/Rss.php
+++ b/core/modules/views/src/Plugin/views/style/Rss.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views\Plugin\views\style;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
 
@@ -108,7 +109,7 @@ public function render() {
       debug('Drupal\views\Plugin\views\style\Rss: Missing row plugin');
       return array();
     }
-    $rows = [];
+    $rows = '';
 
     // This will be filled in by the row plugin and is used later on in the
     // theming output.
@@ -125,14 +126,14 @@ public function render() {
 
     foreach ($this->view->result as $row_index => $row) {
       $this->view->row_index = $row_index;
-      $rows[] = $this->view->rowPlugin->render($row);
+      $rows .= $this->view->rowPlugin->render($row);
     }
 
     $build = array(
       '#theme' => $this->themeFunctions(),
       '#view' => $this->view,
       '#options' => $this->options,
-      '#rows' => $rows,
+      '#rows' => SafeMarkup::set($rows),
     );
     unset($this->view->row_index);
     return $build;
diff --git a/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php
index 292a2e3..997e8c3 100644
--- a/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php
+++ b/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php
@@ -795,7 +795,7 @@ protected function addDisplays(View $view, $display_options, $form, FormStateInt
   protected function defaultDisplayOptions() {
     $display_options = array();
     $display_options['access']['type'] = 'none';
-    $display_options['cache']['type'] = 'tag';
+    $display_options['cache']['type'] = 'none';
     $display_options['query']['type'] = 'views_query';
     $display_options['exposed_form']['type'] = 'basic';
     $display_options['pager']['type'] = 'full';
diff --git a/core/modules/views/src/Routing/ViewPageController.php b/core/modules/views/src/Routing/ViewPageController.php
index 7d0d2b6..4cd8b71 100644
--- a/core/modules/views/src/Routing/ViewPageController.php
+++ b/core/modules/views/src/Routing/ViewPageController.php
@@ -7,12 +7,14 @@
 
 namespace Drupal\views\Routing;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\views\Plugin\views\display\Page;
 use Drupal\views\ViewExecutableFactory;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
 /**
  * Defines a page controller to execute and render a view.
@@ -63,20 +65,31 @@ public static function create(ContainerInterface $container) {
    *   The ID of the view
    * @param string $display_id
    *   The ID of the display.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
    * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
    *   The route match.
    * @return null|void
    */
-  public function handle($view_id, $display_id, RouteMatchInterface $route_match) {
-    $args = array();
-    $route = $route_match->getRouteObject();
-    $map = $route->hasOption('_view_argument_map') ? $route->getOption('_view_argument_map') : array();
+  public function handle($view_id, $display_id, Request $request, RouteMatchInterface $route_match) {
+    $entity = $this->storage->load($view_id);
+    if (empty($entity)) {
+      throw new NotFoundHttpException(SafeMarkup::format('Page controller for view %id requested, but view was not found.', array('%id' => $view_id)));
+    }
+    $view = $this->executableFactory->get($entity);
+    $view->setRequest($request);
+    $view->setDisplay($display_id);
+    $view->initHandlers();
 
-    foreach ($map as $attribute => $parameter_name) {
+    $args = array();
+    $map = $route_match->getRouteObject()->getOption('_view_argument_map', array());
+    $arguments_length = count($view->argument);
+    for ($argument_index = 0; $argument_index < $arguments_length; $argument_index++) {
       // Allow parameters be pulled from the request.
       // The map stores the actual name of the parameter in the request. Views
       // which override existing controller, use for example 'node' instead of
       // arg_nid as name.
+      $attribute = 'arg_' . $argument_index;
       if (isset($map[$attribute])) {
         $attribute = $map[$attribute];
       }
@@ -91,17 +104,12 @@ public function handle($view_id, $display_id, RouteMatchInterface $route_match)
       }
     }
 
-    /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase $class */
-    $class = $route->getOption('_view_display_plugin_class');
-    if ($route->getOption('returns_response')) {
-      /** @var \Drupal\views\Plugin\views\display\ResponseDisplayPluginInterface $class */
-      return $class::buildResponse($view_id, $display_id, $args);
+    $plugin_definition = $view->display_handler->getPluginDefinition();
+    if (!empty($plugin_definition['returns_response'])) {
+      return $view->executeDisplay($display_id, $args);
     }
     else {
-      $build = $class::buildBasicRenderable($view_id, $display_id, $args, $route);
-      Page::setPageRenderArray($build);
-
-      return $build;
+      return $view->buildRenderable($display_id, $args);
     }
   }
 
diff --git a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php
index b5a15c6..1617175 100644
--- a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php
+++ b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php
@@ -8,19 +8,14 @@
 namespace Drupal\views\Tests;
 
 use Drupal\Core\Cache\Cache;
-use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\ViewExecutable;
 use Symfony\Component\HttpFoundation\Request;
 
 trait AssertViewsCacheTagsTrait {
 
-  use AssertPageCacheContextsAndTagsTrait;
 
   /**
-   * Asserts a view's result & render cache items' cache tags.
-   *
-   * This methods uses a full view object in order to render the view.
+   * Asserts a view's result & output cache items' cache tags.
    *
    * @param \Drupal\views\ViewExecutable $view
    *   The view to test, must have caching enabled.
@@ -34,32 +29,23 @@
    *   A set of cache tags expected to be set on the built view's render array.
    *
    * @return array
-   *   The render array.
+   *   The render array
    */
   protected function assertViewsCacheTags(ViewExecutable $view, $expected_results_cache, $views_caching_is_enabled, array $expected_render_array_cache_tags) {
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    /** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
-    $render_cache = \Drupal::service('render_cache');
-
-    $build = $view->buildRenderable();
-    $original = $build;
+    $build = $view->preview();
 
     // Ensure the current request is a GET request so that render caching is
     // active for direct rendering of views, just like for actual requests.
     /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */
     $request_stack = \Drupal::service('request_stack');
-    $request = new Request();
-    $request->server->set('REQUEST_TIME', REQUEST_TIME);
-    $view->setRequest($request);
-    $request_stack->push($request);
-    $renderer->renderRoot($build);
+    $request_stack->push(new Request());
+    \Drupal::service('renderer')->renderRoot($build);
+    $request_stack->pop();
 
     // Render array cache tags.
     $this->pass('Checking render array cache tags.');
     sort($expected_render_array_cache_tags);
     $this->assertEqual($build['#cache']['tags'], $expected_render_array_cache_tags);
-    $this->debugCacheTags($build['#cache']['tags'], $expected_render_array_cache_tags);
 
     if ($views_caching_is_enabled) {
       $this->pass('Checking Views results cache item cache tags.');
@@ -67,101 +53,34 @@ protected function assertViewsCacheTags(ViewExecutable $view, $expected_results_
       $cache_plugin = $view->display_handler->getPlugin('cache');
 
       // Results cache.
-
-      // Ensure that the views query is built.
-      $view->build();
       $results_cache_item = \Drupal::cache('data')->get($cache_plugin->generateResultsKey());
       if (is_array($expected_results_cache)) {
         $this->assertTrue($results_cache_item, 'Results cache item found.');
         if ($results_cache_item) {
           sort($expected_results_cache);
           $this->assertEqual($results_cache_item->tags, $expected_results_cache);
-          $this->debugCacheTags($results_cache_item->tags, $expected_results_cache);
         }
       }
       else {
         $this->assertFalse($results_cache_item, 'Results cache item not found.');
       }
 
-      $this->pass('Checking Views render cache item cache tags.');
-
-      $original['#cache'] += ['contexts' => []];
-      $original['#cache']['contexts'] = Cache::mergeContexts($original['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
-
-      $render_cache_item = $render_cache->get($original);
+      // Output cache.
+      $this->pass('Checking Views output cache item cache tags.');
+      $output_cache_item = \Drupal::cache('render')->get($cache_plugin->generateOutputKey());
       if ($views_caching_is_enabled === TRUE) {
-        $this->assertTrue(!empty($render_cache_item), 'Render cache item found.');
-        if ($render_cache_item) {
-          $this->assertEqual($render_cache_item['#cache']['tags'], $expected_render_array_cache_tags);
-          $this->debugCacheTags($render_cache_item['#cache']['tags'], $expected_render_array_cache_tags);
+        $this->assertTrue($output_cache_item, 'Output cache item found.');
+        if ($output_cache_item) {
+          $this->assertEqual($output_cache_item->tags, Cache::mergeTags($expected_render_array_cache_tags, ['rendered']));
         }
       }
       else {
-        $this->assertFalse($render_cache_item, 'Render cache item not found.');
+        $this->assertFalse($output_cache_item, 'Output cache item not found.');
       }
     }
 
     $view->destroy();
 
-    $request_stack->pop();
-
-    return $build;
-  }
-
-  /**
-   * Asserts a view's result & render cache items' cache tags.
-   *
-   * This method starts with a pre bubbling basic render array.
-   *
-   * @param \Drupal\views\ViewExecutable $view
-   *   The view.
-   * @param string[] $expected_render_array_cache_tags
-   *   The expected render cache tags.
-   * @param bool $views_caching_is_enabled
-   *   Defines whether views output / render caching is enabled.
-   *
-   * @return array
-   *   The render array.
-   */
-  protected function assertViewsCacheTagsFromStaticRenderArray(ViewExecutable $view, array $expected_render_array_cache_tags, $views_caching_is_enabled) {
-    $original = $build = DisplayPluginBase::buildBasicRenderable($view->id(), $view->current_display ?: 'default', $view->args);
-
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    /** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
-    $render_cache = \Drupal::service('render_cache');
-
-    // Ensure the current request is a GET request so that render caching is
-    // active for direct rendering of views, just like for actual requests.
-    /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */
-    $request_stack = \Drupal::service('request_stack');
-    $request = new Request();
-    $request->server->set('REQUEST_TIME', REQUEST_TIME);
-    $request_stack->push($request);
-    $renderer->renderRoot($build);
-
-    // Render array cache tags.
-    $this->pass('Checking render array cache tags.');
-    sort($expected_render_array_cache_tags);
-    $this->assertEqual($build['#cache']['tags'], $expected_render_array_cache_tags);
-    $this->debugCacheTags($build['#cache']['tags'], $expected_render_array_cache_tags);
-
-    $this->pass('Checking Views render cache item cache tags.');
-    $original['#cache'] += ['contexts' => []];
-    $original['#cache']['contexts'] = Cache::mergeContexts($original['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
-
-    $render_cache_item = $render_cache->get($original);
-    if ($views_caching_is_enabled) {
-      $this->assertTrue(!empty($render_cache_item), 'Render cache item found.');
-      if ($render_cache_item) {
-        $this->assertEqual($render_cache_item['#cache']['tags'], $expected_render_array_cache_tags);
-        $this->debugCacheTags($render_cache_item['#cache']['tags'], $expected_render_array_cache_tags);
-      }
-    }
-    else {
-      $this->assertFalse($render_cache_item, 'Render cache item not found.');
-    }
-
     return $build;
   }
 
diff --git a/core/modules/views/src/Tests/GlossaryTest.php b/core/modules/views/src/Tests/GlossaryTest.php
index 9b12759..16e7c04 100644
--- a/core/modules/views/src/Tests/GlossaryTest.php
+++ b/core/modules/views/src/Tests/GlossaryTest.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Url;
+use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 use Drupal\views\Views;
 
 /**
@@ -19,6 +20,7 @@
  */
 class GlossaryTest extends ViewTestBase {
 
+  use AssertPageCacheContextsAndTagsTrait;
   use AssertViewsCacheTagsTrait;
 
   /**
diff --git a/core/modules/views/src/Tests/Handler/FieldDateTest.php b/core/modules/views/src/Tests/Handler/FieldDateTest.php
index 98eae40..3ea113d 100644
--- a/core/modules/views/src/Tests/Handler/FieldDateTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldDateTest.php
@@ -121,19 +121,19 @@ public function testFieldDate() {
     }
 
     // Check times in the past.
-    $time_since = $this->container->get('date.formatter')->formatTimeDiffSince($time);
+    $test = $this->container->get('date.formatter')->formatInterval(REQUEST_TIME - $time, 2);
     $intervals = array(
-      'raw time ago' => $time_since,
-      'time ago' => t('%time ago', array('%time' => $time_since)),
-      'raw time span' => $time_since,
-      'inverse time span' => -$time_since,
-      'time span' => t('%time ago', array('%time' => $time_since)),
+      'raw time ago' => $test,
+      'time ago' => t('%time ago', array('%time' => $test)),
+      'raw time span' => $test,
+      'inverse time span' => -$test,
+      'time span' => t('%time ago', array('%time' => $test)),
     );
     $this->assertRenderedDatesEqual($view, $intervals);
 
     // Check times in the future.
     $time = gmmktime(0, 0, 0, 1, 1, 2050);
-    $formatted = $this->container->get('date.formatter')->formatTimeDiffUntil($time);
+    $formatted = $this->container->get('date.formatter')->formatInterval($time - REQUEST_TIME, 2);
     $intervals = array(
       'raw time span' => -$formatted,
       'time span' => t('%time hence', array(
diff --git a/core/modules/views/src/Tests/Handler/FieldWebTest.php b/core/modules/views/src/Tests/Handler/FieldWebTest.php
index 3fde585..13bb95b 100644
--- a/core/modules/views/src/Tests/Handler/FieldWebTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldWebTest.php
@@ -222,6 +222,8 @@ public function testAlterUrl() {
 
     // Some generic test code adapted from the UrlTest class, which tests
     // mostly the different options for the path.
+    global $base_url, $script_path;
+
     foreach (array(FALSE, TRUE) as $absolute) {
       $alter = &$id_field->options['alter'];
       $alter['path'] = 'node/123';
diff --git a/core/modules/views/src/Tests/Handler/SortRandomTest.php b/core/modules/views/src/Tests/Handler/SortRandomTest.php
index f188558..843019b 100644
--- a/core/modules/views/src/Tests/Handler/SortRandomTest.php
+++ b/core/modules/views/src/Tests/Handler/SortRandomTest.php
@@ -7,8 +7,6 @@
 
 namespace Drupal\views\Tests\Handler;
 
-use Drupal\Core\Cache\Cache;
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Tests\ViewUnitTestBase;
 use Drupal\views\Views;
 
@@ -28,17 +26,10 @@ class SortRandomTest extends ViewUnitTestBase {
 
   /**
    * Add more items to the test set, to make the order tests more robust.
-   *
-   * In total we have then 60 entries, which makes a probability of a collision
-   * of 1/60!, which is around 1/1E80, which is higher than the estimated amount
-   * of protons / electrons in the observable universe, also called the
-   * eddington number.
-   *
-   * @see http://en.wikipedia.org/wiki/Eddington_number
    */
   protected function dataSet() {
     $data = parent::dataSet();
-    for ($i = 0; $i < 55; $i++) {
+    for ($i = 0; $i < 50; $i++) {
       $data[] = array(
         'name' => 'name_' . $i,
         'age' => $i,
@@ -105,40 +96,4 @@ public function testRandomOrdering() {
     ));
   }
 
-  /**
-   * Tests random ordering with tags based caching.
-   *
-   * The random sorting should opt out of caching by defining a max age of 0.
-   * At the same time, the row render caching still works.
-   */
-  public function testRandomOrderingWithRenderCaching() {
-    $view_random = $this->getBasicRandomView();
-
-    $display = &$view_random->storage->getDisplay('default');
-    $display['display_options']['cache'] = [
-      'type' => 'tag',
-    ];
-
-    $view_random->storage->save();
-
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    /** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
-    $render_cache = \Drupal::service('render_cache');
-
-    $original = $build = DisplayPluginBase::buildBasicRenderable($view_random->id(), 'default');
-    $result = $renderer->renderPlain($build);
-
-    $original['#cache'] += ['contexts' => []];
-    $original['#cache']['contexts'] = Cache::mergeContexts($original['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
-
-    $this->assertFalse($render_cache->get($original), 'Ensure there is no render cache entry.');
-
-    $build = DisplayPluginBase::buildBasicRenderable($view_random->id(), 'default');
-    $result2 = $renderer->renderPlain($build);
-
-    // Ensure that the random ordering works and don't produce the same result.
-    $this->assertNotEqual($result, $result2);
-  }
-
 }
diff --git a/core/modules/views/src/Tests/Plugin/CacheTagTest.php b/core/modules/views/src/Tests/Plugin/CacheTagTest.php
index 3d497d5..34b2434 100644
--- a/core/modules/views/src/Tests/Plugin/CacheTagTest.php
+++ b/core/modules/views/src/Tests/Plugin/CacheTagTest.php
@@ -7,8 +7,6 @@
 
 namespace Drupal\views\Tests\Plugin;
 
-use Drupal\Core\Cache\Cache;
-use Drupal\views\ViewExecutable;
 use Drupal\views\Views;
 
 /**
@@ -90,127 +88,93 @@ protected function setUp() {
     }
     $this->article = $this->drupalCreateNode(array('title' => "Test article", 'type' => 'article'));
     $this->user = $this->drupalCreateUser();
-
-    // Mark the current request safe, in order to make render cache working, see
-    // \Drupal\Core\Render\RenderCache::get.
-    \Drupal::request()->setMethod('GET');
-  }
-
-  /**
-   * Gets the render cache for a given view.
-   *
-   * @param \Drupal\views\ViewExecutable $view
-   *   The view.
-   *
-   * @return array|FALSE
-   *   The render cache result or FALSE if not existent.
-   */
-  protected function getRenderCache(ViewExecutable $view) {
-    /** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
-    $render_cache = \Drupal::service('render_cache');
-    $view->element = ['#cache' => []];
-    $build = $view->buildRenderable();
-    $build['#cache']['contexts'] = Cache::mergeContexts($build['#cache']['contexts'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
-
-    return $render_cache->get($build);
   }
 
   /**
    * Tests the tag cache plugin.
    */
   public function testTagCaching() {
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
     $view = Views::getView('test_tag_cache');
-    $build = $view->buildRenderable();
-    $renderer->renderPlain($build);
+    $view->render();
 
     // Saving the view should invalidate the tags.
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found.');
 
     $view->storage->save();
 
     $this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after the view is saved.');
-    $this->assertFalse($this->getRenderCache($view), 'Output cache empty after the view is saved.');
+    $this->assertFalse($cache_plugin->cacheGet('output'), 'Output cache empty after the view is saved.');
 
     $view->destroy();
-    $build = $view->buildRenderable();
-    $renderer->renderPlain($build);
+    $view->render();
 
     // Test invalidating the nodes in this view invalidates the cache.
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found.');
 
     $this->nodeViewBuilder->resetCache($this->pages);
 
     $this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after resetCache is called with pages.');
-    $this->assertFalse($this->getRenderCache($view), 'Output cache empty after resetCache is called with pages.');
+    $this->assertFalse($cache_plugin->cacheGet('output'), 'Output cache empty after resetCache is called with pages.');
 
     $view->destroy();
-    $build = $view->buildRenderable();
-    $renderer->renderPlain($build);
+    $view->render();
 
     // Test saving a node in this view invalidates the cache.
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found.');
 
     $node = reset($this->pages);
     $node->save();
 
     $this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after a page node is saved.');
-    $this->assertFalse($this->getRenderCache($view), 'Output cache empty after a page node is saved.');
+    $this->assertFalse($cache_plugin->cacheGet('output'), 'Output cache empty after a page node is saved.');
 
     $view->destroy();
-    $build = $view->buildRenderable();
-    $renderer->renderPlain($build);
+    $view->render();
 
     // Test saving a node not in this view invalidates the cache too.
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found.');
 
     $this->article->save();
 
     $this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after an article node is saved.');
-    $this->assertFalse($this->getRenderCache($view), 'Output cache empty after an article node is saved.');
+    $this->assertFalse($cache_plugin->cacheGet('output'), 'Output cache empty after an article node is saved.');
 
     $view->destroy();
-    $build = $view->buildRenderable();
-    $renderer->renderPlain($build);
+    $view->render();
 
     // Test that invalidating a tag for a user, does not invalidate the cache,
     // as the user entity type will not be contained in the views cache tags.
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found.');
 
     $this->userViewBuilder->resetCache(array($this->user));
 
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found after a user is invalidated.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found after a user is invalidated.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found after a user is invalidated.');
 
     $view->destroy();
-    // Invalidate the views cache tags in order to invalidate the render
-    // caching.
-    \Drupal::service('cache_tags.invalidator')->invalidateTags($view->storage->getCacheTags());
-    $build = $view->buildRenderable();
-    $renderer->renderPlain($build);
+    $view->render();
 
     // Test the cacheFlush method invalidates the cache.
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertTrue($cache_plugin->cacheGet('results'), 'Results cache found.');
-    $this->assertTrue($this->getRenderCache($view), 'Output cache found.');
+    $this->assertTrue($cache_plugin->cacheGet('output'), 'Output cache found.');
 
     $cache_plugin->cacheFlush();
 
     $cache_plugin = $view->display_handler->getPlugin('cache');
     $this->assertFalse($cache_plugin->cacheGet('results'), 'Results cache empty after the cacheFlush() method is called.');
-    $this->assertFalse($this->getRenderCache($view), 'Output cache empty after the cacheFlush() method is called.');
+    $this->assertFalse($cache_plugin->cacheGet('output'), 'Output cache empty after the cacheFlush() method is called.');
   }
 
 }
diff --git a/core/modules/views/src/Tests/Plugin/CacheTest.php b/core/modules/views/src/Tests/Plugin/CacheTest.php
index bae30f5..a15e0f4 100644
--- a/core/modules/views/src/Tests/Plugin/CacheTest.php
+++ b/core/modules/views/src/Tests/Plugin/CacheTest.php
@@ -43,9 +43,6 @@ protected function setUp($import_test_views = TRUE) {
     $this->installEntitySchema('node');
     $this->installEntitySchema('taxonomy_term');
     $this->installEntitySchema('user');
-
-    // Setup the current time properly.
-    \Drupal::request()->server->set('REQUEST_TIME', time());
   }
 
   /**
@@ -279,18 +276,14 @@ function testHeaderStorage() {
       )
     ));
 
-    $output = $view->buildRenderable();
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    $renderer->render($output);
-
+    $output = $view->preview();
+    \Drupal::service('renderer')->render($output);
     unset($view->pre_render_called);
     $view->destroy();
 
     $view->setDisplay();
-    $output = $view->buildRenderable();
-    $renderer->render($output);
-
+    $output = $view->preview();
+    \Drupal::service('renderer')->render($output);
     $this->assertTrue(in_array('views_test_data/test', $output['#attached']['library']), 'Make sure libraries are added for cached views.');
     $this->assertEqual(['foo' => 'bar'], $output['#attached']['drupalSettings'], 'Make sure drupalSettings are added for cached views.');
     // Note: views_test_data_views_pre_render() adds some cache tags.
diff --git a/core/modules/views/src/Tests/Plugin/CacheWebTest.php b/core/modules/views/src/Tests/Plugin/CacheWebTest.php
index 85194e2..676faa3 100644
--- a/core/modules/views/src/Tests/Plugin/CacheWebTest.php
+++ b/core/modules/views/src/Tests/Plugin/CacheWebTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\views\Tests\Plugin;
 
 use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Views;
 
 /**
@@ -61,15 +60,12 @@ public function testCacheOutputOnPage() {
     $view->save();
     $this->container->get('router.builder')->rebuildIfNeeded();
 
-    /** @var \Drupal\Core\Render\RenderCacheInterface $render_cache */
-    $render_cache = \Drupal::service('render_cache');
-    $cache_element = DisplayPluginBase::buildBasicRenderable('test_display', 'page_1');
-    $cache_element['#cache'] += ['contexts' => $this->container->getParameter('renderer.config')['required_cache_contexts']];
-    $this->assertFalse($render_cache->get($cache_element));
+    $output_key = $view->getDisplay()->getPlugin('cache')->generateOutputKey();
+    $this->assertFalse(\Drupal::cache('render')->get($output_key));
 
     $this->drupalGet('test-display');
     $this->assertResponse(200);
-    $this->assertTrue($render_cache->get($cache_element));
+    $this->assertTrue(\Drupal::cache('render')->get($output_key));
     $cache_tags = [
       'config:user.role.anonymous',
       'config:views.view.test_display',
@@ -80,7 +76,7 @@ public function testCacheOutputOnPage() {
 
     $this->drupalGet('test-display');
     $this->assertResponse(200);
-    $this->assertTrue($render_cache->get($cache_element));
+    $this->assertTrue(\Drupal::cache('render')->get($output_key));
     $this->assertCacheTags($cache_tags);
   }
 
diff --git a/core/modules/views/src/Tests/Plugin/DisplayPageWebTest.php b/core/modules/views/src/Tests/Plugin/DisplayPageWebTest.php
index 31bfd3c..2da04f3 100644
--- a/core/modules/views/src/Tests/Plugin/DisplayPageWebTest.php
+++ b/core/modules/views/src/Tests/Plugin/DisplayPageWebTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\views\Tests\Plugin;
 
-use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 use Drupal\views\Views;
 
 /**
@@ -17,8 +16,6 @@
  */
 class DisplayPageWebTest extends PluginTestBase {
 
-  use AssertPageCacheContextsAndTagsTrait;
-
   /**
    * Views used by this test.
    *
@@ -53,7 +50,6 @@ public function testArguments() {
 
     $this->drupalGet('test_route_with_argument/1');
     $this->assertResponse(200);
-    $this->assertCacheContexts(['languages:language_interface', 'theme', 'url']);
     $result = $this->xpath('//span[@class="field-content"]');
     $this->assertEqual(count($result), 1, 'Ensure that just the filtered entry was returned.');
     $this->assertEqual((string) $result[0], 1, 'The passed ID was returned.');
diff --git a/core/modules/views/src/Tests/Plugin/PagerKernelTest.php b/core/modules/views/src/Tests/Plugin/PagerKernelTest.php
index 71a1c0b..0eb8f7d 100644
--- a/core/modules/views/src/Tests/Plugin/PagerKernelTest.php
+++ b/core/modules/views/src/Tests/Plugin/PagerKernelTest.php
@@ -47,26 +47,29 @@ protected function setUp($import_test_views = TRUE) {
    */
   public function testSetPagerMethods() {
     $view = Views::getView('test_pager_full');
-
-    // Mark the view as cacheable in order have the cache checking working
-    // below.
-    $display = &$view->storage->getDisplay('default');
-    $display['display_options']['cache']['type'] = 'tag';
-    $view->storage->save();
-
     $output = $view->preview();
 
     \Drupal::service('renderer')->renderPlain($output);
     $this->assertIdentical(CacheBackendInterface::CACHE_PERMANENT, $output['#cache']['max-age']);
 
     foreach (['setItemsPerPage', 'setOffset', 'setCurrentPage'] as $method) {
+      // Without $keep_cacheablity.
       $view = Views::getView('test_pager_full');
       $view->setDisplay('default');
       $view->{$method}(1);
       $output = $view->preview();
 
       \Drupal::service('renderer')->renderPlain($output);
-      $this->assertIdentical(CacheBackendInterface::CACHE_PERMANENT, $output['#cache']['max-age'], 'Max age kept.');
+      $this->assertIdentical(0, $output['#cache']['max-age'], 'Max age set to 0 without $keep_cacheablity.');
+
+      // With $keep_cacheablity.
+      $view = Views::getView('test_pager_full');
+      $view->setDisplay('default');
+      $view->{$method}(1, TRUE);
+      $output = $view->preview();
+
+      \Drupal::service('renderer')->renderPlain($output);
+      $this->assertIdentical(CacheBackendInterface::CACHE_PERMANENT, $output['#cache']['max-age'], 'Max age unchanged with $keep_cacheablity.');
     }
 
   }
diff --git a/core/modules/views/src/Tests/PluginInstanceTest.php b/core/modules/views/src/Tests/PluginInstanceTest.php
index 189399f..1893432 100644
--- a/core/modules/views/src/Tests/PluginInstanceTest.php
+++ b/core/modules/views/src/Tests/PluginInstanceTest.php
@@ -90,7 +90,7 @@ public function testPluginInstances() {
         if ($reflection->isSubclassOf('Drupal\views\Plugin\views\PluginBase')) {
           // Create a plugin instance and check what it is. This is not just
           // good to check they can be created but for throwing any notices for
-          // method signatures etc. too.
+          // method signatures etc... too.
           $instance = $manager->createInstance($id);
           $this->assertTrue($instance instanceof $definition['class'], format_string('Instance of @type:@id created', array('@type' => $type, '@id' => $id)));
         }
diff --git a/core/modules/views/src/Tests/QueryGroupByTest.php b/core/modules/views/src/Tests/QueryGroupByTest.php
index 768aaaf..ad3e225 100644
--- a/core/modules/views/src/Tests/QueryGroupByTest.php
+++ b/core/modules/views/src/Tests/QueryGroupByTest.php
@@ -183,7 +183,7 @@ public function testGroupByNone() {
    */
   public function testGroupByCountOnlyFilters() {
     // Check if GROUP BY and HAVING are included when a view
-    // doesn't display SUM, COUNT, MAX, etc. functions in SELECT statement.
+    // Doesn't display SUM, COUNT, MAX... functions in SELECT statement
 
     for ($x = 0; $x < 10; $x++) {
       $this->storage->create(array('name' => 'name1'))->save();
diff --git a/core/modules/views/src/Tests/RenderCacheIntegrationTest.php b/core/modules/views/src/Tests/RenderCacheIntegrationTest.php
index b1235b1..4ec2c41 100644
--- a/core/modules/views/src/Tests/RenderCacheIntegrationTest.php
+++ b/core/modules/views/src/Tests/RenderCacheIntegrationTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\views\Tests;
 
 use Drupal\Core\Cache\Cache;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\entity_test\Entity\EntityTest;
 use Drupal\views\Views;
@@ -47,12 +46,6 @@ protected function setUp() {
    * Tests a field-based view's cache tags when using the "none" cache plugin.
    */
   public function testFieldBasedViewCacheTagsWithCachePluginNone() {
-    $view = Views::getview('entity_test_fields');
-    $view->getDisplay()->overrideOption('cache', [
-      'type' => 'none',
-    ]);
-    $view->save();
-
     $this->assertCacheTagsForFieldBasedView(FALSE);
   }
 
@@ -97,21 +90,16 @@ protected function assertCacheTagsForFieldBasedView($do_assert_views_caches) {
     $view = Views::getview('entity_test_fields');
 
     // Empty result (no entities yet).
-    $this->pass('Test without entities');
     $base_tags =  ['config:views.view.entity_test_fields', 'entity_test_list'];
     $this->assertViewsCacheTags($view, $base_tags, $do_assert_views_caches, $base_tags);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $base_tags, $do_assert_views_caches);
 
 
     // Non-empty result (1 entity).
-    /** @var \Drupal\Core\Entity\EntityInterface[] $entities */
     $entities[] = $entity = EntityTest::create();
     $entity->save();
 
-    $this->pass('Test with entities');
     $tags_with_entity = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
     $this->assertViewsCacheTags($view, $tags_with_entity, $do_assert_views_caches, $tags_with_entity);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_with_entity, $do_assert_views_caches);
 
 
     // Paged result (more entities than the items-per-page limit).
@@ -119,91 +107,35 @@ protected function assertCacheTagsForFieldBasedView($do_assert_views_caches) {
       $entities[] = $entity = EntityTest::create();
       $entity->save();
     }
-
     // Page 1.
-    $this->pass('Test pager');
-    $this->pass('Page 1');
-    \Drupal::request()->query->set('page', 0);
     $tags_page_1 = Cache::mergeTags($base_tags, $entities[1]->getCacheTags(), $entities[2]->getCacheTags(), $entities[3]->getCacheTags(), $entities[4]->getCacheTags(), $entities[5]->getCacheTags());
     $this->assertViewsCacheTags($view, $tags_page_1, $do_assert_views_caches, $tags_page_1);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_page_1, $do_assert_views_caches);
     $view->destroy();
     // Page 2.
-    $this->pass('Page 2');
     $view->setCurrentPage(1);
-    \Drupal::request()->query->set('page', 1);
     $tags_page_2 = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
     $this->assertViewsCacheTags($view, $tags_page_2, $do_assert_views_caches, $tags_page_2);
     $view->destroy();
 
     // Ensure that invalidation works on both pages.
-    $this->pass('Page invalidations');
-    $this->pass('Page 2');
     $view->setCurrentPage(1);
-    \Drupal::request()->query->set('page', 1);
     $entities[0]->name->value = $random_name = $this->randomMachineName();
     $entities[0]->save();
     $build = $this->assertViewsCacheTags($view, $tags_page_2, $do_assert_views_caches, $tags_page_2);
-    // @todo Static render arrays don't support different pages yet, see
-    //   https://www.drupal.org/node/2500701.
-    // $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_page_2, $do_assert_views_caches);
     $this->assertTrue(strpos($build['#markup'], $random_name) !== FALSE);
     $view->destroy();
 
-    $this->pass('Page 1');
     $view->setCurrentPage(0);
-    \Drupal::request()->query->set('page', 0);
     $entities[1]->name->value = $random_name = $this->randomMachineName();
     $entities[1]->save();
     $build = $this->assertViewsCacheTags($view, $tags_page_1, $do_assert_views_caches, $tags_page_1);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_page_1, $do_assert_views_caches);
     $this->assertTrue(strpos($build['#markup'], $random_name) !== FALSE);
-    $view->destroy();
-
-    // Setup arguments to ensure that render caching also varies by them.
-    $this->pass('Test arguments');
-
-    // Custom assert for a single result row.
-    $single_entity_assertions = function(array $build, EntityInterface $entity) {
-      $this->setRawContent($build['#markup']);
-
-      $result = $this->cssSelect('div.views-row');
-      $count = count($result);
-      $this->assertEqual($count, 1);
-
-      $this->assertEqual((string) $result[0]->div->span, (string) $entity->id());
-    };
-
-    // Execute the view once with a static renderable and one with a full
-    // prepared render array.
-    $tags_argument = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
-    $view->setArguments([$entities[0]->id()]);
-    $build = $this->assertViewsCacheTags($view, $tags_argument, $do_assert_views_caches, $tags_argument);
-    $single_entity_assertions($build, $entities[0]);
-
-    $view->setArguments([$entities[0]->id()]);
-    $build = $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_argument, $do_assert_views_caches);
-    $single_entity_assertions($build, $entities[0]);
-
-    // Set a different argument and ensure that the result is different.
-    $tags2_argument = Cache::mergeTags($base_tags, $entities[1]->getCacheTags());
-    $view->setArguments([$entities[1]->id()]);
-    $build = $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags2_argument, $do_assert_views_caches);
-    $single_entity_assertions($build, $entities[1]);
-
-    $view->destroy();
   }
 
   /**
    * Tests a entity-based view's cache tags when using the "none" cache plugin.
    */
   public function testEntityBasedViewCacheTagsWithCachePluginNone() {
-    $view = Views::getview('entity_test_row');
-    $view->getDisplay()->overrideOption('cache', [
-      'type' => 'none',
-    ]);
-    $view->save();
-
     $this->assertCacheTagsForEntityBasedView(FALSE);
   }
 
@@ -247,7 +179,7 @@ protected function assertCacheTagsForEntityBasedView($do_assert_views_caches) {
     // Empty result (no entities yet).
     $base_tags = $base_render_tags = ['config:views.view.entity_test_row', 'entity_test_list'];
     $this->assertViewsCacheTags($view, $base_tags, $do_assert_views_caches, $base_tags);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $base_tags, $do_assert_views_caches);
+
 
     // Non-empty result (1 entity).
     $entities[] = $entity = EntityTest::create();
@@ -256,7 +188,6 @@ protected function assertCacheTagsForEntityBasedView($do_assert_views_caches) {
     $result_tags_with_entity = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
     $render_tags_with_entity = Cache::mergeTags($base_render_tags, $entities[0]->getCacheTags(), ['entity_test_view']);
     $this->assertViewsCacheTags($view, $result_tags_with_entity, $do_assert_views_caches, $render_tags_with_entity);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $render_tags_with_entity, $do_assert_views_caches);
 
 
     // Paged result (more entities than the items-per-page limit).
@@ -269,7 +200,6 @@ protected function assertCacheTagsForEntityBasedView($do_assert_views_caches) {
     $result_tags_page_1 = Cache::mergeTags($base_tags, $new_entities_cache_tags);
     $render_tags_page_1 = Cache::mergeTags($base_render_tags, $new_entities_cache_tags, ['entity_test_view']);
     $this->assertViewsCacheTags($view, $result_tags_page_1, $do_assert_views_caches, $render_tags_page_1);
-    $this->assertViewsCacheTagsFromStaticRenderArray($view, $render_tags_page_1, $do_assert_views_caches);
   }
 
   /**
@@ -278,11 +208,11 @@ protected function assertCacheTagsForEntityBasedView($do_assert_views_caches) {
   public function testBuildRenderableWithCacheContexts() {
     $view = View::load('test_view');
     $display =& $view->getDisplay('default');
-    $display['cache_metadata']['contexts'] = ['views_test_cache_context'];
+    $display['cache_metadata']['contexts'] = ['beatles'];
     $executable = $view->getExecutable();
 
     $build = $executable->buildRenderable();
-    $this->assertEqual(['views_test_cache_context'], $build['#cache']['contexts']);
+    $this->assertEqual(['beatles'], $build['#cache']['contexts']);
   }
 
   /**
@@ -292,7 +222,7 @@ public function testViewAddCacheMetadata() {
     $view = View::load('test_display');
     $view->save();
 
-    $this->assertEqual(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'url.query_args.pagers:0', 'user.node_grants:view', 'user.permissions'], $view->getDisplay('default')['cache_metadata']['contexts']);
+    $this->assertEqual(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'url.query_args.pagers:0', 'user.node_grants:view'], $view->getDisplay('default')['cache_metadata']['contexts']);
   }
 
 }
diff --git a/core/modules/views/src/Tests/ViewAjaxTest.php b/core/modules/views/src/Tests/ViewAjaxTest.php
index 35b5518..bb4c76c 100644
--- a/core/modules/views/src/Tests/ViewAjaxTest.php
+++ b/core/modules/views/src/Tests/ViewAjaxTest.php
@@ -54,14 +54,11 @@ public function testAjaxView() {
     $response = $this->drupalPost('views/ajax', 'application/vnd.drupal-ajax', $post);
     $data = Json::decode($response);
 
-    $this->assertTrue(isset($data[0]['settings']['views']['ajaxViews']));
-    $this->assertEqual($data[1]['command'], 'add_css');
-
     // Ensure that the view insert command is part of the result.
-    $this->assertEqual($data[2]['command'], 'insert');
-    $this->assertTrue(strpos($data[2]['selector'], '.js-view-dom-id-') === 0);
+    $this->assertEqual($data[1]['command'], 'insert');
+    $this->assertTrue(strpos($data[1]['selector'], '.js-view-dom-id-') === 0);
 
-    $this->setRawContent($data[2]['data']);
+    $this->setRawContent($data[1]['data']);
     $result = $this->xpath('//div[contains(@class, "views-row")]');
     $this->assertEqual(count($result), 2, 'Ensure that two items are rendered in the HTML.');
   }
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index d0ae414..d5cd460 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -406,8 +406,7 @@ class ViewExecutable implements \Serializable {
     '#attached' => [
       'library' => [],
       'drupalSettings' => [],
-    ],
-    '#cache' => [],
+    ]
   ];
 
   /**
@@ -491,33 +490,21 @@ public function setArguments(array $args) {
   }
 
   /**
-   * Expands the list of used cache contexts for the view.
-   *
-   * @param string $cache_context
-   *   The additional cache context.
-   *
-   * @return $this
-   */
-  public function addCacheContext($cache_context) {
-    $this->element['#cache']['contexts'][] = $cache_context;
-
-    return $this;
-  }
-
-  /**
    * Change/Set the current page for the pager.
    *
    * @param int $page
    *   The current page.
+   * @param bool $keep_cacheability
+   *   (optional) Keep the cacheability. By default we mark the view as not
+   *   cacheable. The reason for this parameter is that we do not know what the
+   *   passed in value varies by. For example, it could be per role. Defaults to
+   *   FALSE.
    */
-  public function setCurrentPage($page) {
+  public function setCurrentPage($page, $keep_cacheability = FALSE) {
     $this->current_page = $page;
 
-    // Calls like ::unserialize() might call this method without a proper $page.
-    // Also check whether the element is pre rendered. At that point, the cache
-    // keys cannot longer be manipulated.
-    if ($page !== NULL && empty($this->element['#pre_rendered'])) {
-      $this->element['#cache']['keys'][] = 'page:' . $page;
+    if (!$keep_cacheability) {
+      $this->element['#cache']['max-age'] = 0;
     }
 
     // If the pager is already initialized, pass it through to the pager.
@@ -559,15 +546,23 @@ public function getItemsPerPage() {
    *
    * @param int $items_per_page
    *   The items per page.
+   * @param bool $keep_cacheability
+   *   (optional) Keep the cacheability. By default we mark the view as not
+   *   cacheable. The reason for this parameter is that we do not know what the
+   *   passed in value varies by. For example, it could be per role. Defaults to
+   *   FALSE.
    */
-  public function setItemsPerPage($items_per_page) {
-    $this->element['#cache']['keys'][] = 'items_per_page:' . $items_per_page;
+  public function setItemsPerPage($items_per_page, $keep_cacheability = FALSE) {
     $this->items_per_page = $items_per_page;
 
     // If the pager is already initialized, pass it through to the pager.
     if (!empty($this->pager)) {
       $this->pager->setItemsPerPage($items_per_page);
     }
+
+    if (!$keep_cacheability) {
+      $this->element['#cache']['max-age'] = 0;
+    }
   }
 
   /**
@@ -589,15 +584,23 @@ public function getOffset() {
    *
    * @param int $offset
    *   The pager offset.
+   * @param bool $keep_cacheability
+   *   (optional) Keep the cacheability. By default we mark the view as not
+   *   cacheable. The reason for this parameter is that we do not know what the
+   *   passed in value varies by. For example, it could be per role. Defaults to
+   *   FALSE.
    */
-  public function setOffset($offset) {
-    $this->element['#cache']['keys'][] = 'offset:' . $offset;
+  public function setOffset($offset, $keep_cacheability = FALSE) {
     $this->offset = $offset;
 
     // If the pager is already initialized, pass it through to the pager.
     if (!empty($this->pager)) {
       $this->pager->setOffset($offset);
     }
+
+    if (!$keep_cacheability) {
+      $this->element['#cache']['max-age'] = 0;
+    }
   }
 
   /**
@@ -1376,60 +1379,72 @@ public function render($display_id = NULL) {
       $cache = FALSE;
     }
     else {
-      /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
       $cache = $this->display_handler->getPlugin('cache');
     }
 
-    // Run preRender for the pager as it might change the result.
-    if (!empty($this->pager)) {
-      $this->pager->preRender($this->result);
+    /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
+    if ($cache && $cache->cacheGet('output')) {
     }
+    else {
+      if ($cache) {
+        $cache->cacheStart();
+      }
 
-    // Initialize the style plugin.
-    $this->initStyle();
+      // Run preRender for the pager as it might change the result.
+      if (!empty($this->pager)) {
+        $this->pager->preRender($this->result);
+      }
 
-    if (!isset($this->response)) {
-      // Set the response so other parts can alter it.
-      $this->response = new Response('', 200);
-    }
+      // Initialize the style plugin.
+      $this->initStyle();
 
-    // Give field handlers the opportunity to perform additional queries
-    // using the entire resultset prior to rendering.
-    if ($this->style_plugin->usesFields()) {
-      foreach ($this->field as $id => $handler) {
-        if (!empty($this->field[$id])) {
-          $this->field[$id]->preRender($this->result);
+      if (!isset($this->response)) {
+        // Set the response so other parts can alter it.
+        $this->response = new Response('', 200);
+      }
+
+      // Give field handlers the opportunity to perform additional queries
+      // using the entire resultset prior to rendering.
+      if ($this->style_plugin->usesFields()) {
+        foreach ($this->field as $id => $handler) {
+          if (!empty($this->field[$id])) {
+            $this->field[$id]->preRender($this->result);
+          }
         }
       }
-    }
 
-    $this->style_plugin->preRender($this->result);
+      $this->style_plugin->preRender($this->result);
 
-    // Let each area handler have access to the result set.
-    $areas = array('header', 'footer');
-    // Only call preRender() on the empty handlers if the result is empty.
-    if (empty($this->result)) {
-      $areas[] = 'empty';
-    }
-    foreach ($areas as $area) {
-      foreach ($this->{$area} as $handler) {
-        $handler->preRender($this->result);
+      // Let each area handler have access to the result set.
+      $areas = array('header', 'footer');
+      // Only call preRender() on the empty handlers if the result is empty.
+      if (empty($this->result)) {
+        $areas[] = 'empty';
+      }
+      foreach ($areas as $area) {
+        foreach ($this->{$area} as $handler) {
+          $handler->preRender($this->result);
+        }
+      }
+
+      // Let modules modify the view just prior to rendering it.
+      $module_handler->invokeAll('views_pre_render', array($this));
+
+      // Let the themes play too, because pre render is a very themey thing.
+      foreach ($themes as $theme_name) {
+        $function = $theme_name . '_views_pre_render';
+        if (function_exists($function)) {
+          $function($this);
+        }
+      }
+
+      $this->display_handler->output = $this->display_handler->render();
+
+      if ($cache) {
+        $cache->cacheSet('output');
       }
     }
 
-    // Let modules modify the view just prior to rendering it.
-    $module_handler->invokeAll('views_pre_render', array($this));
-
-    // Let the themes play too, because pre render is a very themey thing.
-    foreach ($themes as $theme_name) {
-      $function = $theme_name . '_views_pre_render';
-      if (function_exists($function)) {
-        $function($this);
-      }
-    }
-
-    $this->display_handler->output = $this->display_handler->render();
-
     $exposed_form->postRender($this->display_handler->output);
 
     if ($cache) {
@@ -1477,14 +1492,12 @@ public function getCacheTags() {
    *   The display ID.
    * @param array $args
    *   An array of arguments passed along to the view.
-   * @param bool $cache
-   *   (optional) Should the result be render cached.
    *
    * @return array|null
    *   A renderable array with #type 'view' or NULL if the display ID was
    *   invalid.
    */
-  public function buildRenderable($display_id = NULL, $args = array(), $cache = TRUE) {
+  public function buildRenderable($display_id = NULL, $args = array()) {
     // @todo Extract that into a generic method.
     if (empty($this->current_display) || $this->current_display != $this->chooseDisplay($display_id)) {
       if (!$this->setDisplay($display_id)) {
@@ -1492,7 +1505,7 @@ public function buildRenderable($display_id = NULL, $args = array(), $cache = TR
       }
     }
 
-    return $this->display_handler->buildRenderable($args, $cache);
+    return $this->display_handler->buildRenderable($args);
   }
 
   /**
@@ -2386,7 +2399,7 @@ public function unserialize($serialized) {
 
     $this->setDisplay($current_display);
     $this->setArguments($args);
-    $this->setCurrentPage($current_page);
+    $this->setCurrentPage($current_page, TRUE);
     $this->setExposedInput($exposed_input);
     $this->exposed_data = $exposed_data;
     $this->exposed_raw_input = $exposed_raw_input;
diff --git a/core/modules/views/src/Views.php b/core/modules/views/src/Views.php
index 33570ae..747f2f8 100644
--- a/core/modules/views/src/Views.php
+++ b/core/modules/views/src/Views.php
@@ -194,47 +194,44 @@ public static function getEnabledDisplayExtenders() {
   }
 
   /**
-   * Return a list of all view IDs and display IDs that have a particular
+   * Return a list of all views and display IDs that have a particular
    * setting in their display's plugin settings.
    *
    * @param string $type
    *   A flag from the display plugin definitions (e.g, 'uses_menu_links').
    *
    * @return array
-   *   A list of arrays containing the $view_id and $display_id.
+   *   A list of arrays containing the $view and $display_id.
    * @code
    * array(
-   *   array($view_id, $display_id),
-   *   array($view_id, $display_id),
+   *   array($view, $display_id),
+   *   array($view, $display_id),
    * );
    * @endcode
    */
   public static function getApplicableViews($type) {
     // Get all display plugins which provides the type.
     $display_plugins = static::pluginManager('display')->getDefinitions();
-
-    $plugin_ids = [];
+    $ids = array();
     foreach ($display_plugins as $id => $definition) {
       if (!empty($definition[$type])) {
-        $plugin_ids[$id] = $id;
+        $ids[$id] = $id;
       }
     }
 
     $entity_ids = \Drupal::service('entity.query')->get('view')
       ->condition('status', TRUE)
-      ->condition("display.*.display_plugin", $plugin_ids, 'IN')
+      ->condition("display.*.display_plugin", $ids, 'IN')
       ->execute();
 
     $result = array();
     foreach (\Drupal::entityManager()->getStorage('view')->loadMultiple($entity_ids) as $view) {
       // Check each display to see if it meets the criteria and is enabled.
-
-      foreach ($view->get('display') as $id => $display) {
-        // If the key doesn't exist, enabled is assumed.
-        $enabled = !empty($display['display_options']['enabled']) || !array_key_exists('enabled', $display['display_options']);
-
-        if ($enabled && in_array($display['display_plugin'], $plugin_ids)) {
-          $result[] = [$view->id(), $id];
+      $executable = $view->getExecutable();
+      $executable->initDisplay();
+      foreach ($executable->displayHandlers as $id => $handler) {
+        if (!empty($handler->definition[$type]) && $handler->isEnabled()) {
+          $result[] = array($executable, $id);
         }
       }
     }
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_fields.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_fields.yml
index 150926c..0f589a1 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_fields.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_fields.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
@@ -51,15 +51,6 @@ display:
           plugin_id: standard
           entity_type: entity_test
           entity_field: name
-      arguments:
-        id:
-          id: id
-          table: entity_test
-          field: id
-          plugin_id: numeric
-          entity_type: entity_test
-          entity_field: id
-          default_action: 'ignore'
       sorts:
         id:
           table: entity_test
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_row.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_row.yml
index ee4578f..4bd0503 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_row.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.entity_test_row.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       sorts:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.numeric_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.numeric_test.yml
index 8593665..e8e99ad 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.numeric_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.numeric_test.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'administer views'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_access_none.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_access_none.yml
index 72be69b..6b267be 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_access_none.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_access_none.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_aggregate_count.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_aggregate_count.yml
index c8e9488..1116bcb 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_aggregate_count.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_aggregate_count.yml
@@ -27,7 +27,7 @@ display:
           entity_type: entity_test
           entity_field: name
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_alias.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_alias.yml
index 1dce6dc..da36f2f 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_alias.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_alias.yml
@@ -19,7 +19,7 @@ display:
           perm: 'access user profiles'
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_current_user.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_current_user.yml
index e5e4af4..cd481fa 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_current_user.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_current_user.yml
@@ -26,7 +26,7 @@ display:
           entity_type: node
           entity_field: uid
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_fixed.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_fixed.yml
index c1456f6..4b4f296 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_fixed.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_fixed.yml
@@ -26,7 +26,7 @@ display:
           table: views
           plugin_id: 'null'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml
index c6b72e3..f406543 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_dependency.yml
@@ -32,7 +32,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attached_disabled.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attached_disabled.yml
index 1dd5edc..d07216f 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attached_disabled.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attached_disabled.yml
@@ -26,7 +26,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attachment_ui.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attachment_ui.yml
index 17bcdb7..89089c2 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attachment_ui.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_attachment_ui.yml
@@ -19,7 +19,7 @@ display:
         options:
           perm: 'views_test_data test permission'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
index f5ada7a..82d10ad 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
@@ -33,7 +33,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       style:
         type: table
         options:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml
index bf0df9a..47bd959 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_destroy.yml
@@ -41,7 +41,7 @@ display:
           plugin_id: date_month
           entity_type: node
       cache:
-        type: tag
+        type: none
       empty:
         area:
           empty: false
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_disabled_display.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_disabled_display.yml
index c8de50a..c0c45c3 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_disabled_display.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_disabled_display.yml
@@ -26,7 +26,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml
index 8936310..9a0b910 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_attachment.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_attachment.yml
index 615ae8c..715158c 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_attachment.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_attachment.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_defaults.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_defaults.yml
index b969c34..224019c 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_defaults.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_defaults.yml
@@ -20,7 +20,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_feed.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_feed.yml
index 452d934..1f8dbc9 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_feed.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display_feed.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_dropbutton.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_dropbutton.yml
index e7a2760..3e5fcea 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_dropbutton.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_dropbutton.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_operations.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_operations.yml
index 9ccd9a9..ee58e8b 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_operations.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_operations.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_link.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_link.yml
index 509826c..8eb7a42 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_link.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_link.yml
@@ -22,7 +22,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml
index 6894d76..55f5b1c 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml
@@ -25,7 +25,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area.yml
index baa055c..b90c153 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       header:
         test_example:
           field: test_example
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area_access.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area_access.yml
index ab27d07..2ec7214 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area_access.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_example_area_access.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       empty:
         test_example:
           field: test_example
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_admin_ui.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_admin_ui.yml
index db16bcb..32b0692 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_admin_ui.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_admin_ui.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         options:
           reset_button: true
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml
index be96ab4..3818532 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         options:
           reset_button: true
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml
index d33174a..bed02ca 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         options:
           reset_button: true
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_sort_items_per_page.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_sort_items_per_page.yml
index d7d2d93..f2d3364 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_sort_items_per_page.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_sort_items_per_page.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         options:
           expose_sort_order: true
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_feed_icon.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_feed_icon.yml
index a5bb9f5..dc81943 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_feed_icon.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_feed_icon.yml
@@ -27,7 +27,7 @@ display:
           role:
             authenticated: authenticated
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_alias_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_alias_test.yml
index 0c72f88..6e178cc 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_alias_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_alias_test.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         id:
           id: id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_classes.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_classes.yml
index 28b3dad..2480aa3 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_classes.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_classes.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         id:
           id: id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml
index 869d282..58ee430 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         id:
           id: id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml
index 7680027..b0122a3 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         id:
           id: id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
index d1e5c50..d85d4d1 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         id:
           id: id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_test.yml
index 49a88cf..aa37836 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_test.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         id:
           id: id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_get_entity.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_get_entity.yml
index cc3b66c..3613335 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_get_entity.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_get_entity.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_output.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_output.yml
index 8b3ae47..c3d2bc1 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_output.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_output.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       fields:
         name:
           id: name
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_tokens.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_tokens.yml
index 2a2626c..718b27c 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_tokens.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_tokens.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter.yml
index c6f9807..86313c1 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
index 47556800..16afa71 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_date_between.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_group_override.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_group_override.yml
index 7734d1c..85c4de2 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_group_override.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_group_override.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_groups.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_groups.yml
index 6ea46a9..4d57f77 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_groups.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_groups.yml
@@ -18,7 +18,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
index ef0188a..66520dc 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
@@ -14,7 +14,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       filters:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_get_attach_displays.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_get_attach_displays.yml
index 608efa0..6116e77 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_get_attach_displays.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_get_attach_displays.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml
index bf44f36..1e8af98 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml
@@ -34,7 +34,7 @@ display:
           entity_type: node
           entity_field: title
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count.yml
index c6aba49..4d4dd56 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count_multicardinality.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count_multicardinality.yml
index c295db5..6be6793 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count_multicardinality.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_count_multicardinality.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_in_filters.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_in_filters.yml
index da6a676..173a0e8 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_in_filters.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_by_in_filters.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_rows.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_rows.yml
index 2c34841..4dffd05 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_rows.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_group_rows.yml
@@ -26,7 +26,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_groupwise_term_ui.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_groupwise_term_ui.yml
index c29fb52..cfff08e 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_groupwise_term_ui.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_groupwise_term_ui.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml
index 900852b..92962d7 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml
@@ -23,7 +23,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_http_status_code.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_http_status_code.yml
index 9183682..83192b8 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_http_status_code.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_http_status_code.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager.yml
index e65ea4a..843b492 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full.yml
index 68dae03..01fe100 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_none.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_none.yml
index 9757036..7b11e9e 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_none.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_none.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_some.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_some.yml
index 29dccf4..156e7dd 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_some.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_some.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_plugin_dependencies.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_plugin_dependencies.yml
index 21877c9..86f4189 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_plugin_dependencies.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_plugin_dependencies.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: test_static
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_preview.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_preview.yml
index d0c26bf..9461d01 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_preview.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_preview.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_redirect_view.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_redirect_view.yml
index 723d934..b3c5c70 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_redirect_view.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_redirect_view.yml
@@ -22,7 +22,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_relationship_dependency.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_relationship_dependency.yml
index f392a52..dbbbf16 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_relationship_dependency.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_relationship_dependency.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_row_render_cache.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_row_render_cache.yml
index 28a1812..d0d5ebf 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_row_render_cache.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_row_render_cache.yml
@@ -24,7 +24,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_search.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_search.yml
index f0448aa..91767f9 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_search.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_search.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_store_pager_settings.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_store_pager_settings.yml
index 1b6bc95..bae5768 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_store_pager_settings.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_store_pager_settings.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_html_list.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_html_list.yml
index 99f9bfc..35a0496 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_html_list.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_html_list.yml
@@ -20,7 +20,7 @@ display:
         type: none
         options: {  }
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml
index 2764a8f..6c631b3 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_style_opml.yml
@@ -21,7 +21,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_ungroup_rows.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_ungroup_rows.yml
index 3acfc42..cafeae9 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_ungroup_rows.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_ungroup_rows.yml
@@ -25,7 +25,7 @@ display:
       access:
         type: perm
       cache:
-        type: tag
+        type: none
       query:
         type: views_query
       exposed_form:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_argument_validate_numeric.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_argument_validate_numeric.yml
index 7337fcc..865bca9 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_argument_validate_numeric.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_argument_validate_numeric.yml
@@ -25,7 +25,7 @@ display:
             type: numeric
           plugin_id: 'null'
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_delete.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_delete.yml
index fb2cff3..4ee2b75 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_delete.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_delete.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test.yml
index 48df3dd..ab61fbc 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_additional_base_field.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_additional_base_field.yml
index a1cb151..c3921a1 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_additional_base_field.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_additional_base_field.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_data.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_data.yml
index 5492480..6ccd8be 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_data.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_data.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_revision.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_revision.yml
index 8a5a477..ec4649f 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_revision.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_entity_test_revision.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml
index 82be894..a5be547 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml
@@ -17,7 +17,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       fields:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_views_groupby_save.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_views_groupby_save.yml
index a95fca3..11533bd 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_views_groupby_save.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_views_groupby_save.yml
@@ -15,7 +15,7 @@ display:
       access:
         type: none
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php
index 173e857..20bf579 100644
--- a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php
+++ b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php
@@ -10,7 +10,6 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\Plugin\views\query\QueryPluginBase;
 use Drupal\views\Plugin\views\join\JoinPluginBase;
-use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
 
 /**
@@ -115,7 +114,7 @@ public function execute(ViewExecutable $view) {
         if ($this->fields) {
           $element = array_intersect_key($element, $this->fields);
         }
-        $result[] = new ResultRow($element);
+        $result[] = (object) $element;
       }
     }
     $this->view->result = $result;
diff --git a/core/modules/views/tests/modules/views_test_data/test_views/views.view.test_access_static.yml b/core/modules/views/tests/modules/views_test_data/test_views/views.view.test_access_static.yml
index 6f2ff35..b79f068 100644
--- a/core/modules/views/tests/modules/views_test_data/test_views/views.view.test_access_static.yml
+++ b/core/modules/views/tests/modules/views_test_data/test_views/views.view.test_access_static.yml
@@ -19,7 +19,7 @@ display:
       access:
         type: test_static
       cache:
-        type: tag
+        type: none
       exposed_form:
         type: basic
       pager:
diff --git a/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php b/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php
index d5c0054..9be3036 100644
--- a/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php
+++ b/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php
@@ -186,9 +186,9 @@ protected function setupMocks() {
     $executable->displayHandlers = $display_collection;
 
     $this->routeSubscriber->applicableViews = array();
-    $this->routeSubscriber->applicableViews[] = array('test_id', 'page_1');
-    $this->routeSubscriber->applicableViews[] = array('test_id', 'page_2');
-    $this->routeSubscriber->applicableViews[] = array('test_id', 'page_3');
+    $this->routeSubscriber->applicableViews[] = array($executable, 'page_1');
+    $this->routeSubscriber->applicableViews[] = array($executable, 'page_2');
+    $this->routeSubscriber->applicableViews[] = array($executable, 'page_3');
 
     return array($executable, $view, $display_1, $display_2);
   }
diff --git a/core/modules/views/tests/src/Unit/Plugin/Block/ViewsBlockTest.php b/core/modules/views/tests/src/Unit/Plugin/Block/ViewsBlockTest.php
index 50b4490..a7282c7 100644
--- a/core/modules/views/tests/src/Unit/Plugin/Block/ViewsBlockTest.php
+++ b/core/modules/views/tests/src/Unit/Plugin/Block/ViewsBlockTest.php
@@ -58,13 +58,6 @@ class ViewsBlockTest extends UnitTestCase {
   protected $account;
 
   /**
-   * The mocked display handler.
-   *
-   * @var \Drupal\views\Plugin\views\display\Block|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $displayHandler;
-
-  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -85,9 +78,6 @@ protected function setUp() {
       ->method('setDisplay')
       ->with('block_1')
       ->will($this->returnValue(TRUE));
-    $this->executable->expects($this->any())
-      ->method('getShowAdminLinks')
-      ->willReturn(FALSE);
 
     $this->executable->display_handler = $this->getMockBuilder('Drupal\views\Plugin\views\display\Block')
       ->disableOriginalConstructor()
@@ -97,10 +87,6 @@ protected function setUp() {
     $this->view = $this->getMockBuilder('Drupal\views\Entity\View')
       ->disableOriginalConstructor()
       ->getMock();
-    $this->view->expects($this->any())
-      ->method('id')
-      ->willReturn('test_view');
-    $this->executable->storage = $this->view;
 
     $this->executableFactory = $this->getMockBuilder('Drupal\views\ViewExecutableFactory')
       ->disableOriginalConstructor()
@@ -110,19 +96,6 @@ protected function setUp() {
       ->with($this->view)
       ->will($this->returnValue($this->executable));
 
-    $this->displayHandler = $this->getMockBuilder('Drupal\views\Plugin\views\display\Block')
-      ->disableOriginalConstructor()
-      ->getMock();
-
-    $this->displayHandler->expects($this->any())
-      ->method('blockSettings')
-      ->willReturn([]);
-
-    $this->displayHandler->expects($this->any())
-      ->method('getPluginId')
-      ->willReturn('block');
-    $this->executable->display_handler = $this->displayHandler;
-
     $this->storage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
       ->disableOriginalConstructor()
       ->getMock();
@@ -141,7 +114,7 @@ protected function setUp() {
    */
   public function testBuild() {
     $output = $this->randomMachineName(100);
-    $build = array('#markup' => $output, '#view_id' => 'test_view', '#view_display_plugin_class' => '\Drupal\views\Plugin\views\display\Block', '#view_display_show_admin_links' => FALSE, '#view_display_plugin_id' => 'block');
+    $build = array('#markup' => $output);
     $this->executable->expects($this->once())
       ->method('buildRenderable')
       ->with('block_1', [])
diff --git a/core/modules/views/tests/src/Unit/Plugin/Derivative/ViewsLocalTaskTest.php b/core/modules/views/tests/src/Unit/Plugin/Derivative/ViewsLocalTaskTest.php
index af9a683..c75d96f 100644
--- a/core/modules/views/tests/src/Unit/Plugin/Derivative/ViewsLocalTaskTest.php
+++ b/core/modules/views/tests/src/Unit/Plugin/Derivative/ViewsLocalTaskTest.php
@@ -32,11 +32,6 @@ class ViewsLocalTaskTest extends UnitTestCase {
    */
   protected $state;
 
-  /**
-   * @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $viewStorage;
-
   protected $baseDefinition = array(
     'class' => '\Drupal\views\Plugin\Menu\LocalTask\ViewsLocalTask',
     'deriver' => '\Drupal\views\Plugin\Derivative\ViewsLocalTask'
@@ -52,9 +47,8 @@ class ViewsLocalTaskTest extends UnitTestCase {
   protected function setUp() {
     $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
     $this->state = $this->getMock('Drupal\Core\State\StateInterface');
-    $this->viewStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
 
-    $this->localTaskDerivative = new TestViewsLocalTask($this->routeProvider, $this->state, $this->viewStorage);
+    $this->localTaskDerivative = new TestViewsLocalTask($this->routeProvider, $this->state);
   }
 
   /**
@@ -87,22 +81,7 @@ public function testGetDerivativeDefinitionsWithoutLocalTask() {
       ->will($this->returnValue(array('type' => 'normal')));
     $executable->display_handler = $display_plugin;
 
-    $storage = $this->getMockBuilder('Drupal\views\Entity\View')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $storage->expects($this->any())
-      ->method('id')
-      ->will($this->returnValue('example_view'));
-    $storage->expects($this->any())
-      ->method('getExecutable')
-      ->willReturn($executable);
-
-    $this->viewStorage->expects($this->any())
-      ->method('load')
-      ->with('example_view')
-      ->willReturn($storage);
-
-    $result = [['example_view', 'page_1']];
+    $result = array(array($executable, 'page_1'));
     $this->localTaskDerivative->setApplicableMenuViews($result);
 
     $definitions = $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
@@ -122,16 +101,8 @@ public function testGetDerivativeDefinitionsWithLocalTask() {
     $storage->expects($this->any())
       ->method('id')
       ->will($this->returnValue('example_view'));
-    $storage->expects($this->any())
-      ->method('getExecutable')
-      ->willReturn($executable);
     $executable->storage = $storage;
 
-    $this->viewStorage->expects($this->any())
-      ->method('load')
-      ->with('example_view')
-      ->willReturn($storage);
-
     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
       ->setMethods(array('getOption'))
       ->disableOriginalConstructor()
@@ -142,7 +113,7 @@ public function testGetDerivativeDefinitionsWithLocalTask() {
       ->will($this->returnValue(array('type' => 'tab', 'weight' => 12, 'title' => 'Example title')));
     $executable->display_handler = $display_plugin;
 
-    $result = [['example_view', 'page_1']];
+    $result = array(array($executable, 'page_1'));
     $this->localTaskDerivative->setApplicableMenuViews($result);
 
     // Mock the view route names state.
@@ -175,16 +146,8 @@ public function testGetDerivativeDefinitionsWithOverrideRoute() {
     $storage->expects($this->any())
       ->method('id')
       ->will($this->returnValue('example_view'));
-    $storage->expects($this->any())
-      ->method('getExecutable')
-      ->willReturn($executable);
     $executable->storage = $storage;
 
-    $this->viewStorage->expects($this->any())
-      ->method('load')
-      ->with('example_view')
-      ->willReturn($storage);
-
     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
       ->setMethods(array('getOption'))
       ->disableOriginalConstructor()
@@ -195,7 +158,7 @@ public function testGetDerivativeDefinitionsWithOverrideRoute() {
       ->will($this->returnValue(array('type' => 'tab', 'weight' => 12)));
     $executable->display_handler = $display_plugin;
 
-    $result = [['example_view', 'page_1']];
+    $result = array(array($executable, 'page_1'));
     $this->localTaskDerivative->setApplicableMenuViews($result);
 
     // Mock the view route names state.
@@ -224,16 +187,8 @@ public function testGetDerivativeDefinitionsWithDefaultLocalTask() {
     $storage->expects($this->any())
       ->method('id')
       ->will($this->returnValue('example_view'));
-    $storage->expects($this->any())
-      ->method('getExecutable')
-      ->willReturn($executable);
     $executable->storage = $storage;
 
-    $this->viewStorage->expects($this->any())
-      ->method('load')
-      ->with('example_view')
-      ->willReturn($storage);
-
     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
       ->setMethods(array('getOption'))
       ->disableOriginalConstructor()
@@ -244,7 +199,7 @@ public function testGetDerivativeDefinitionsWithDefaultLocalTask() {
       ->will($this->returnValue(array('type' => 'default tab', 'weight' => 12, 'title' => 'Example title')));
     $executable->display_handler = $display_plugin;
 
-    $result = [['example_view', 'page_1']];
+    $result = array(array($executable, 'page_1'));
     $this->localTaskDerivative->setApplicableMenuViews($result);
 
     // Mock the view route names state.
@@ -293,16 +248,8 @@ public function testGetDerivativeDefinitionsWithExistingLocalTask() {
     $storage->expects($this->any())
       ->method('id')
       ->will($this->returnValue('example_view'));
-    $storage->expects($this->any())
-      ->method('getExecutable')
-      ->willReturn($executable);
     $executable->storage = $storage;
 
-    $this->viewStorage->expects($this->any())
-      ->method('load')
-      ->with('example_view')
-      ->willReturn($storage);
-
     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
       ->setMethods(array('getOption', 'getPath'))
       ->disableOriginalConstructor()
@@ -316,7 +263,7 @@ public function testGetDerivativeDefinitionsWithExistingLocalTask() {
       ->will($this->returnValue('path/example'));
     $executable->display_handler = $display_plugin;
 
-    $result = [['example_view', 'page_1']];
+    $result = array(array($executable, 'page_1'));
     $this->localTaskDerivative->setApplicableMenuViews($result);
 
     // Mock the view route names state.
diff --git a/core/modules/views/tests/src/Unit/Plugin/display/PageTest.php b/core/modules/views/tests/src/Unit/Plugin/display/PageTest.php
deleted file mode 100644
index 3592780..0000000
--- a/core/modules/views/tests/src/Unit/Plugin/display/PageTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\views\Unit\Plugin\display\PageTest.
- */
-
-namespace Drupal\Tests\views\Unit\Plugin\display;
-
-use Drupal\Tests\UnitTestCase;
-use Drupal\views\Plugin\views\display\Page;
-use Symfony\Component\Routing\Route;
-
-/**
- * @coversDefaultClass \Drupal\views\Plugin\views\display\Page
- * @group views
- */
-class PageTest extends UnitTestCase {
-
-  /**
-   * @covers ::buildBasicRenderable
-   */
-  public function testBuildBasicRenderable() {
-    $route = new Route('/test-view');
-    $route->setDefault('view_id', 'test_view');
-    $route->setOption('_view_display_plugin_id', 'page');
-    $route->setOption('_view_display_show_admin_links', TRUE);
-
-    $result = Page::buildBasicRenderable('test_view', 'page_1', [], $route);
-
-    $this->assertEquals('test_view', $result['#view_id']);
-    $this->assertEquals('page', $result['#view_display_plugin_id']);
-    $this->assertEquals(TRUE, $result['#view_display_show_admin_links']);
-  }
-
-  /**
-   * @covers ::buildBasicRenderable
-   * @expectedException \BadFunctionCallException
-   */
-  public function testBuildBasicRenderableWithMissingRoute() {
-    Page::buildBasicRenderable('test_view', 'page_1', []);
-  }
-
-}
diff --git a/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php b/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php
index b0ebe13..0cc643a 100644
--- a/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php
+++ b/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php
@@ -28,7 +28,7 @@ class PathPluginBaseTest extends UnitTestCase {
   /**
    * The tested path plugin base.
    *
-   * @var \Drupal\views\Plugin\views\display\PathPluginBase|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\views\Plugin\views\display\PathPluginBase
    */
   protected $pathPlugin;
 
@@ -107,90 +107,6 @@ public function testCollectRoutes() {
     $this->assertTrue($route instanceof Route);
     $this->assertEquals('test_id', $route->getDefault('view_id'));
     $this->assertEquals('page_1', $route->getDefault('display_id'));
-    $this->assertSame(FALSE, $route->getOption('returns_response'));
-  }
-
-  /**
-   * Tests the collectRoutes method with a display returning a response.
-   *
-   * @see \Drupal\views\Plugin\views\display\PathPluginBase::collectRoutes()
-   */
-  public function testCollectRoutesWithDisplayReturnResponse() {
-    list($view) = $this->setupViewExecutableAccessPlugin();
-
-    $display = array();
-    $display['display_plugin'] = 'page';
-    $display['id'] = 'page_1';
-    $display['display_options'] = array(
-      'path' => 'test_route',
-    );
-    $this->pathPlugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
-      ->setConstructorArgs(array(array(), 'path_base', array('returns_response' => TRUE), $this->routeProvider, $this->state))
-      ->setMethods(NULL)
-      ->getMock();
-    $this->pathPlugin->initDisplay($view, $display);
-
-    $collection = new RouteCollection();
-    $this->pathPlugin->collectRoutes($collection);
-    $route = $collection->get('view.test_id.page_1');
-    $this->assertSame(TRUE, $route->getOption('returns_response'));
-  }
-
-  /**
-   * Tests the collectRoutes method with arguments.
-   *
-   * @see \Drupal\views\Plugin\views\display\PathPluginBase::collectRoutes()
-   */
-  public function testCollectRoutesWithArguments() {
-    list($view) = $this->setupViewExecutableAccessPlugin();
-
-    $display = array();
-    $display['display_plugin'] = 'page';
-    $display['id'] = 'page_1';
-    $display['display_options'] = array(
-      'path' => 'test_route/%/example',
-    );
-    $this->pathPlugin->initDisplay($view, $display);
-
-    $collection = new RouteCollection();
-    $result = $this->pathPlugin->collectRoutes($collection);
-    $this->assertEquals(array('test_id.page_1' => 'view.test_id.page_1'), $result);
-
-    $route = $collection->get('view.test_id.page_1');
-    $this->assertTrue($route instanceof Route);
-    $this->assertEquals('test_id', $route->getDefault('view_id'));
-    $this->assertEquals('page_1', $route->getDefault('display_id'));
-    $this->assertEquals(array('arg_0' => 'arg_0'), $route->getOption('_view_argument_map'));
-  }
-
-  /**
-   * Tests the collectRoutes method with arguments not specified in the path.
-   *
-   * @see \Drupal\views\Plugin\views\display\PathPluginBase::collectRoutes()
-   */
-  public function testCollectRoutesWithArgumentsNotSpecifiedInPath() {
-    list($view) = $this->setupViewExecutableAccessPlugin();
-
-    $display = array();
-    $display['display_plugin'] = 'page';
-    $display['id'] = 'page_1';
-    $display['display_options'] = array(
-      'path' => 'test_with_arguments',
-    );
-    $display['display_options']['arguments'] = array(
-      'test_id' => array(),
-    );
-    $this->pathPlugin->initDisplay($view, $display);
-
-    $collection = new RouteCollection();
-    $result = $this->pathPlugin->collectRoutes($collection);
-    $this->assertEquals(array('test_id.page_1' => 'view.test_id.page_1'), $result);
-
-    $route = $collection->get('view.test_id.page_1');
-    $this->assertTrue($route instanceof Route);
-    $this->assertEquals('test_id', $route->getDefault('view_id'));
-    $this->assertEquals('page_1', $route->getDefault('display_id'));
-    $this->assertEquals(array('arg_0' => 'arg_0'), $route->getOption('_view_argument_map'));
   }
 
   /**
diff --git a/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php b/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php
index d39ef33..3197aae 100644
--- a/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php
+++ b/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php
@@ -43,18 +43,6 @@ class ViewPageControllerTest extends UnitTestCase {
    */
   protected $executableFactory;
 
-  /**
-   * A render array expected for every page controller render array result.
-   *
-   * @var array
-   */
-  protected $defaultRenderArray = [
-    '#cache_properties' => ['#view_id', '#view_display_show_admin_links', '#view_display_plugin_id'],
-    '#view_id' => 'test_page_view',
-    '#view_display_plugin_id' => NULL,
-    '#view_display_show_admin_links' => NULL,
-  ];
-
   protected function setUp() {
     $this->storage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
       ->disableOriginalConstructor()
@@ -70,30 +58,52 @@ protected function setUp() {
    * Tests the page controller.
    */
   public function testPageController() {
-    $this->storage->expects($this->never())
-      ->method('load');
+    $view = $this->getMock('Drupal\views\ViewEntityInterface');
+
+    $this->storage->expects($this->once())
+      ->method('load')
+      ->with('test_page_view')
+      ->will($this->returnValue($view));
+
+    $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->expects($this->once())
+      ->method('setDisplay')
+      ->with('default');
+    $executable->expects($this->once())
+      ->method('initHandlers');
+
+    $views_display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $views_display->expects($this->any())
+      ->method('getDefinition')
+      ->willReturn([]);
+    $executable->display_handler = $views_display;
 
     $build = [
       '#type' => 'view',
       '#name' => 'test_page_view',
-      '#display_id' => 'default',
-      '#embed' => FALSE,
-      '#arguments' => [],
-      '#cache' => [
-        'keys' => ['view', 'test_page_view', 'display', 'default'],
-      ],
-    ] + $this->defaultRenderArray;
+      '#display_id' => 'default'
+    ];
+    $executable->expects($this->once())
+      ->method('buildRenderable')
+      ->with('default', [])
+      ->will($this->returnValue($build));
+
+    $this->executableFactory->expects($this->any())
+      ->method('get')
+      ->with($view)
+      ->will($this->returnValue($executable));
 
     $request = new Request();
     $request->attributes->set('view_id', 'test_page_view');
     $request->attributes->set('display_id', 'default');
-    $options = [
-      '_view_display_plugin_class' => '\Drupal\views\Plugin\views\display\Page',
-    ];
-    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test', ['view_id' => 'test_page_view', 'display_id' => 'default'], [], $options));
+    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test', ['view_id' => 'test_page_view', 'display_id' => 'default']));
     $route_match = RouteMatch::createFromRequest($request);
 
-    $output = $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $route_match);
+    $output = $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $request, $route_match);
     $this->assertInternalType('array', $output);
     $this->assertEquals($build, $output);
   }
@@ -102,35 +112,54 @@ public function testPageController() {
    * Tests the page controller with arguments on a non overridden page view.
    */
   public function testHandleWithArgumentsWithoutOverridden() {
-    $this->storage->expects($this->never())
-      ->method('load');
+    $view = $this->getMock('Drupal\views\ViewEntityInterface');
+
+    $this->storage->expects($this->once())
+      ->method('load')
+      ->with('test_page_view')
+      ->will($this->returnValue($view));
+
+    $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->expects($this->once())
+      ->method('setDisplay')
+      ->with('page_1');
+    $executable->expects($this->once())
+      ->method('initHandlers');
+
+    $views_display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $views_display->expects($this->any())
+      ->method('getDefinition')
+      ->willReturn([]);
+    $executable->display_handler = $views_display;
+
+    // Manually setup a argument handler.
+    $argument = $this->getMockBuilder('Drupal\views\Plugin\views\argument\ArgumentPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->argument['test_id'] = $argument;
+
+    $executable->expects($this->once())
+      ->method('buildRenderable')
+      ->with('page_1', array('test-argument'));
+
+    $this->executableFactory->expects($this->any())
+      ->method('get')
+      ->with($view)
+      ->will($this->returnValue($executable));
 
     $request = new Request();
     $request->attributes->set('view_id', 'test_page_view');
     $request->attributes->set('display_id', 'page_1');
     // Add the argument to the request.
     $request->attributes->set('arg_0', 'test-argument');
-    $options = [
-      '_view_argument_map' => ['arg_0' => 'arg_0'],
-      '_view_display_plugin_class' => '\Drupal\views\Plugin\views\display\Page',
-    ];
-    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test/{arg_0}', ['view_id' => 'test_page_view', 'display_id' => 'default'], [], $options));
+    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test/{arg_0}', ['view_id' => 'test_page_view', 'display_id' => 'default']));
     $route_match = RouteMatch::createFromRequest($request);
 
-    $result = $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $route_match);
-
-    $build = [
-      '#type' => 'view',
-      '#name' => 'test_page_view',
-      '#display_id' => 'page_1',
-      '#embed' => FALSE,
-      '#arguments' => ['test-argument'],
-      '#cache' => [
-        'keys' => ['view', 'test_page_view', 'display', 'page_1', 'args', 'test-argument'],
-      ],
-    ] + $this->defaultRenderArray;
-
-    $this->assertEquals($build, $result);
+    $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $request, $route_match);
   }
 
   /**
@@ -139,37 +168,56 @@ public function testHandleWithArgumentsWithoutOverridden() {
    * Note: This test does not care about upcasting for now.
    */
   public function testHandleWithArgumentsOnOverriddenRoute() {
-    $this->storage->expects($this->never())
-      ->method('load');
+    $view = $this->getMock('Drupal\views\ViewEntityInterface');
+
+    $this->storage->expects($this->once())
+      ->method('load')
+      ->with('test_page_view')
+      ->will($this->returnValue($view));
+
+    $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->expects($this->once())
+      ->method('setDisplay')
+      ->with('page_1');
+    $executable->expects($this->once())
+      ->method('initHandlers');
+
+    $views_display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $views_display->expects($this->any())
+      ->method('getDefinition')
+      ->willReturn([]);
+    $executable->display_handler = $views_display;
+
+    // Manually setup a argument handler.
+    $argument = $this->getMockBuilder('Drupal\views\Plugin\views\argument\ArgumentPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->argument['test_id'] = $argument;
+
+    $executable->expects($this->once())
+      ->method('buildRenderable')
+      ->with('page_1', array('test-argument'));
+
+    $this->executableFactory->expects($this->any())
+      ->method('get')
+      ->with($view)
+      ->will($this->returnValue($executable));
 
     $request = new Request();
     $request->attributes->set('view_id', 'test_page_view');
     $request->attributes->set('display_id', 'page_1');
     // Add the argument to the request.
     $request->attributes->set('parameter', 'test-argument');
-    $options = [
-      '_view_argument_map' => [
-        'arg_0' => 'parameter',
-      ],
-      '_view_display_plugin_class' => '\Drupal\views\Plugin\views\display\Page',
-    ];
-    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test/{parameter}', ['view_id' => 'test_page_view', 'display_id' => 'default'], [], $options));
+    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test/{parameter}', ['view_id' => 'test_page_view', 'display_id' => 'default'], [], ['_view_argument_map' => [
+      'arg_0' => 'parameter',
+    ]]));
     $route_match = RouteMatch::createFromRequest($request);
 
-    $result = $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $route_match);
-
-    $build = [
-      '#type' => 'view',
-      '#name' => 'test_page_view',
-      '#display_id' => 'page_1',
-      '#embed' => FALSE,
-      '#arguments' => ['test-argument'],
-      '#cache' => [
-        'keys' => ['view', 'test_page_view', 'display', 'page_1', 'args', 'test-argument'],
-      ],
-      ] + $this->defaultRenderArray;
-
-    $this->assertEquals($build, $result);
+    $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $request, $route_match);
   }
 
   /**
@@ -179,8 +227,44 @@ public function testHandleWithArgumentsOnOverriddenRoute() {
    * are pulled in.
    */
   public function testHandleWithArgumentsOnOverriddenRouteWithUpcasting() {
-    $this->storage->expects($this->never())
-      ->method('load');
+    $view = $this->getMock('Drupal\views\ViewEntityInterface');
+
+    $this->storage->expects($this->once())
+      ->method('load')
+      ->with('test_page_view')
+      ->will($this->returnValue($view));
+
+    $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->expects($this->once())
+      ->method('setDisplay')
+      ->with('page_1');
+    $executable->expects($this->once())
+      ->method('initHandlers');
+
+    $views_display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $views_display->expects($this->any())
+      ->method('getDefinition')
+      ->willReturn([]);
+    $executable->display_handler = $views_display;
+
+    // Manually setup a argument handler.
+    $argument = $this->getMockBuilder('Drupal\views\Plugin\views\argument\ArgumentPluginBase')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $executable->argument['test_id'] = $argument;
+
+    $executable->expects($this->once())
+      ->method('buildRenderable')
+      ->with('page_1', array('example_id'));
+
+    $this->executableFactory->expects($this->any())
+      ->method('get')
+      ->with($view)
+      ->will($this->returnValue($executable));
 
     $request = new Request();
     $request->attributes->set('view_id', 'test_page_view');
@@ -189,29 +273,29 @@ public function testHandleWithArgumentsOnOverriddenRouteWithUpcasting() {
     $request->attributes->set('test_entity', $this->getMock('Drupal\Core\Entity\EntityInterface'));
     $raw_variables = new ParameterBag(array('test_entity' => 'example_id'));
     $request->attributes->set('_raw_variables', $raw_variables);
-    $options = [
-      '_view_argument_map' => [
-        'arg_0' => 'test_entity',
-      ],
-      '_view_display_plugin_class' => '\Drupal\views\Plugin\views\display\Page',
-    ];
-    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test/{test_entity}', ['view_id' => 'test_page_view', 'display_id' => 'default'], [], $options));
+    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/test/{test_entity}', ['view_id' => 'test_page_view', 'display_id' => 'default'], [], ['_view_argument_map' => [
+      'arg_0' => 'test_entity',
+    ]]));
     $route_match = RouteMatch::createFromRequest($request);
 
-    $result = $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $route_match);
+    $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $request, $route_match);
+  }
 
-    $build = [
-      '#type' => 'view',
-      '#name' => 'test_page_view',
-      '#display_id' => 'page_1',
-      '#embed' => FALSE,
-      '#arguments' => ['example_id'],
-      '#cache' => [
-        'keys' => ['view', 'test_page_view', 'display', 'page_1', 'args', 'example_id'],
-      ],
-      ] + $this->defaultRenderArray;
+  /**
+   * Tests handle with a non existing view.
+   *
+   * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+   */
+  public function testHandleWithNotExistingView() {
+    // Pass in a non existent view.
+    $random_view_id = $this->randomMachineName();
 
-    $this->assertEquals($build, $result);
+    $request = new Request();
+    $request->attributes->set('view_id', $random_view_id);
+    $request->attributes->set('display_id', 'default');
+    $route_match = RouteMatch::createFromRequest($request);
+
+    $this->pageController->handle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $request, $route_match);
   }
 
 }
diff --git a/core/modules/views/tests/src/Unit/ViewsTest.php b/core/modules/views/tests/src/Unit/ViewsTest.php
index 8bf4770..aa7a8c9 100644
--- a/core/modules/views/tests/src/Unit/ViewsTest.php
+++ b/core/modules/views/tests/src/Unit/ViewsTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Tests\views\Unit;
 
-use Drupal\Core\Entity\Query\QueryFactory;
 use Drupal\Tests\UnitTestCase;
 use Drupal\views\Views;
 use Drupal\views\Entity\View;
@@ -23,19 +22,12 @@
 class ViewsTest extends UnitTestCase {
 
   /**
-   * The test container.
-   *
-   * @var \Drupal\Core\DependencyInjection\ContainerBuilder
-   */
-  protected $container;
-
-  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
-    $this->container = new ContainerBuilder();
+    $container = new ContainerBuilder();
     $user = $this->getMock('Drupal\Core\Session\AccountInterface');
     $request_stack = new RequestStack();
     $request_stack->push(new Request());
@@ -43,9 +35,26 @@ protected function setUp() {
       ->disableOriginalConstructor()
       ->getMock();
     $route_provider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
-    $this->container->set('views.executable', new ViewExecutableFactory($user, $request_stack, $views_data, $route_provider));
+    $container->set('views.executable', new ViewExecutableFactory($user, $request_stack, $views_data, $route_provider));
 
-    \Drupal::setContainer($this->container);
+    $this->view = new View(array('id' => 'test_view'), 'view');
+
+    $view_storage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $view_storage->expects($this->once())
+      ->method('load')
+      ->with('test_view')
+      ->will($this->returnValue($this->view));
+
+    $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
+    $entity_manager->expects($this->once())
+      ->method('getStorage')
+      ->with('view')
+      ->will($this->returnValue($view_storage));
+    $container->set('entity.manager', $entity_manager);
+
+    \Drupal::setContainer($container);
   }
 
   /**
@@ -54,153 +63,10 @@ protected function setUp() {
    * @covers ::getView
    */
   public function testGetView() {
-    $view = new View(['id' => 'test_view'], 'view');
-
-    $view_storage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $view_storage->expects($this->once())
-      ->method('load')
-      ->with('test_view')
-      ->will($this->returnValue($view));
-
-    $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
-    $entity_manager->expects($this->once())
-      ->method('getStorage')
-      ->with('view')
-      ->will($this->returnValue($view_storage));
-    $this->container->set('entity.manager', $entity_manager);
-
     $executable = Views::getView('test_view');
     $this->assertInstanceOf('Drupal\views\ViewExecutable', $executable);
-    $this->assertEquals($view->id(), $executable->storage->id());
-    $this->assertEquals(spl_object_hash($view), spl_object_hash($executable->storage));
-  }
-
-  /**
-   * @covers ::getApplicableViews
-   *
-   * @dataProvider providerTestGetApplicableViews
-   */
-  public function testGetApplicableViews($applicable_type, $expected) {
-    $view_1 = new View([
-      'id' => 'test_view_1',
-      'display' => [
-        'default' => [
-          'display_plugin' => 'default',
-          'display_options' => [],
-        ],
-        'type_a' => [
-          'display_plugin' => 'type_a',
-          'display_options' => [],
-        ],
-      ],
-    ], 'view');
-    $view_2 = new View([
-      'id' => 'test_view_2',
-      'display' => [
-        'default' => [
-          'display_plugin' => 'default',
-          'display_options' => [],
-        ],
-        'type_b' => [
-          'display_plugin' => 'type_b',
-          'display_options' => [
-            'enabled' => TRUE,
-          ],
-        ],
-        'type_b_2' => [
-          'display_plugin' => 'type_b',
-          'display_options' => [
-            'enabled' => FALSE,
-          ],
-        ],
-      ],
-    ], 'view');
-    $view_3 = new View([
-      'id' => 'test_view_3',
-      'display' => [
-        'default' => [
-          'display_plugin' => 'default',
-          'display_options' => [],
-        ],
-        // Test with Type A but a disabled display.
-        'type_a' => [
-          'display_plugin' => 'type_a',
-          'display_options' => [
-            'enabled' => FALSE
-          ],
-        ],
-        // Type D intentionally doesn't exist.
-        'type_d' => [
-          'display_plugin' => 'type_d',
-          'display_options' => [],
-        ],
-      ],
-    ], 'view');
-
-    $query = $this->getMock('Drupal\Core\Entity\Query\QueryInterface');
-    $query->expects($this->exactly(2))
-      ->method('condition')
-      ->willReturnSelf();
-    $query->expects($this->once())
-      ->method('execute')
-      ->willReturn(['test_view_1', 'test_view_2', 'test_view_3']);
-
-    $view_storage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $view_storage->expects($this->once())
-      ->method('getQuery')
-      ->willReturn($query);
-
-    $view_storage->expects($this->once())
-      ->method('loadMultiple')
-      ->with(['test_view_1', 'test_view_2', 'test_view_3'])
-      ->will($this->returnValue(['test_view_1' => $view_1, 'test_view_2' => $view_2, 'test_view_3' => $view_3]));
-
-    $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
-    $entity_manager->expects($this->exactly(2))
-      ->method('getStorage')
-      ->with('view')
-      ->will($this->returnValue($view_storage));
-    $this->container->set('entity.manager', $entity_manager);
-
-    $definitions = [
-      'type_a' => [
-        'type_a' => TRUE,
-        'type_b' => FALSE,
-      ],
-      'type_b' => [
-        'type_a' => FALSE,
-        'type_b' => TRUE,
-      ],
-    ];
-
-    $display_manager = $this->getMock('Drupal\Component\Plugin\PluginManagerInterface');
-    $display_manager->expects($this->once())
-      ->method('getDefinitions')
-      ->willReturn($definitions);
-    $this->container->set('plugin.manager.views.display', $display_manager);
-
-    $entity_query = new QueryFactory($entity_manager);
-    $this->container->set('entity.query', $entity_query);
-
-    $result = Views::getApplicableViews($applicable_type);
-    $this->assertEquals($expected, $result);
-  }
-
-  /**
-   * Data provider for testGetApplicableViews.
-   *
-   * @return array
-   */
-  public function providerTestGetApplicableViews() {
-    return [
-      ['type_a', [['test_view_1', 'type_a']]],
-      ['type_b', [['test_view_2', 'type_b']]],
-      ['type_c', []],
-    ];
+    $this->assertEquals($this->view->id(), $executable->storage->id());
+    $this->assertEquals(spl_object_hash($this->view), spl_object_hash($executable->storage));
   }
 
 }
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 1d65c58..e968eb8 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -19,7 +19,6 @@
 use Drupal\Core\Url;
 use Drupal\views\Plugin\Derivative\ViewsLocalTask;
 use Drupal\Core\Template\AttributeArray;
-use Drupal\views\Plugin\views\display\Page;
 use Drupal\views\ViewExecutable;
 use Drupal\Component\Plugin\Exception\PluginException;
 use Drupal\views\Entity\View;
@@ -314,14 +313,11 @@ function views_element_info_alter(&$types) {
  * #pre_render callback to set contextual links for views using a Page display.
  */
 function views_page_display_pre_render(array $element) {
-  if (!\Drupal::moduleHandler()->moduleExists('contextual')) {
-    return $element;
-  }
   // If the main content of this page contains a view, attach its contextual
   // links to the overall page array. This allows them to be rendered directly
   // next to the page title.
-  if ($render_array = Page::getPageRenderArray()) {
-    views_add_contextual_links($element, 'page', $render_array['#display_id'], $render_array);
+  if ($view = views_get_page_view()) {
+    views_add_contextual_links($element, 'page', $view, $view->current_display);
   }
   return $element;
 }
@@ -405,35 +401,24 @@ function views_preprocess_html(&$variables) {
  *   also need to set 'contextual_links_locations' in your plugin annotation to
  *   indicate which view displays support having their contextual links
  *   rendered in the location you have defined.
- * @param string $display_id
+ * @param $view
+ *   The view whose contextual links will be added.
+ * @param $display_id
  *   The ID of the display within $view whose contextual links will be added.
- * @param array $view_element
- *   The render array of the view. It should contain the following properties:
- *     - #view_id: The ID of the view.
- *     - #view_display_show_admin_links: A boolean whether the admin links
- *       should be shown.
- *     - #view_display_plugin_id: The plugin ID of the display.
  *
  * @see \Drupal\views\Plugin\block\block\ViewsBlock::addContextualLinks()
  * @see views_preprocess_page()
  * @see template_preprocess_views_view()
  */
-function views_add_contextual_links(&$render_element, $location, $display_id, array $view_element = NULL) {
-  if (!isset($view_element)) {
-    $view_element = $render_element;
-  }
-  $view_element['#cache_properties'] = ['view_id', 'view_display_show_admin_links', 'view_display_plugin_id'];
-  $view_id = $view_element['#view_id'];
-  $show_admin_links = $view_element['#view_display_show_admin_links'];
-  $display_plugin_id = $view_element['#view_display_plugin_id'];
-
+function views_add_contextual_links(&$render_element, $location, ViewExecutable $view, $display_id) {
   // Do not do anything if the view is configured to hide its administrative
   // links or if the Contextual Links module is not enabled.
-  if (\Drupal::moduleHandler()->moduleExists('contextual') && $show_admin_links) {
+  if (\Drupal::moduleHandler()->moduleExists('contextual') && $view->getShowAdminLinks()) {
     // Also do not do anything if the display plugin has not defined any
     // contextual links that are intended to be displayed in the requested
     // location.
-    $plugin = Views::pluginManager('display')->getDefinition($display_plugin_id);
+    $plugin_id = $view->displayHandlers->get($display_id)->getPluginId();
+    $plugin = Views::pluginManager('display')->getDefinition($plugin_id);
     // If contextual_links_locations are not set, provide a sane default. (To
     // avoid displaying any contextual links at all, a display plugin can still
     // set 'contextual_links_locations' to, e.g., {""}.)
@@ -456,20 +441,17 @@ function views_add_contextual_links(&$render_element, $location, $display_id, ar
         $args = array();
         $valid = TRUE;
         if (!empty($link['route_parameters_names'])) {
-          $view_storage = \Drupal::entityManager()
-            ->getStorage('view')
-            ->load($view_id);
           foreach ($link['route_parameters_names'] as $parameter_name => $property) {
             // If the plugin is trying to create an invalid contextual link
             // (for example, "path/to/{$view->storage->property}", where
             // $view->storage->{property} does not exist), we cannot construct
             // the link, so we skip it.
-            if (!property_exists($view_storage, $property)) {
+            if (!property_exists($view->storage, $property)) {
               $valid = FALSE;
               break;
             }
             else {
-              $args[$parameter_name] = $view_storage->get($property);
+              $args[$parameter_name] = $view->storage->get($property);
             }
           }
         }
@@ -481,14 +463,13 @@ function views_add_contextual_links(&$render_element, $location, $display_id, ar
             'route_parameters' => $args,
             'metadata' => array(
               'location' => $location,
-              'name' => $view_id,
+              'name' => $view->storage->id(),
               'display_id' => $display_id,
             ),
           );
           // If we're setting contextual links on a page, for a page view, for a
           // user that may use contextual links, attach Views' contextual links
           // JavaScript.
-          $render_element['#cache']['contexts'][] = 'user.permissions';
           if ($location === 'page' && $render_element['#type'] === 'page' && \Drupal::currentUser()->hasPermission('access contextual links')) {
             $render_element['#attached']['library'][] = 'views/views.contextual-links';
           }
@@ -541,6 +522,32 @@ function views_invalidate_cache() {
 }
 
 /**
+ * Set the current 'page view' that is being displayed so that it is easy
+ * for other modules or the theme to identify.
+ */
+function &views_set_page_view($view = NULL) {
+  static $cache = NULL;
+  if (isset($view)) {
+    $cache = $view;
+  }
+
+  return $cache;
+}
+
+/**
+ * Find out what, if any, page view is currently in use.
+ *
+ * Note that this returns a reference, so be careful! You can unintentionally
+ * modify the $view object.
+ *
+ * @return \Drupal\views\ViewExecutable
+ *   A fully formed, empty $view object.
+ */
+function &views_get_page_view() {
+  return views_set_page_view();
+}
+
+/**
  * Set the current 'current view' that is being built/rendered so that it is
  * easy for other modules or items in drupal_eval to identify
  *
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index 2018d97..236b6d0 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -917,12 +917,7 @@ function template_preprocess_views_view_row_rss(&$variables) {
   $item = $variables['row'];
   $variables['title'] = $item->title;
   $variables['link'] = $item->link;
-
-  /** @var \Drupal\Core\Render\RendererInterface $renderer */
-  $renderer = \Drupal::service('renderer');
-  // We render the item description. It might contain entities, which attach rss
-  // elements via hook_entity_view, see comment_entity_view().
-  $variables['description'] = is_array($item->description) ? $renderer->render($item->description) : $item->description;
+  $variables['description'] = $item->description;
   $variables['item_elements'] = array();
   foreach ($item->elements as $element) {
     if (isset($element['attributes']) && is_array($element['attributes'])) {
@@ -1042,6 +1037,7 @@ function template_preprocess_views_mini_pager(&$variables) {
     $variables['items']['previous']['attributes'] = new Attribute();
   }
 
+  $li_next = array();
   if ($pager_page_array[$element] < ($pager_total[$element] - 1)) {
     $options = array(
       'query' => pager_query_add_page($parameters, $element, $pager_page_array[$element] + 1),
diff --git a/core/modules/views_ui/src/Tests/DefaultViewsTest.php b/core/modules/views_ui/src/Tests/DefaultViewsTest.php
index 416f276..8a88e3d 100644
--- a/core/modules/views_ui/src/Tests/DefaultViewsTest.php
+++ b/core/modules/views_ui/src/Tests/DefaultViewsTest.php
@@ -200,7 +200,7 @@ public function testPathDestination() {
    * @param $unique_href_part
    *   A unique string that is expected to occur within the href of the desired
    *   link. For example, if the link URL is expected to look like
-   *   "admin/structure/views/view/glossary/*", then "/glossary/" could be
+   *   "admin/structure/views/view/glossary/...", then "/glossary/" could be
    *   passed as the expected unique string.
    *
    * @return
diff --git a/core/modules/views_ui/src/Tests/DisplayTest.php b/core/modules/views_ui/src/Tests/DisplayTest.php
index 20667de..a735c21 100644
--- a/core/modules/views_ui/src/Tests/DisplayTest.php
+++ b/core/modules/views_ui/src/Tests/DisplayTest.php
@@ -188,7 +188,7 @@ public function testPageContextualLinks() {
     // Get server-rendered contextual links.
     // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks()
     $post = array('ids[0]' => $id);
-    $response = $this->drupalPostWithFormat('contextual/render', 'json', $post, array('query' => array('destination' => 'test-display')));
+    $response = $this->drupalPost('contextual/render', 'application/json', $post, array('query' => array('destination' => 'test-display')));
     $this->assertResponse(200);
     $json = Json::decode($response);
     $this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_display/edit/page_1">Edit view</a></li></ul>');
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index bf7fdcf..1e3261b 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -147,7 +147,7 @@ public function form(array $form, FormStateInterface $form_state) {
       );
       $lock_message_substitutions = array(
         '!user' => drupal_render($username),
-        '!age' => $this->dateFormatter->formatTimeDiffSince($view->lock->updated),
+        '!age' => $this->dateFormatter->formatInterval(REQUEST_TIME - $view->lock->updated),
         '@url' => $view->url('break-lock-form'),
       );
       $form['locked'] = array(
diff --git a/core/modules/views_ui/tests/modules/views_ui_test/config/install/views.view.sa_contrib_2013_035.yml b/core/modules/views_ui/tests/modules/views_ui_test/config/install/views.view.sa_contrib_2013_035.yml
index d45d509..580fdad 100644
--- a/core/modules/views_ui/tests/modules/views_ui_test/config/install/views.view.sa_contrib_2013_035.yml
+++ b/core/modules/views_ui/tests/modules/views_ui_test/config/install/views.view.sa_contrib_2013_035.yml
@@ -24,7 +24,7 @@ display:
         options:
           perm: 'access content'
       cache:
-        type: tag
+        type: none
         options: {  }
       query:
         type: views_query
diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module
index 45cf248..6712c5d 100644
--- a/core/modules/views_ui/views_ui.module
+++ b/core/modules/views_ui/views_ui.module
@@ -322,7 +322,7 @@ function views_ui_views_analyze(ViewExecutable $view) {
 }
 
 /**
- * Truncate strings to a set length and provide a '...' if they truncated.
+ * Truncate strings to a set length and provide a ... if they truncated.
  *
  * This is often used in the UI to ensure long strings fit.
  */
diff --git a/core/profiles/standard/src/Tests/StandardTest.php b/core/profiles/standard/src/Tests/StandardTest.php
index 3e2ee07..2171765 100644
--- a/core/profiles/standard/src/Tests/StandardTest.php
+++ b/core/profiles/standard/src/Tests/StandardTest.php
@@ -9,7 +9,6 @@
 
 use Drupal\config\Tests\SchemaCheckTestTrait;
 use Drupal\contact\Entity\ContactForm;
-use Drupal\filter\Entity\FilterFormat;
 use Drupal\simpletest\WebTestBase;
 use Drupal\user\Entity\Role;
 
@@ -126,14 +125,6 @@ function testStandard() {
     // The installer does not have this limitation since it ensures that all of
     // the install profiles dependencies are installed before creating the
     // editor configuration.
-    foreach (FilterFormat::loadMultiple() as $filter) {
-      // Ensure that editor can be uninstalled by removing use in filter
-      // formats. It is necessary to prime the filter collection before removing
-      // the filter.
-      $filter->filters();
-      $filter->removeFilter('editor_file_reference');
-      $filter->save();
-    }
     \Drupal::service('module_installer')->uninstall(array('editor', 'ckeditor'));
     $this->rebuildContainer();
     \Drupal::service('module_installer')->install(array('editor'));
diff --git a/core/scripts/dump-database-d8-mysql.php b/core/scripts/dump-database-d8-mysql.php
deleted file mode 100755
index b50f4c0..0000000
--- a/core/scripts/dump-database-d8-mysql.php
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env php
-<?php
-
-use Drupal\Core\Command\DbDumpApplication;
-use Drupal\Core\Database\Database;
-use Drupal\Core\DrupalKernel;
-use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
-
-if (PHP_SAPI !== 'cli') {
-  return;
-}
-
-// Bootstrap.
-$autoloader = require __DIR__ . '/../../autoload.php';
-require_once __DIR__ . '/../includes/bootstrap.inc';
-$request = Request::createFromGlobals();
-Settings::initialize(dirname(dirname(__DIR__)), DrupalKernel::findSitePath($request), $autoloader);
-$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod')->boot();
-
-// Run the database dump command.
-$application = new DbDumpApplication(Database::getConnection(), \Drupal::moduleHandler());
-$application->run();
diff --git a/core/tests/Drupal/Tests/Component/PhpStorage/PhpStorageTestBase.php b/core/tests/Drupal/Tests/Component/PhpStorage/PhpStorageTestBase.php
index 53492d8..fabf301 100644
--- a/core/tests/Drupal/Tests/Component/PhpStorage/PhpStorageTestBase.php
+++ b/core/tests/Drupal/Tests/Component/PhpStorage/PhpStorageTestBase.php
@@ -54,7 +54,7 @@ public function assertCRUD($php) {
     $this->assertTrue($php->exists($name), 'Exists works correctly');
 
     // Delete the file, and then ensure exists() returns FALSE.
-    $this->assertTrue($php->delete($name), 'Delete succeeded');
+    $this->assertTrue($php->delete($name), 'Delete suceeded');
     $this->assertFalse($php->exists($name), 'Delete deleted file');
 
     // Ensure delete() can be called on a non-existing file. It should return
diff --git a/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php
index 97e2fb1..34a2016 100644
--- a/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php
@@ -125,6 +125,9 @@ public function testCreateChangelistNoChange() {
     $this->targetStorage->expects($this->once())
       ->method('getAllCollectionNames')
       ->will($this->returnValue(array()));
+    $this->configManager->expects($this->any())
+      ->method('supportsConfigurationEntities')
+      ->will($this->returnValue(TRUE));
 
     $this->storageComparer->createChangelist();
     $this->assertEmpty($this->storageComparer->getChangelist('create'));
@@ -159,6 +162,9 @@ public function testCreateChangelistCreate() {
     $this->targetStorage->expects($this->once())
       ->method('getAllCollectionNames')
       ->will($this->returnValue(array()));
+    $this->configManager->expects($this->any())
+      ->method('supportsConfigurationEntities')
+      ->will($this->returnValue(TRUE));
 
     $this->storageComparer->createChangelist();
     $expected = array(
@@ -198,6 +204,9 @@ public function testCreateChangelistDelete() {
     $this->targetStorage->expects($this->once())
       ->method('getAllCollectionNames')
       ->will($this->returnValue(array()));
+    $this->configManager->expects($this->any())
+      ->method('supportsConfigurationEntities')
+      ->will($this->returnValue(TRUE));
 
     $this->storageComparer->createChangelist();
     $expected = array(
@@ -237,6 +246,9 @@ public function testCreateChangelistUpdate() {
     $this->targetStorage->expects($this->once())
       ->method('getAllCollectionNames')
       ->will($this->returnValue(array()));
+    $this->configManager->expects($this->any())
+      ->method('supportsConfigurationEntities')
+      ->will($this->returnValue(TRUE));
 
     $this->storageComparer->createChangelist();
     $expected = array(
diff --git a/core/tests/Drupal/Tests/Core/ContentNegotiationTest.php b/core/tests/Drupal/Tests/Core/ContentNegotiationTest.php
index 9c54eae..d5f3081 100644
--- a/core/tests/Drupal/Tests/Core/ContentNegotiationTest.php
+++ b/core/tests/Drupal/Tests/Core/ContentNegotiationTest.php
@@ -44,13 +44,36 @@ public function testAjaxIframeUpload() {
   }
 
   /**
-   * Tests the specifying a format via query parameters gets used.
+   * Tests the getContentType() method when a priority format is found.
+   *
+   * @dataProvider priorityFormatProvider
+   * @covers ::getContentType
    */
-  public function testFormatViaQueryParameter() {
+  public function testAPriorityFormatIsFound($priority, $format) {
     $request = new Request();
-    $request->query->set('_format', 'bob');
+    $request->setFormat($format['format'], $format['mime_type']);
+    $request->headers->set('Accept', sprintf('%s,application/json', $format['mime_type']));
 
-    $this->assertSame('bob', $this->contentNegotiation->getContentType($request));
+    $this->assertSame($priority, $this->contentNegotiation->getContentType($request));
+  }
+
+  public function priorityFormatProvider()
+  {
+    return [
+      ['html', ['format' => 'html', 'mime_type' => 'text/html']],
+    ];
+  }
+
+  /**
+   * Tests the getContentType() method when no priority format is found but a valid one is found.
+   *
+   * @covers ::getContentType
+   */
+  public function testNoPriorityFormatIsFoundButReturnsTheFirstValidOne() {
+    $request = new Request();
+    $request->headers->set('Accept', 'application/rdf+xml');
+
+    $this->assertSame('rdf', $this->contentNegotiation->getContentType($request));
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Datetime/DateTest.php b/core/tests/Drupal/Tests/Core/Datetime/DateTest.php
index 09c890a..1cbed5e 100644
--- a/core/tests/Drupal/Tests/Core/Datetime/DateTest.php
+++ b/core/tests/Drupal/Tests/Core/Datetime/DateTest.php
@@ -10,7 +10,6 @@
 use Drupal\Core\Datetime\DateFormatter;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Tests\UnitTestCase;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * @coversDefaultClass \Drupal\Core\Datetime\DateFormatter
@@ -40,37 +39,22 @@ class DateTest extends UnitTestCase {
   protected $stringTranslation;
 
   /**
-   * The mocked string translation.
-   *
-   * @var \Symfony\Component\HttpFoundation\RequestStack|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $requestStack;
-
-  /**
-   * The mocked date formatter class.
+   * The tested date service class.
    *
    * @var \Drupal\Core\Datetime\DateFormatter
    */
   protected $dateFormatter;
 
-  /**
-   * The date formatter class where methods can be stubbed.
-   *
-   * @var \Drupal\Core\Datetime\DateFormatter|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $dateFormatterStub;
-
   protected function setUp() {
     parent::setUp();
 
     $entity_storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
 
     $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
-    $this->entityManager->expects($this->any())->method('getStorage')->with('date_format')->willReturn($entity_storage);
+    $this->entityManager->expects($this->once())->method('getStorage')->with('date_format')->willReturn($entity_storage);
 
     $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
     $this->stringTranslation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
-    $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack');
 
     $config_factory = $this->getConfigFactoryStub(['system.date' => ['country' => ['default' => 'GB']]]);
     $container = new ContainerBuilder();
@@ -78,20 +62,15 @@ protected function setUp() {
     $container->set('string_translation', $this->getStringTranslationStub());
     \Drupal::setContainer($container);
 
-    $this->dateFormatter = new DateFormatter($this->entityManager, $this->languageManager, $this->stringTranslation, $this->getConfigFactoryStub(), $this->requestStack);
-
-    $this->dateFormatterStub = $this->getMockBuilder('\Drupal\Core\Datetime\DateFormatter')
-      ->setConstructorArgs([$this->entityManager, $this->languageManager, $this->stringTranslation, $this->getConfigFactoryStub(), $this->requestStack])
-      ->setMethods(['formatDiff'])
-      ->getMock();
+    $this->dateFormatter = new DateFormatter($this->entityManager, $this->languageManager, $this->stringTranslation, $this->getConfigFactoryStub());
   }
 
   /**
-   * Tests the formatInterval method.
+   * Tests the formatPlugin method.
    *
    * @dataProvider providerTestFormatInterval
    *
-   * @covers ::formatInterval
+   * @covers \Drupal\Core\Datetime\DateFormatter::formatInterval
    */
   public function testFormatInterval($interval, $granularity, $expected, $langcode = NULL) {
     // Mocks a simple formatPlural implementation.
@@ -181,218 +160,4 @@ public function testGetSampleDateFormats() {
     }
   }
 
-  /**
-   * Tests the formatTimeDiffUntil method.
-   *
-   * @covers ::formatTimeDiffUntil
-   */
-  public function testFormatTimeDiffUntil() {
-    $expected = '1 second';
-    $request_time = $this->createTimestamp('2013-12-11 10:09:08');
-    $timestamp = $this->createTimestamp('2013-12-11 10:09:09');
-    $options = array();
-
-    // Mocks the formatDiff function of the dateformatter object.
-    $this->dateFormatterStub
-      ->expects($this->any())
-      ->method('formatDiff')
-      ->with($timestamp, $request_time, $options)
-      ->will($this->returnValue($expected));
-
-    $request = Request::createFromGlobals();
-    $request->server->set('REQUEST_TIME', $request_time);
-    // Mocks a the request stack getting the current request.
-    $this->requestStack->expects($this->any())
-      ->method('getCurrentRequest')
-      ->willReturn($request);
-
-    $this->assertEquals($expected, $this->dateFormatterStub->formatTimeDiffSince($timestamp, $options));
-  }
-
-  /**
-   * Tests the formatTimeDiffSince method.
-   *
-   * @covers ::formatTimeDiffSince
-   */
-  public function testFormatTimeDiffSince() {
-    $expected = '1 second';
-    $timestamp = $this->createTimestamp('2013-12-11 10:09:07');
-    $request_time = $this->createTimestamp('2013-12-11 10:09:08');
-    $options = array();
-
-    // Mocks the formatDiff function of the dateformatter object.
-    $this->dateFormatterStub
-      ->expects($this->any())
-      ->method('formatDiff')
-      ->with($request_time, $timestamp, $options)
-      ->will($this->returnValue($expected));
-
-    $request = Request::createFromGlobals();
-    $request->server->set('REQUEST_TIME', $request_time);
-    // Mocks a the request stack getting the current request.
-    $this->requestStack->expects($this->any())
-      ->method('getCurrentRequest')
-      ->willReturn($request);
-
-    $this->assertEquals($expected, $this->dateFormatterStub->formatTimeDiffUntil($timestamp, $options));
-  }
-
-  /**
-   * Tests the formatDiff method.
-   *
-   * @dataProvider providerTestFormatDiff
-   *
-   * @covers ::formatDiff
-   */
-  public function testformatDiff($expected, $timestamp1, $timestamp2, $options = array()) {
-
-    // Mocks a simple formatPlural implementation.
-    $this->stringTranslation->expects($this->any())
-      ->method('formatPlural')
-      ->with($this->anything(), $this->anything(), $this->anything(), array(), array('langcode' => isset($options['langcode']) ? $options['langcode'] : NULL))
-      ->will($this->returnCallback(function($count, $one, $multiple) {
-        return $count == 1 ? $one : str_replace('@count', $count, $multiple);
-      }));
-
-    // Mocks a simple translate implementation.
-    $this->stringTranslation->expects($this->any())
-      ->method('translate')
-      ->with($this->anything())
-      ->will($this->returnCallback(function($string, $args, $options) {
-        return $string;
-      }));
-
-    $this->assertEquals($expected, $this->dateFormatter->formatDiff($timestamp1, $timestamp2, $options));
-  }
-
-  /**
-   * Data provider for testformatDiff().
-   */
-  public function providerTestFormatDiff() {
-    // This is the fixed request time in the test.
-    $request_time = $this->createTimestamp('2013-12-11 10:09:08');
-
-    $granularity_3 = array('granularity' => 3);
-    $granularity_4 = array('granularity' => 4);
-
-    $langcode_en = array('langcode' => 'en');
-    $langcode_lolspeak = array('langcode' => 'xxx-lolspeak');
-
-    $non_strict = array('strict' => FALSE);
-
-    $data = array(
-      // Checks for equal timestamps.
-      array('0 seconds', $request_time, $request_time),
-
-      // Checks for seconds only.
-      array('1 second', $this->createTimestamp('2013-12-11 10:09:07'), $request_time),
-      array('1 second', $this->createTimestamp('2013-12-11 10:09:07'), $request_time),
-      array('1 second', $this->createTimestamp('2013-12-11 10:09:07'), $request_time, $granularity_3 + $langcode_en),
-      array('1 second', $this->createTimestamp('2013-12-11 10:09:07'), $request_time, $granularity_4 + $langcode_lolspeak),
-      array('2 seconds', $this->createTimestamp('2013-12-11 10:09:06'), $request_time),
-      array('59 seconds', $this->createTimestamp('2013-12-11 10:08:09'), $request_time),
-      array('59 seconds', $this->createTimestamp('2013-12-11 10:08:09'), $request_time),
-
-      // Checks for minutes and possibly seconds.
-      array('1 minute', $this->createTimestamp('2013-12-11 10:08:08'), $request_time),
-      array('1 minute', $this->createTimestamp('2013-12-11 10:08:08'), $request_time),
-      array('1 minute 1 second', $this->createTimestamp('2013-12-11 10:08:07'), $request_time),
-      array('1 minute 59 seconds', $this->createTimestamp('2013-12-11 10:07:09'), $request_time),
-      array('2 minutes', $this->createTimestamp('2013-12-11 10:07:08'), $request_time),
-      array('2 minutes 1 second', $this->createTimestamp('2013-12-11 10:07:07'), $request_time),
-      array('2 minutes 2 seconds', $this->createTimestamp('2013-12-11 10:07:06'), $request_time),
-      array('2 minutes 2 seconds', $this->createTimestamp('2013-12-11 10:07:06'), $request_time, $granularity_3),
-      array('2 minutes 2 seconds', $this->createTimestamp('2013-12-11 10:07:06'), $request_time, $granularity_4),
-      array('30 minutes', $this->createTimestamp('2013-12-11 09:39:08'), $request_time),
-      array('59 minutes 59 seconds', $this->createTimestamp('2013-12-11 09:09:09'), $request_time),
-      array('59 minutes 59 seconds', $this->createTimestamp('2013-12-11 09:09:09'), $request_time),
-
-      // Checks for hours and possibly minutes or seconds.
-      array('1 hour', $this->createTimestamp('2013-12-11 09:09:08'), $request_time),
-      array('1 hour', $this->createTimestamp('2013-12-11 09:09:08'), $request_time),
-      array('1 hour 1 second', $this->createTimestamp('2013-12-11 09:09:07'), $request_time),
-      array('1 hour 2 seconds', $this->createTimestamp('2013-12-11 09:09:06'), $request_time),
-      array('1 hour 1 minute', $this->createTimestamp('2013-12-11 09:08:08'), $request_time),
-      array('1 hour 1 minute 1 second', $this->createTimestamp('2013-12-11 09:08:07'), $request_time, $granularity_3),
-      array('1 hour 1 minute 2 seconds', $this->createTimestamp('2013-12-11 09:08:06'), $request_time, $granularity_4),
-      array('1 hour 30 minutes', $this->createTimestamp('2013-12-11 08:39:08'), $request_time),
-      array('2 hours', $this->createTimestamp('2013-12-11 08:09:08'), $request_time),
-      array('23 hours 59 minutes', $this->createTimestamp('2013-12-10 10:10:08'), $request_time),
-
-      // Checks for days and possibly hours, minutes or seconds.
-      array('1 day', $this->createTimestamp('2013-12-10 10:09:08'), $request_time),
-      array('1 day 1 second', $this->createTimestamp('2013-12-10 10:09:07'), $request_time),
-      array('1 day 1 hour', $this->createTimestamp('2013-12-10 09:09:08'), $request_time),
-      array('1 day 1 hour 1 minute', $this->createTimestamp('2013-12-10 09:08:07'), $request_time, $granularity_3 + $langcode_en),
-      array('1 day 1 hour 1 minute 1 second', $this->createTimestamp('2013-12-10 09:08:07'), $request_time, $granularity_4 + $langcode_lolspeak),
-      array('1 day 2 hours 2 minutes 2 seconds', $this->createTimestamp('2013-12-10 08:07:06'), $request_time, $granularity_4),
-      array('2 days', $this->createTimestamp('2013-12-09 10:09:08'), $request_time),
-      array('2 days 2 minutes', $this->createTimestamp('2013-12-09 10:07:08'), $request_time),
-      array('2 days 2 hours', $this->createTimestamp('2013-12-09 08:09:08'), $request_time),
-      array('2 days 2 hours 2 minutes', $this->createTimestamp('2013-12-09 08:07:06'), $request_time, $granularity_3 + $langcode_en),
-      array('2 days 2 hours 2 minutes 2 seconds', $this->createTimestamp('2013-12-09 08:07:06'), $request_time, $granularity_4 + $langcode_lolspeak),
-
-      // Checks for weeks and possibly days, hours, minutes or seconds.
-      array('1 week', $this->createTimestamp('2013-12-04 10:09:08'), $request_time),
-      array('1 week 1 day', $this->createTimestamp('2013-12-03 10:09:08'), $request_time),
-      array('2 weeks', $this->createTimestamp('2013-11-27 10:09:08'), $request_time),
-      array('2 weeks 2 days', $this->createTimestamp('2013-11-25 08:07:08'), $request_time),
-      array('2 weeks 2 days 2 hours 2 minutes', $this->createTimestamp('2013-11-25 08:07:08'), $request_time, $granularity_4),
-      array('4 weeks', $this->createTimestamp('2013-11-13 10:09:08'), $request_time),
-      array('4 weeks 1 day', $this->createTimestamp('2013-11-12 10:09:08'), $request_time),
-
-      // Checks for months and possibly days, hours, minutes or seconds.
-      array('1 month', $this->createTimestamp('2013-11-11 10:09:08'), $request_time),
-      array('1 month 1 second', $this->createTimestamp('2013-11-11 10:09:07'), $request_time),
-      array('1 month 1 hour', $this->createTimestamp('2013-11-11 09:09:08'), $request_time),
-      array('1 month 1 hour 1 minute', $this->createTimestamp('2013-11-11 09:08:07'), $request_time, $granularity_3),
-      array('1 month 1 hour 1 minute 1 second', $this->createTimestamp('2013-11-11 09:08:07'), $request_time, $granularity_4),
-      array('1 month 4 weeks', $this->createTimestamp('2013-10-13 10:09:08'), $request_time),
-      array('1 month 4 weeks 1 day', $this->createTimestamp('2013-10-13 10:09:08'), $request_time, $granularity_3),
-      array('1 month 4 weeks', $this->createTimestamp('2013-10-12 10:09:08'), $request_time),
-      array('1 month 4 weeks 2 days', $this->createTimestamp('2013-10-12 10:09:08'), $request_time, $granularity_3),
-      array('2 months', $this->createTimestamp('2013-10-11 10:09:08'), $request_time),
-      array('2 months 1 day', $this->createTimestamp('2013-10-10 10:09:08'), $request_time),
-      array('2 months 2 days', $this->createTimestamp('2013-10-09 08:07:06'), $request_time),
-      array('2 months 2 days 2 hours', $this->createTimestamp('2013-10-09 08:07:06'), $request_time, $granularity_3),
-      array('2 months 2 days 2 hours 2 minutes', $this->createTimestamp('2013-10-09 08:07:06'), $request_time, $granularity_4),
-      array('6 months 2 days', $this->createTimestamp('2013-06-09 10:09:08'), $request_time),
-      array('11 months 3 hours', $this->createTimestamp('2013-01-11 07:09:08'), $request_time),
-      array('11 months 4 weeks', $this->createTimestamp('2012-12-12 10:09:08'), $request_time),
-      array('11 months 4 weeks 2 days', $this->createTimestamp('2012-12-12 10:09:08'), $request_time, $granularity_3),
-
-      // Checks for years and possibly months, days, hours, minutes or seconds.
-      array('1 year', $this->createTimestamp('2012-12-11 10:09:08'), $request_time),
-      array('1 year 1 minute', $this->createTimestamp('2012-12-11 10:08:08'), $request_time),
-      array('1 year 1 day', $this->createTimestamp('2012-12-10 10:09:08'), $request_time),
-      array('2 years', $this->createTimestamp('2011-12-11 10:09:08'), $request_time),
-      array('2 years 2 minutes', $this->createTimestamp('2011-12-11 10:07:08'), $request_time),
-      array('2 years 2 days', $this->createTimestamp('2011-12-09 10:09:08'), $request_time),
-      array('2 years 2 months 2 days', $this->createTimestamp('2011-10-09 08:07:06'), $request_time, $granularity_3),
-      array('2 years 2 months 2 days 2 hours', $this->createTimestamp('2011-10-09 08:07:06'), $request_time, $granularity_4),
-      array('10 years', $this->createTimestamp('2003-12-11 10:09:08'), $request_time),
-      array('100 years', $this->createTimestamp('1913-12-11 10:09:08'), $request_time),
-
-      // Checks the non-strict option vs. strict (default).
-      array('1 second', $this->createTimestamp('2013-12-11 10:09:08'), $this->createTimestamp('2013-12-11 10:09:07'), $non_strict),
-      array('0 seconds', $this->createTimestamp('2013-12-11 10:09:08'), $this->createTimestamp('2013-12-11 10:09:07')),
-    );
-
-    return $data;
-  }
-
-  /**
-   * Creates a UNIX timestamp given a date and time string in the format
-   * year-month-day hour:minute:seconds (e.g. 2013-12-11 10:09:08).
-   *
-   * @param string $dateTimeString
-   *   The formatted date and time string.
-   *
-   * @return int
-   *   The UNIX timestamp.
-   */
-  private function createTimestamp($dateTimeString) {
-    return \DateTime::createFromFormat('Y-m-d G:i:s', $dateTimeString)->getTimestamp();
-  }
-
 }
diff --git a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
deleted file mode 100644
index d923f9a..0000000
--- a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
+++ /dev/null
@@ -1,152 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\Core\DrupalKernel\DrupalKernelTest.
- */
-
-namespace Drupal\Tests\Core\DrupalKernel {
-
-  use Drupal\Core\DrupalKernel;
-  use Drupal\Tests\UnitTestCase;
-  use org\bovigo\vfs\vfsStream;
-  use Symfony\Component\HttpFoundation\Request;
-
-  /**
-   * @coversDefaultClass \Drupal\Core\DrupalKernel
-   * @group DrupalKernel
-   */
-  class DrupalKernelTest extends UnitTestCase {
-
-    /**
-     * Tests hostname validation with settings.
-     *
-     * @covers ::setupTrustedHosts
-     * @dataProvider providerTestTrustedHosts
-     */
-    public function testTrustedHosts($host, $server_name, $message, $expected = FALSE) {
-      $request = new Request();
-
-      $trusted_host_patterns = [
-        '^example\.com$',
-        '^.+\.example\.com$',
-        '^example\.org',
-        '^.+\.example\.org',
-      ];
-
-      if (!empty($host)) {
-        $request->headers->set('HOST', $host);
-      }
-
-      $request->server->set('SERVER_NAME', $server_name);
-
-      $method = new \ReflectionMethod('Drupal\Core\DrupalKernel', 'setupTrustedHosts');
-      $method->setAccessible(TRUE);
-      $valid_host = $method->invoke(null, $request, $trusted_host_patterns);
-
-      $this->assertSame($expected, $valid_host, $message);
-
-      // Reset the trusted hosts because it is statically stored on the request.
-      $method->invoke(null, $request, []);
-      // Reset the request factory because it is statically stored on the request.
-      Request::setFactory(NULL);
-    }
-
-    /**
-     * Provides test data for testTrustedHosts().
-     */
-    public function providerTestTrustedHosts() {
-      $data = [];
-
-      // Tests canonical URL.
-      $data[] = [
-        'www.example.com',
-        'www.example.com',
-        'canonical URL is trusted',
-        TRUE
-      ];
-
-      // Tests missing hostname for HTTP/1.0 compatibility where the Host
-      // header is optional.
-      $data[] = [NULL, 'www.example.com', 'empty Host is valid', TRUE];
-
-      // Tests the additional patterns from the settings.
-      $data[] = [
-        'example.com',
-        'www.example.com',
-        'host from settings is trusted',
-        TRUE
-      ];
-      $data[] = [
-        'subdomain.example.com',
-        'www.example.com',
-        'host from settings is trusted',
-        TRUE
-      ];
-      $data[] = [
-        'www.example.org',
-        'www.example.com',
-        'host from settings is trusted',
-        TRUE
-      ];
-      $data[] = [
-        'example.org',
-        'www.example.com',
-        'host from settings is trusted',
-        TRUE
-      ];
-
-      // Tests mismatch.
-      $data[] = [
-        'www.blackhat.com',
-        'www.example.com',
-        'unspecified host is untrusted',
-        FALSE
-      ];
-
-      return $data;
-    }
-
-    /**
-     * Tests site path finding.
-     *
-     * This test is run in a separate process since it defines DRUPAL_ROOT. This
-     * stops any possible pollution of other tests.
-     *
-     * @covers ::findSitePath
-     * @runInSeparateProcess
-     */
-    public function testFindSitePath() {
-      $vfs_root = vfsStream::setup('drupal_root');
-      $sites_php = <<<'EOD'
-<?php
-$sites['8888.www.example.org'] = 'example';
-EOD;
-
-      // Create the expected directory structure.
-      vfsStream::create(['sites' => [
-        'sites.php' => $sites_php,
-        'example' => [
-          'settings.php' => 'test'
-        ]
-      ]]);
-
-      define('DRUPAL_ROOT', $vfs_root->url('drupal_root'));
-      $request = new Request();
-      $request->server->set('SERVER_NAME', 'www.example.org');
-      $request->server->set('SERVER_PORT', '8888');
-      $request->server->set('SCRIPT_NAME', '/index.php');
-      $this->assertEquals('sites/example', DrupalKernel::findSitePath($request));
-    }
-  }
-
-}
-
-
-namespace {
-  if (!function_exists('drupal_valid_test_ua')) {
-    function drupal_valid_test_ua($new_prefix = NULL) {
-      return FALSE;
-    }
-  }
-}
\ No newline at end of file
diff --git a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php
new file mode 100644
index 0000000..1fb30ae
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTrustedHostsTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\DrupalKernel\DrupalKernelTrustedHostsTest.
+ */
+
+namespace Drupal\Tests\Core\DrupalKernel;
+
+use Drupal\Core\DrupalKernel;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @coversDefaultClass \Drupal\Core\DrupalKernel
+ * @group DrupalKernel
+ */
+class DrupalKernelTrustedHostsTest extends UnitTestCase {
+
+  /**
+   * Tests hostname validation with settings.
+   *
+   * @covers ::setupTrustedHosts
+   * @dataProvider providerTestTrustedHosts
+   */
+  public function testTrustedHosts($host, $server_name, $message, $expected = FALSE) {
+    $request = new Request();
+
+    $trusted_host_patterns = [
+      '^example\.com$',
+      '^.+\.example\.com$',
+      '^example\.org',
+      '^.+\.example\.org',
+    ];
+
+    if (!empty($host)) {
+      $request->headers->set('HOST', $host);
+    }
+
+    $request->server->set('SERVER_NAME', $server_name);
+
+    $method = new \ReflectionMethod('Drupal\Core\DrupalKernel', 'setupTrustedHosts');
+    $method->setAccessible(TRUE);
+    $valid_host = $method->invoke(null, $request, $trusted_host_patterns);
+
+    $this->assertSame($expected, $valid_host, $message);
+
+    // Reset the trusted hosts because it is statically stored on the request.
+    $method->invoke(null, $request, []);
+    // Reset the request factory because it is statically stored on the request.
+    Request::setFactory(NULL);
+  }
+
+  /**
+   * Provides test data for testTrustedHosts().
+   */
+  public function providerTestTrustedHosts() {
+    $data = [];
+
+    // Tests canonical URL.
+    $data[] = ['www.example.com', 'www.example.com', 'canonical URL is trusted', TRUE];
+
+    // Tests missing hostname for HTTP/1.0 compatibility where the Host
+    // header is optional.
+    $data[] = [NULL, 'www.example.com', 'empty Host is valid', TRUE];
+
+    // Tests the additional paterns from the settings.
+    $data[] = ['example.com', 'www.example.com', 'host from settings is trusted', TRUE];
+    $data[] = ['subdomain.example.com', 'www.example.com', 'host from settings is trusted', TRUE];
+    $data[] = ['www.example.org', 'www.example.com', 'host from settings is trusted', TRUE];
+    $data[] = ['example.org', 'www.example.com', 'host from settings is trusted', TRUE];
+
+    // Tests mismatch.
+    $data[] = ['www.blackhat.com', 'www.example.com', 'unspecified host is untrusted', FALSE];
+
+    return $data;
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index 11b7ced..25b6a94 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -1106,7 +1106,7 @@ public function testGetEntityTypeLabels() {
   public function testGetTranslationFromContext() {
     $this->setUpEntityManager();
 
-    $this->languageManager->expects($this->exactly(1))
+    $this->languageManager->expects($this->exactly(2))
       ->method('getFallbackCandidates')
       ->will($this->returnCallback(function (array $context = array()) {
         $candidates = array();
@@ -1117,17 +1117,17 @@ public function testGetTranslationFromContext() {
       }));
 
     $entity = $this->getMock('Drupal\Tests\Core\Entity\TestContentEntityInterface');
-    $entity->expects($this->exactly(1))
+    $entity->expects($this->exactly(2))
       ->method('getUntranslated')
       ->will($this->returnValue($entity));
     $language = $this->getMock('\Drupal\Core\Language\LanguageInterface');
     $language->expects($this->any())
       ->method('getId')
       ->will($this->returnValue('en'));
-    $entity->expects($this->exactly(3))
+    $entity->expects($this->exactly(2))
       ->method('language')
       ->will($this->returnValue($language));
-    $entity->expects($this->exactly(1))
+    $entity->expects($this->exactly(2))
       ->method('hasTranslation')
       ->will($this->returnValueMap(array(
         array(LanguageInterface::LANGCODE_DEFAULT, FALSE),
diff --git a/core/tests/Drupal/Tests/Core/Extension/RequiredModuleUninstallValidatorTest.php b/core/tests/Drupal/Tests/Core/Extension/RequiredModuleUninstallValidatorTest.php
deleted file mode 100644
index 718ba8f..0000000
--- a/core/tests/Drupal/Tests/Core/Extension/RequiredModuleUninstallValidatorTest.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\Core\Extension\RequiredModuleUninstallValidatorTest.
- */
-
-namespace Drupal\Tests\Core\Extension;
-
-use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Tests\UnitTestCase;
-
-/**
- * @coversDefaultClass \Drupal\Core\Extension\RequiredModuleUninstallValidator
- * @group Extension
- */
-class RequiredModuleUninstallValidatorTest extends UnitTestCase {
-
-  /**
-   * @var \Drupal\Core\Extension\RequiredModuleUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $uninstallValidator;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->uninstallValidator = $this->getMockBuilder('Drupal\Core\Extension\RequiredModuleUninstallValidator')
-      ->disableOriginalConstructor()
-      ->setMethods(['getModuleInfoByModule'])
-      ->getMock();
-    $this->uninstallValidator->setStringTranslation($this->getStringTranslationStub());
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNoModule() {
-    $this->uninstallValidator->expects($this->once())
-      ->method('getModuleInfoByModule')
-      ->willReturn([]);
-
-    $module = $this->randomMachineName();
-    $expected = [];
-    $reasons = $this->uninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateNotRequired() {
-    $module = $this->randomMachineName();
-
-    $this->uninstallValidator->expects($this->once())
-      ->method('getModuleInfoByModule')
-      ->willReturn(['required' => FALSE, 'name' => $module]);
-
-    $expected = [];
-    $reasons = $this->uninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-  /**
-   * @covers ::validate
-   */
-  public function testValidateRequired() {
-    $module = $this->randomMachineName();
-
-    $this->uninstallValidator->expects($this->once())
-      ->method('getModuleInfoByModule')
-      ->willReturn(['required' => TRUE, 'name' => $module]);
-
-    $expected = [SafeMarkup::format('The @module module is required', ['@module' => $module])];
-    $reasons = $this->uninstallValidator->validate($module);
-    $this->assertSame($expected, $reasons);
-  }
-
-}
diff --git a/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php b/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
index 452ac54..1d9a67a 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
@@ -15,8 +15,6 @@
 /**
  * @coversDefaultClass \Drupal\Core\Form\FormCache
  * @group Form
- * @runTestsInSeparateProcesses
- * @preserveGlobalState disabled
  */
 class FormCacheTest extends UnitTestCase {
 
@@ -96,6 +94,8 @@ class FormCacheTest extends UnitTestCase {
   protected function setUp() {
     parent::setUp();
 
+    $this->resetSafeMarkup();
+
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
 
     $this->formCacheStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
@@ -121,6 +121,14 @@ protected function setUp() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    parent::tearDown();
+    $this->resetSafeMarkup();
+  }
+
+  /**
    * @covers ::getCache
    */
   public function testGetCacheValidToken() {
@@ -486,4 +494,13 @@ public function testDeleteCache() {
     $this->formCache->deleteCache($form_build_id);
   }
 
+  /**
+   * Ensures SafeMarkup does not bleed from one test to another.
+   */
+  protected function resetSafeMarkup() {
+    $property = (new \ReflectionClass('Drupal\Component\Utility\SafeMarkup'))->getProperty('safeStrings');
+    $property->setAccessible(TRUE);
+    $property->setValue(array());
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTestBase.php b/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTestBase.php
index 25d9c6d..85b1984 100644
--- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTestBase.php
@@ -88,6 +88,11 @@ protected function getLocalTaskManager($module_dirs, $route_name, $route_params)
     $property->setAccessible(TRUE);
     $property->setValue($manager, $route_provider);
 
+    $route_builder = $this->getMock('Drupal\Core\Routing\RouteBuilderInterface');
+    $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'routeBuilder');
+    $property->setAccessible(TRUE);
+    $property->setValue($manager, $route_builder);
+
     $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface')
       ->disableOriginalConstructor()
       ->getMock();
diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php
index 92b2b54..937be5a 100644
--- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php
@@ -50,6 +50,13 @@ class LocalTaskManagerTest extends UnitTestCase {
   protected $routeProvider;
 
   /**
+   * The mocked route builder.
+   *
+   * @var \Drupal\Core\Routing\RouteBuilderInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $routeBuilder;
+
+  /**
    * The mocked plugin discovery.
    *
    * @var \PHPUnit_Framework_MockObject_MockObject
@@ -93,6 +100,7 @@ protected function setUp() {
     $this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
     $this->request = new Request();
     $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
+    $this->routeBuilder = $this->getMock('Drupal\Core\Routing\RouteBuilderInterface');
     $this->pluginDiscovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
     $this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
@@ -211,6 +219,9 @@ public function testGetLocalTaskForRouteWithFilledCache() {
     $this->cacheBackend->expects($this->never())
       ->method('set');
 
+    $this->routeBuilder->expects($this->never())
+      ->method('rebuild');
+
     $result = $this->getLocalTasksForRouteResult($mock_plugin);
     $local_tasks = $this->manager->getLocalTasksForRoute('menu_local_task_test_tasks_view');
     $this->assertEquals($result, $local_tasks);
@@ -250,7 +261,7 @@ protected function setupLocalTaskManager() {
       ->will($this->returnValue(new Language(array('id' => 'en'))));
 
     $account = $this->getMock('Drupal\Core\Session\AccountInterface');
-    $this->manager = new LocalTaskManager($this->controllerResolver, $request_stack, $this->routeMatch, $this->routeProvider, $module_handler, $this->cacheBackend, $language_manager, $this->accessManager, $account);
+    $this->manager = new LocalTaskManager($this->controllerResolver, $request_stack, $this->routeMatch, $this->routeProvider, $this->routeBuilder, $module_handler, $this->cacheBackend, $language_manager, $this->accessManager, $account);
 
     $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'discovery');
     $property->setAccessible(TRUE);
diff --git a/core/modules/system/tests/modules/accept_header_routing_test/tests/Unit/AcceptHeaderMatcherTest.php b/core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php
similarity index 91%
rename from core/modules/system/tests/modules/accept_header_routing_test/tests/Unit/AcceptHeaderMatcherTest.php
rename to core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php
index 4dc9ddf..d0c811c 100644
--- a/core/modules/system/tests/modules/accept_header_routing_test/tests/Unit/AcceptHeaderMatcherTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php
@@ -2,12 +2,12 @@
 
 /**
  * @file
- * Contains \Drupal\Tests\accept_header_routing_test\Unit\Routing\AcceptHeaderMatcherTest.
+ * Contains Drupal\Tests\Core\Routing\AcceptHeaderMatcherTest.
  */
 
-namespace Drupal\Tests\accept_header_routing_teste\Unit\Routing;
+namespace Drupal\Tests\Core\Routing;
 
-use Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher;
+use Drupal\Core\Routing\AcceptHeaderMatcher;
 use Drupal\Tests\Core\Routing\RoutingFixtures;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\HttpFoundation\Request;
@@ -22,14 +22,14 @@ class AcceptHeaderMatcherTest extends UnitTestCase {
   /**
    * A collection of shared fixture data for tests.
    *
-   * @var \Drupal\Tests\Core\Routing\RoutingFixtures
+   * @var RoutingFixtures
    */
   protected $fixtures;
 
   /**
    * The matcher object that is going to be tested.
    *
-   * @var \Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher
+   * @var \Drupal\Core\Routing\AcceptHeaderMatcher
    */
   protected $matcher;
 
diff --git a/core/tests/Drupal/Tests/Core/Routing/RequestFormatRouteFilterTest.php b/core/tests/Drupal/Tests/Core/Routing/RequestFormatRouteFilterTest.php
deleted file mode 100644
index 7c1db96..0000000
--- a/core/tests/Drupal/Tests/Core/Routing/RequestFormatRouteFilterTest.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\Core\Routing\RequestFormatRouteFilterTest.
- */
-
-namespace Drupal\Tests\Core\Routing;
-
-use Drupal\Core\Routing\RequestFormatRouteFilter;
-use Drupal\Tests\UnitTestCase;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * @coversDefaultClass \Drupal\Core\Routing\RequestFormatRouteFilter
- * @group Routing
- */
-class RequestFormatRouteFilterTest extends UnitTestCase {
-
-  /**
-   * @covers ::applies
-   */
-  public function testAppliesWithoutFormat() {
-    $route_filter = new RequestFormatRouteFilter();
-    $route = new Route('/test');
-    $this->assertFalse($route_filter->applies($route));
-  }
-
-  /**
-   * @covers ::applies
-   */
-  public function testAppliesWithFormat() {
-    $route_filter = new RequestFormatRouteFilter();
-    $route = new Route('/test');
-    $route->setRequirement('_format', 'json');
-    $this->assertTrue($route_filter->applies($route));
-  }
-
-  /**
-   * @covers ::filter
-   */
-  public function testFilter() {
-    $route_filter = new RequestFormatRouteFilter();
-
-    $route_without_format = new Route('/test');
-    $route_with_format = $route = new Route('/test');
-    $route_with_format->setRequirement('_format', 'json');
-    $route_with_multiple_formats = $route = new Route('/test');
-    $route_with_multiple_formats->setRequirement('_format', 'json|xml');
-
-    $collection = new RouteCollection();
-    $collection->add('test_0', $route_without_format);
-    $collection->add('test_1', $route_with_format);
-    $collection->add('test_2', $route_with_multiple_formats);
-
-    $request = new Request();
-    $request->setRequestFormat('xml');
-    $collection = $route_filter->filter($collection, $request);
-
-    $this->assertCount(2, $collection);
-    $this->assertEquals(array_keys($collection->all())[0], 'test_2');
-    $this->assertEquals(array_keys($collection->all())[1], 'test_0');
-  }
-
-  /**
-   * @covers ::filter
-   * @expectedException \Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException
-   * @expectedExceptionMessage No route found for the specified format xml.
-   */
-  public function testNoRouteFound() {
-    $collection = new RouteCollection();
-    $route_with_format = $route = new Route('/test');
-    $route_with_format->setRequirement('_format', 'json');
-    $collection->add('test_0', $route_with_format);
-    $collection->add('test_1', clone $route_with_format);
-
-    $request = Request::create('test?_format=xml', 'GET');
-    $request->setRequestFormat('xml');
-    $route_filter = new RequestFormatRouteFilter();
-    $route_filter->filter($collection, $request);
-  }
-
-}
diff --git a/core/themes/classy/templates/content-edit/file-managed-file.html.twig b/core/themes/classy/templates/content-edit/file-managed-file.html.twig
index f639237..43739be 100644
--- a/core/themes/classy/templates/content-edit/file-managed-file.html.twig
+++ b/core/themes/classy/templates/content-edit/file-managed-file.html.twig
@@ -10,12 +10,6 @@
  * @see template_preprocess_file_managed_file()
  */
 #}
-{%
-  set classes = [
-    'js-form-managed-file',
-    'form-managed-file',
-  ]
-%}
-<div{{ attributes.addClass(classes) }}>
+<div{{ attributes.addClass('form-managed-file') }}>
   {{ element }}
 </div>
diff --git a/core/themes/classy/templates/navigation/book-tree.html.twig b/core/themes/classy/templates/navigation/book-tree.html.twig
index 543696c..be69457 100644
--- a/core/themes/classy/templates/navigation/book-tree.html.twig
+++ b/core/themes/classy/templates/navigation/book-tree.html.twig
@@ -1,42 +1,14 @@
 {#
 /**
  * @file
- * Theme override to display a book tree.
+ * Theme override for a book tree.
  *
  * Returns HTML for a wrapper for a book sub-tree.
  *
  * Available variables:
- * - items: A nested list of book items. Each book item contains:
- *   - attributes: HTML attributes for the book item.
- *   - below: The book item child items.
- *   - title: The book link title.
- *   - url: The book link URL, instance of \Drupal\Core\Url.
+ *   - tree: An HTML string containing the tree's items.
+ *
+ * @see template_preprocess_book_tree()
  */
 #}
-{% import _self as book_tree %}
-
-{#
-  We call a macro which calls itself to render the full tree.
-  @see http://twig.sensiolabs.org/doc/tags/macro.html
-#}
-{{ book_tree.book_links(items, attributes, 0) }}
-
-{% macro book_links(items, attributes, menu_level) %}
-  {% import _self as book_tree %}
-  {% if items %}
-    {% if menu_level == 0 %}
-      <ul{{ attributes.addClass('menu') }}>
-    {% else %}
-      <ul class="menu">
-    {% endif %}
-      {% for item in items %}
-        <li{{ item.attributes }}>
-          {{ link(item.title, item.url) }}
-          {% if item.below %}
-            {{ book_tree.book_links(item.below, attributes, menu_level + 1) }}
-          {% endif %}
-        </li>
-      {% endfor %}
-    </ul>
-  {% endif %}
-{% endmacro %}
+<ul class="menu">{{ tree }}</ul>
diff --git a/core/themes/classy/templates/user/user.html.twig b/core/themes/classy/templates/user/user.html.twig
index 9ee9c0a..7d3add5 100644
--- a/core/themes/classy/templates/user/user.html.twig
+++ b/core/themes/classy/templates/user/user.html.twig
@@ -17,7 +17,6 @@
  *   e.g. account.field_example.en, thus overriding any language negotiation
  *   rule that was previously applied.
  * - attributes: HTML attributes for the container element.
- * - user: A Drupal User entity.
  *
  * @see template_preprocess_user()
  */
diff --git a/robots.txt b/robots.txt
index d754cc0..4d51b9d 100644
--- a/robots.txt
+++ b/robots.txt
@@ -14,6 +14,7 @@
 # http://www.robotstxt.org/robotstxt.html
 
 User-agent: *
+Crawl-delay: 10
 # JS/CSS
 Allow: /core/*.css$
 Allow: /core/*.js$
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 65139dc..ef83939 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -48,7 +48,7 @@
  * sites/8080.www.drupal.org.mysite.test/.
  *
  * @see example.sites.php
- * @see \Drupal\Core\DrupalKernel::getSitePath()
+ * @see conf_path()
  *
  * In addition to customizing application settings through variables in
  * settings.php, you can create a services.yml file in the same directory to
diff --git a/web.config b/web.config
index 782d4ae..b072d9b 100644
--- a/web.config
+++ b/web.config
@@ -35,7 +35,7 @@
         </rule>
 
     <!-- To redirect all users to access the site WITH the 'www.' prefix,
-     http://example.com/foo will be redirected to http://www.example.com/foo)
+     http://example.com/... will be redirected to http://www.example.com/...)
      adapt and uncomment the following:   -->
     <!--
         <rule name="Redirect to add www" stopProcessing="true">
@@ -48,7 +48,7 @@
     -->
 
     <!-- To redirect all users to access the site WITHOUT the 'www.' prefix,
-     http://www.example.com/foo will be redirected to http://example.com/foo)
+     http://www.example.com/... will be redirected to http://example.com/...)
      adapt and uncomment the following:   -->
     <!--
         <rule name="Redirect to remove www" stopProcessing="true">
