diff --git a/autoload.php b/autoload.php
index caedb48..690e09f 100644
--- a/autoload.php
+++ b/autoload.php
@@ -16,4 +16,4 @@
  * @see core/modules/statistics/statistics.php
  */
 
-return require __DIR__ . '/core/vendor/autoload.php';
+return require_once __DIR__ . '/core/vendor/autoload.php';
diff --git a/core/CHANGELOG.txt b/core/CHANGELOG.txt
index 34ba1f7..83fc766 100644
--- a/core/CHANGELOG.txt
+++ b/core/CHANGELOG.txt
@@ -46,7 +46,6 @@ Drupal 8.0, xxxx-xx-xx (development version)
 - Removed the Garland theme from core.
 - Removed the Statistics module's accesslog functionality and reports from core.
 - Removed XML-RPC functionality from core.
-- Removed user signatures support from core.
 - Removed backwards-compatibility with 'magic_quotes_gpc'/'magic_quotes_runtime'
   PHP configuration settings. Both are required to be disabled.
 - Universally Unique IDentifier (UUID):
diff --git a/core/assets/vendor/jquery-once/jquery.once.js b/core/assets/vendor/jquery-once/jquery.once.js
index 71adb8a..5363945 100644
--- a/core/assets/vendor/jquery-once/jquery.once.js
+++ b/core/assets/vendor/jquery-once/jquery.once.js
@@ -1,173 +1,92 @@
-/*!
-* jQuery Once v2.0.0 - http://github.com/robloach/jquery-once
-* @license MIT, GPL-2.0
-*   http://opensource.org/licenses/MIT
-*   http://opensource.org/licenses/GPL-2.0
-*/
-
 /**
-* Universal Module Definition
-*
-* jQuery Once has a dependency on jQuery, so we wrap the code with a UMD
-* pattern in order to allow loading jQuery and jQuery Once through a module
-* definition like CommonJS, AMD, or through a global object.
-*
-* @see {@link http://github.com/umdjs/umd}
-*/
+ * jQuery Once Plugin 1.2.3
+ * http://plugins.jquery.com/once/
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+
 (function (factory) {
   "use strict";
-  if (typeof exports === "object") {
-    // CommonJS
-    factory(require("jquery"));
-  } else if (typeof define === "function" && define.amd) {
-    // AMD
-    define(["jquery"], factory);
+  if (typeof exports === 'object') {
+    factory(require('jquery'));
+  } else if (typeof define === 'function' && define.amd) {
+    define(['jquery'], factory);
   } else {
-    // Global object
     factory(jQuery);
   }
 }(function ($) {
   "use strict";
+  var cache = {}, uuid = 0;
 
   /**
-  * Ensures that the given ID is valid, returning "once" if one is not given.
-  *
-  * @param {string} [id="once"]
-  *   A string representing the ID to check. Defaults to `"once"`.
-  *
-  * @returns The valid ID name.
-  *
-  * @throws Error when an ID is provided, but not a string.
-  * @private
-  */
-  var checkId = function(id) {
-    id = id || "once";
-    if (typeof id !== "string") {
-      throw new Error("The jQuery Once id parameter must be a string");
+   * Filters elements by whether they have not yet been processed.
+   *
+   * @param id
+   *   (Optional) If this is a string, then it will be used as the CSS class
+   *   name that is applied to the elements for determining whether it has
+   *   already been processed. The elements will get a class in the form of
+   *   "id-processed".
+   *
+   *   If the id parameter is a function, it will be passed off to the fn
+   *   parameter and the id will become a unique identifier, represented as a
+   *   number.
+   *
+   *   When the id is neither a string or a function, it becomes a unique
+   *   identifier, depicted as a number. The element's class will then be
+   *   represented in the form of "jquery-once-#-processed".
+   *
+   *   Take note that the id must be valid for usage as an element's class name.
+   * @param fn
+   *   (Optional) If given, this function will be called for each element that
+   *   has not yet been processed. The function's return value follows the same
+   *   logic as $.each(). Returning true will continue to the next matched
+   *   element in the set, while returning false will entirely break the
+   *   iteration.
+   *
+   * @api public
+   */
+  $.fn.once = function (id, fn) {
+    if (typeof id !== 'string') {
+      // Generate a numeric ID if the id passed can't be used as a CSS class.
+      if (!(id in cache)) {
+        cache[id] = ++uuid;
+      }
+      // When the fn parameter is not passed, we interpret it from the id.
+      if (!fn) {
+        fn = id;
+      }
+      id = 'jquery-once-' + cache[id];
     }
-    return id;
-  };
-
-  /**
-  * Filter elements that have yet to be processed by the given data ID.
-  *
-  * @param {string} [id="once"]
-  *   The data ID used to determine whether the given elements have already
-  *   been processed or not. Defaults to `"once"`.
-  *
-  * @returns jQuery collection of elements that have now run once by
-  *   the given ID.
-  *
-  * @example
-  * ``` javascript
-  * // The following will change the color of each paragraph to red, just once
-  * // for the "changecolor" key.
-  * $('p').once('changecolor').css('color', 'red');
-  *
-  * // .once() will return a set of elements that yet to have the once ID
-  * // associated with them. You can return to the original collection set by
-  * // using .end().
-  * $('p')
-  *   .once("changecolorblue")
-  *     .css("color", "blue")
-  *   .end()
-  *   .css("color", "red");
-  *
-  * // To execute a function on the once set, you can use jQuery's each().
-  * $('div.calendar').once().each(function() {
-  *   // Since there is no once ID provided here, the key will be "once".
-  * });
-  * ```
-  *
-  * @see removeOnce
-  * @see findOnce
-  * @this jQuery
-  *
-  * @global
-  * @public
-  */
-  $.fn.once = function (id) {
-    // Build the jQuery Once data name from the provided ID.
-    var name = "jquery-once-" + checkId(id);
-
-    // Find elements that don't have the jQuery Once data applied to them yet.
-    return this.filter(function() {
-      return $(this).data(name) !== true;
-    }).data(name, true);
-  };
+    // Remove elements from the set that have already been processed.
+    var name = id + '-processed';
+    var elements = this.not('.' + name).addClass(name);
 
-  /**
-  * Removes the once data from elements, based on the given ID.
-  *
-  * @param {string} [id="once"]
-  *   A string representing the name of the data ID which should be used when
-  *   filtering the elements. This only filters elements that have already been
-  *   processed by the once function. The ID should be the same ID that was
-  *   originally passed to the once() function. Defaults to `"once"`.
-  *
-  * @returns jQuery collection of elements that were acted upon to remove their
-  *    once data.
-  *
-  * @example
-  * ``` javascript
-  * // Remove once data with the "changecolor" ID. The result set is the
-  * // elements that had their once data removed.
-  * $('p').removeOnce("changecolor").css("color", "");
-  *
-  * // Any jQuery function can be performed on the result set.
-  * $("div.calendar").removeOnce().each(function() {
-  *   // Remove the calendar behavior.
-  * });
-  * ```
-  *
-  * @see once
-  * @this jQuery
-  *
-  * @global
-  * @public
-  */
-  $.fn.removeOnce = function (id) {
-    // Filter through the elements to find the once'd elements.
-    return this.findOnce(id).removeData("jquery-once-" + checkId(id));
+    return $.isFunction(fn) ? elements.each(fn) : elements;
   };
 
   /**
-  * Filters elements that have already been processed once.
-  *
-  * @param {string} [id="once"]
-  *   A string representing the name of the data id which should be used when
-  *   filtering the elements. This only filters elements that have already
-  *   been processed by the once function. The id should be the same id that
-  *   was originally passed to the once() function. Defaults to "once".
-  *
-  * @returns jQuery collection of elements that have been run once.
-  *
-  * @example
-  * ``` javascript
-  * // Find all elements that have been changecolor'ed once.
-  * $('p').findOnce('changecolor').each(function() {
-  *   // This function is called for all elements that has already once'd.
-  * });
-  *
-  * // Find all elements that have been acted on with the default "once" key.
-  * $('p').findOnce().each(function() {
-  *   // This function is called for all elements that have been acted on with
-  *   // a "once" action.
-  * });
-  * ```
-  *
-  * @see once
-  * @this jQuery
-  *
-  * @global
-  * @public
-  */
-  $.fn.findOnce = function (id) {
-    // Filter the elements by which do have the data.
-    var name = "jquery-once-" + checkId(id);
+   * Filters elements that have been processed once already.
+   *
+   * @param id
+   *   A required string representing the name of the class which should be used
+   *   when filtering the elements. This only filters elements that have already
+   *   been processed by the once function. The id should be the same id that
+   *   was originally passed to the once() function.
+   * @param fn
+   *   (Optional) If given, this function will be called for each element that
+   *   has not yet been processed. The function's return value follows the same
+   *   logic as $.each(). Returning true will continue to the next matched
+   *   element in the set, while returning false will entirely break the
+   *   iteration.
+   *
+   * @api public
+   */
+  $.fn.removeOnce = function (id, fn) {
+    var name = id + '-processed';
+    var elements = this.filter('.' + name).removeClass(name);
 
-    return this.filter(function() {
-      return $(this).data(name) === true;
-    });
+    return $.isFunction(fn) ? elements.each(fn) : elements;
   };
 }));
diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index faab889..edd97ac 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -21,19 +21,19 @@ ignore:
 # Basic scalar data types from typed data.
 boolean:
   label: 'Boolean'
-  class: '\Drupal\Core\TypedData\Plugin\DataType\BooleanData'
+  class: '\Drupal\Core\TypedData\Plugin\DataType\Boolean'
 email:
   label: 'Email'
   class: '\Drupal\Core\TypedData\Plugin\DataType\Email'
 integer:
   label: 'Integer'
-  class: '\Drupal\Core\TypedData\Plugin\DataType\IntegerData'
+  class: '\Drupal\Core\TypedData\Plugin\DataType\Integer'
 float:
   label: 'Float'
-  class: '\Drupal\Core\TypedData\Plugin\DataType\FloatData'
+  class: '\Drupal\Core\TypedData\Plugin\DataType\Float'
 string:
   label: 'String'
-  class: '\Drupal\Core\TypedData\Plugin\DataType\StringData'
+  class: '\Drupal\Core\TypedData\Plugin\DataType\String'
 uri:
   label: 'Uri'
   class: '\Drupal\Core\TypedData\Plugin\DataType\Uri'
@@ -295,6 +295,12 @@ block_settings:
         max_age:
           type: integer
           label: 'Maximum age'
+        contexts:
+          type: sequence
+          label: 'Vary by context'
+          sequence:
+            type: string
+            label: 'Context'
     status:
       type: boolean
       label: 'Status'
diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index c8ab09e..a6d963c 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -391,10 +391,10 @@ jquery.joyride:
 
 jquery.once:
   remote: https://github.com/RobLoach/jquery-once
-  version: 2.0.0
+  version: 1.2.3
   license:
     name: GNU-GPL-2.0-or-later
-    url: https://github.com/RobLoach/jquery-once/blob/master/LICENSE.md
+    url: https://github.com/RobLoach/jquery-once/blob/1.2.3/LICENSE
     gpl-compatible: true
   js:
     assets/vendor/jquery-once/jquery.once.js: { weight: -19 }
diff --git a/core/core.services.yml b/core/core.services.yml
index 8ce9b11..658c0a4 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -5,87 +5,32 @@ parameters:
     default: keyvalue.database
   factory.keyvalue.expirable:
     default: keyvalue.expirable.database
+  factory.queue: {}
+  reverse_proxy: {}
+  file_chmod: {}
+  session_write_interval: 180
+
 services:
-  # Simple cache contexts, directly derived from the request context.
-  cache_context.ip:
-    class: Drupal\Core\Cache\IpCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
-  cache_context.headers:
-    class: Drupal\Core\Cache\HeadersCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
-  cache_context.cookies:
-    class: Drupal\Core\Cache\CookiesCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
-  cache_context.request_format:
-    class: Drupal\Core\Cache\RequestFormatCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
+  cache_factory:
+    class: Drupal\Core\Cache\CacheFactory
+    arguments: ['@settings', '%cache_default_bin_backends%']
+    calls:
+      - [setContainer, ['@service_container']]
+  cache_contexts:
+    class: Drupal\Core\Cache\CacheContexts
+    arguments: ['@service_container', '%cache_contexts%' ]
   cache_context.url:
     class: Drupal\Core\Cache\UrlCacheContext
     arguments: ['@request_stack']
     tags:
-      - { name: cache.context }
-  cache_context.url.host:
-    class: Drupal\Core\Cache\HostCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
-  cache_context.url.query_args:
-    class: Drupal\Core\Cache\QueryArgsCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
-  cache_context.url.query_args.pagers:
-    class: Drupal\Core\Cache\PagersCacheContext
-    arguments: ['@request_stack']
-    tags:
-      - { name: cache.context }
-
-  # Complex cache contexts, that depend on the routing system.
-  cache_context.route:
-    class: Drupal\Core\Cache\RouteCacheContext
-    arguments: ['@current_route_match']
-    tags:
-      - { name: cache.context }
-  cache_context.route.name:
-    class: Drupal\Core\Cache\RouteNameCacheContext
-    arguments: ['@current_route_match']
-    tags:
-      - { name: cache.context }
-  cache_context.route.menu_active_trails:
-    class: Drupal\Core\Cache\MenuActiveTrailsCacheContext
-    calls:
-      - [setContainer, ['@service_container']]
-    tags:
-      - { name: cache.context }
-
-  # Complex cache contexts, that may be calculated from a combination of
-  # multiple aspects of the request context plus additional logic. Hence they
-  # are their own roots.
-  cache_context.user:
-    class: Drupal\Core\Cache\UserCacheContext
-    arguments: ['@current_user']
-    tags:
-      - { name: cache.context}
-  cache_context.user.roles:
-    class: Drupal\Core\Cache\UserRolesCacheContext
-    arguments: ['@current_user']
-    tags:
       - { name: cache.context}
-  cache_context.user.is_super_user:
-    class: Drupal\Core\Cache\IsSuperUserCacheContext
-    arguments: ['@current_user']
+  cache_context.pager:
+    class: Drupal\Core\Cache\PagerCacheContext
+    arguments: ['@request_stack']
     tags:
       - { name: cache.context}
-  cache_context.languages:
-    class: Drupal\Core\Cache\LanguagesCacheContext
+  cache_context.language:
+    class: Drupal\Core\Cache\LanguageCacheContext
     arguments: ['@language_manager']
     tags:
       - { name: cache.context}
@@ -98,15 +43,12 @@ services:
     class: Drupal\Core\Cache\TimeZoneCacheContext
     tags:
       - { name: cache.context}
-
-  cache_factory:
-    class: Drupal\Core\Cache\CacheFactory
-    arguments: ['@settings', '%cache_default_bin_backends%']
+  cache_context.menu.active_trail:
+    class: Drupal\Core\Cache\MenuActiveTrailCacheContext
     calls:
       - [setContainer, ['@service_container']]
-  cache_contexts:
-    class: Drupal\Core\Cache\CacheContexts
-    arguments: ['@service_container', '%cache_contexts%' ]
+    tags:
+      - { name: cache.context}
   cache_tags.invalidator:
     parent: container.trait
     class: Drupal\Core\Cache\CacheTagsInvalidator
@@ -271,7 +213,7 @@ services:
     arguments: [default]
   file_system:
     class: Drupal\Core\File\FileSystem
-    arguments: ['@stream_wrapper_manager', '@settings', '@logger.channel.file']
+    arguments: ['@stream_wrapper_manager', '%file_chmod%', '@logger.channel.file']
   form_builder:
     class: Drupal\Core\Form\FormBuilder
     arguments: ['@form_validator', '@form_submitter', '@form_cache', '@module_handler', '@event_dispatcher', '@request_stack', '@class_resolver', '@theme.manager', '@?csrf_token']
@@ -346,7 +288,7 @@ services:
     arguments: ['@keyvalue']
   queue:
     class: Drupal\Core\Queue\QueueFactory
-    arguments: ['@settings']
+    arguments: ['%factory.queue%']
     calls:
       - [setContainer, ['@service_container']]
   queue.database:
@@ -549,26 +491,14 @@ services:
   http_kernel.basic:
     class: Symfony\Component\HttpKernel\HttpKernel
     arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']
-  http_negotiation.format_negotiator:
-    class: Drupal\Core\ContentNegotiation
-    private: true
-  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:
     class: Drupal\Core\StackMiddleware\ReverseProxyMiddleware
-    arguments: ['@settings']
+    arguments: ['%reverse_proxy%']
     tags:
       - { name: http_middleware, priority: 300 }
   http_middleware.page_cache:
     class: Drupal\Core\StackMiddleware\PageCache
-    arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy']
+    arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy', '@content_negotiation']
     tags:
       - { name: http_middleware, priority: 200 }
   http_middleware.kernel_pre_handle:
@@ -590,7 +520,6 @@ services:
     arguments: ['%language.default_values%']
   string_translator.custom_strings:
     class: Drupal\Core\StringTranslation\Translator\CustomStrings
-    arguments: ['@settings']
     tags:
       - { name: string_translator, priority: 30 }
   string_translation:
@@ -646,7 +575,7 @@ services:
       - { name: backend_overridable }
   router.route_preloader:
     class: Drupal\Core\Routing\RoutePreloader
-    arguments: ['@router.route_provider', '@state']
+    arguments: ['@router.route_provider', '@state', '@content_negotiation']
     tags:
       - { name: 'event_subscriber' }
   router.matcher.final_matcher:
@@ -757,6 +686,7 @@ services:
     arguments: [16]
   accept_header_matcher:
     class: Drupal\Core\Routing\AcceptHeaderMatcher
+    arguments: ['@content_negotiation']
     tags:
       - { name: route_filter }
   content_type_header_matcher:
@@ -823,6 +753,7 @@ services:
       - { name: route_enhancer, priority: 20 }
   route_content_controller_subscriber:
     class: Drupal\Core\EventSubscriber\ContentControllerSubscriber
+    arguments: ['@content_negotiation']
     tags:
       - { name: event_subscriber }
   route_special_attributes_subscriber:
@@ -842,7 +773,7 @@ services:
       - { name: event_subscriber }
   main_content_renderer.html:
     class: Drupal\Core\Render\MainContent\HtmlRenderer
-    arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler', '@renderer', '@cache_contexts']
+    arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler', '@renderer']
     tags:
       - { name: render.main_content_renderer, format: html }
   main_content_renderer.ajax:
@@ -872,11 +803,13 @@ services:
     tags:
       - { name: event_subscriber }
     arguments: ['@router', '@router.request_context', NULL, '@request_stack']
+  content_negotiation:
+    class: Drupal\Core\ContentNegotiation
   view_subscriber:
     class: Drupal\Core\EventSubscriber\ViewSubscriber
-    arguments: ['@title_resolver']
     tags:
       - { name: event_subscriber }
+    arguments: ['@content_negotiation', '@title_resolver']
   bare_html_page_renderer:
     class: Drupal\Core\Render\BareHtmlPageRenderer
     arguments: ['@renderer']
@@ -1074,6 +1007,10 @@ services:
       - { name: event_subscriber }
     calls:
       - [setContainer, ['@service_container']]
+  ajax.subscriber:
+    class: Drupal\Core\Ajax\AjaxSubscriber
+    tags:
+      - { name: event_subscriber }
   image.toolkit.manager:
     class: Drupal\Core\ImageToolkit\ImageToolkitManager
     arguments: ['@config.factory']
@@ -1208,7 +1145,7 @@ services:
     alias: session_handler.storage
   session_handler.storage:
     class: Drupal\Core\Session\SessionHandler
-    arguments: ['@request_stack', '@database']
+    arguments: ['@request_stack', '@database', '%session_write_interval%']
     tags:
       - { name: backend_overridable }
   session_handler.write_check:
@@ -1228,7 +1165,7 @@ services:
       - [setWriteSafeHandler, ['@session_handler.write_safe']]
   session_manager.metadata_bag:
     class: Drupal\Core\Session\MetadataBag
-    arguments: ['@settings']
+    arguments: ['%session_write_interval%']
   asset.css.collection_renderer:
     class: Drupal\Core\Asset\CssCollectionRenderer
     arguments: [ '@state' ]
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 26a75f6..27d9576 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -8,6 +8,7 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\Environment;
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Extension\ExtensionDiscovery;
@@ -428,12 +429,12 @@ function t($string, array $args = array(), array $options = array()) {
 /**
  * Formats a string for HTML display by replacing variable placeholders.
  *
- * @see \Drupal\Component\Utility\SafeMarkup::format()
+ * @see \Drupal\Component\Utility\String::format()
  * @see t()
  * @ingroup sanitization
  */
 function format_string($string, array $args = array()) {
-  return SafeMarkup::format($string, $args);
+  return String::format($string, $args);
 }
 
 /**
@@ -494,7 +495,7 @@ function watchdog_exception($type, Exception $exception, $message = NULL, $varia
   // Use a default value if $message is not set.
   if (empty($message)) {
     // The exception message is run through
-    // \Drupal\Component\Utility\SafeMarkup::checkPlain() by
+    // \Drupal\Component\Utility\String::checkPlain() by
     // \Drupal\Core\Utility\Error:decodeException().
     $message = '%type: !message in %function (line %line of %file).';
   }
@@ -1021,10 +1022,10 @@ function drupal_static_reset($name = NULL) {
 /**
  * Formats text for emphasized display in a placeholder inside a sentence.
  *
- * @see \Drupal\Component\Utility\SafeMarkup::placeholder()
+ * @see \Drupal\Component\Utility\String::placeholder()
  */
 function drupal_placeholder($text) {
-  return SafeMarkup::placeholder($text);
+  return String::placeholder($text);
 }
 
 /**
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index a6e918f..a651a3a 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -98,7 +98,7 @@ function install_drupal($class_loader, $settings = array()) {
   //   infrastructure in https://www.drupal.org/node/2389243
   if (is_array($class_loader) && $settings === array()) {
     $settings = $class_loader;
-    $class_loader = require __DIR__ . '/../../autoload.php';
+    $class_loader = require __DIR__ . '/../vendor/autoload.php';
   }
 
   global $install_state;
@@ -346,10 +346,11 @@ function install_begin_request($class_loader, &$install_state) {
   $container
     ->register('stream_wrapper_manager', 'Drupal\Core\StreamWrapper\StreamWrapperManager')
     ->addMethodCall('setContainer', array(new Reference('service_container')));
+  $container->setParameter('file_chmod', []);
   $container
     ->register('file_system', 'Drupal\Core\File\FileSystem')
     ->addArgument(new Reference('stream_wrapper_manager'))
-    ->addArgument(Settings::getInstance())
+    ->addArgument('%file_chmod%')
     ->addArgument((new LoggerChannelFactory())->get('file'));
 
   \Drupal::setContainer($container);
@@ -741,8 +742,6 @@ function install_tasks($install_state) {
     ),
     'install_profile_themes' => array(
     ),
-    'install_install_profile' => array(
-    ),
     'install_import_translations' => array(
       'display_name' => t('Set up translations'),
       'display' => $needs_translations,
@@ -1024,6 +1023,10 @@ function install_base_system(&$install_state) {
   // State can be set to the database now that system.module is installed.
   $modules = $install_state['profile_info']['dependencies'];
 
+  // The installation profile is also a module, which needs to be installed
+  // after all the dependencies have been installed.
+  $modules[] = drupal_get_profile();
+
   \Drupal::state()->set('install_profile_modules', array_diff($modules, array('system')));
   $install_state['base_system_verified'] = TRUE;
 }
@@ -1569,7 +1572,10 @@ function install_profile_modules(&$install_state) {
   // the modules.
   $required = array();
   $non_required = array();
-
+  // Although the profile module is marked as required, it needs to go after
+  // every dependency, including non-required ones. So clear its required
+  // flag for now to allow it to install late.
+  $files[$install_state['parameters']['profile']]->info['required'] = FALSE;
   // Add modules that other modules depend on.
   foreach ($modules as $module) {
     if ($files[$module]->requires) {
@@ -1611,35 +1617,21 @@ function install_profile_modules(&$install_state) {
  *   An array of information about the current installation state.
  */
 function install_profile_themes(&$install_state) {
-  // Install the themes specified by the installation profile.
-  $themes = $install_state['profile_info']['themes'];
-  \Drupal::service('theme_handler')->install($themes);
+  $theme_handler = \Drupal::service('theme_handler');
 
-  // Ensure that the install profile's theme is used.
+  // ThemeHandler::install() resets the current list of themes. The theme used
+  // in the installer is not necessarily in the list of themes to install, so
+  // retain the current list.
   // @see _drupal_maintenance_theme()
-  \Drupal::service('theme.manager')->resetActiveTheme();
-}
+  $current_themes = $theme_handler->listInfo();
 
-/**
- * Installs the install profile.
- *
- * @param $install_state
- *   An array of information about the current installation state.
- */
-function install_install_profile(&$install_state) {
-  \Drupal::service('module_installer')->install(array(drupal_get_profile()), FALSE);
-  // Install all available optional config. During installation the module order
-  // is determined by dependencies. If there are no dependencies between modules
-  // then the order in which they are installed is dependent on random factors
-  // like PHP version. Optional configuration therefore might or might not be
-  // created depending on this order. Ensuring that we have installed all of the
-  // optional configuration whose dependencies can be met at this point removes
-  // any disparities that this creates.
-  \Drupal::service('config.installer')->installOptionalConfig();
-
-  // Ensure that the install profile's theme is used.
-  // @see _drupal_maintenance_theme()
-  \Drupal::service('theme.manager')->resetActiveTheme();
+  // Install the themes specified by the installation profile.
+  $themes = $install_state['profile_info']['themes'];
+  $theme_handler->install($themes);
+
+  foreach ($current_themes as $theme) {
+    $theme_handler->addTheme($theme);
+  }
 }
 
 /**
@@ -1664,10 +1656,7 @@ function install_download_additional_translations_operations(&$install_state) {
   // If a non-English language was selected, change the default language and
   // remove English.
   if ($langcode != 'en') {
-    \Drupal::configFactory()->getEditable('system.site')
-      ->set('langcode', $langcode)
-      ->set('default_langcode', $langcode)
-      ->save();
+    \Drupal::configFactory()->getEditable('system.site')->set('langcode', $langcode)->save();
     \Drupal::service('language.default')->set($language);
     if (empty($install_state['profile_info']['keep_english'])) {
       entity_delete_multiple('configurable_language', array('en'));
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 61d286b..e247378 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -620,7 +620,6 @@ function drupal_install_system($install_state) {
   if (isset($install_state['parameters']['langcode'])) {
     \Drupal::configFactory()->getEditable('system.site')
       ->set('langcode', $install_state['parameters']['langcode'])
-      ->set('default_langcode', $install_state['parameters']['langcode'])
       ->save();
   }
 }
diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc
index 16779af..d63ce1b 100644
--- a/core/includes/theme.maintenance.inc
+++ b/core/includes/theme.maintenance.inc
@@ -68,10 +68,11 @@ function _drupal_maintenance_theme() {
   // installed, retrieve all available themes.
   /** @var \Drupal\Core\Theme\ThemeInitialization $theme_init */
   $theme_init = \Drupal::service('theme.initialization');
-  $theme_handler = \Drupal::service('theme_handler');
   if (empty($themes) || !isset($themes[$custom_theme])) {
+    $theme_handler = \Drupal::service('theme_handler');
     $themes = $theme_handler->rebuildThemeData();
     $theme_handler->addTheme($themes[$custom_theme]);
+    \Drupal::theme()->setActiveTheme($theme_init->getActiveTheme($themes[$custom_theme], array()));
   }
 
   // \Drupal\Core\Extension\ThemeHandlerInterface::listInfo() triggers a
@@ -85,12 +86,8 @@ function _drupal_maintenance_theme() {
   $base_theme = array();
   $ancestor = $theme;
   while ($ancestor && isset($themes[$ancestor]->base_theme)) {
-    $base_theme[] = $themes[$themes[$ancestor]->base_theme];
+    $base_theme[] = $new_base_theme = $themes[$themes[$ancestor]->base_theme];
     $ancestor = $themes[$ancestor]->base_theme;
-    if ($ancestor) {
-      // Ensure that the base theme is added.
-      $theme_handler->addTheme($themes[$ancestor]);
-    }
   }
   // @todo This is just a workaround. Find a better way how to handle themes
   //   on maintenance pages, see https://www.drupal.org/node/2322619.
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index f949669..17be145 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -342,14 +342,8 @@ public static function configFactory() {
   /**
    * Returns a queue for the given queue name.
    *
-   * The following values can be set in your settings.php file's $settings
-   * array to define which services are used for queues:
-   * - queue_reliable_service_$name: The container service to use for the
-   *   reliable queue $name.
-   * - queue_service_$name: The container service to use for the
-   *   queue $name.
-   * - queue_default: The container service to use by default for queues
-   *   without overrides. This defaults to 'queue.database'.
+   * The configuration can be set as container parameters in the services.yml
+   * file, see sites/default/default.services.yml.
    *
    * @param string $name
    *   The name of the queue to work with.
diff --git a/core/lib/Drupal/Component/Utility/Html.php b/core/lib/Drupal/Component/Utility/Html.php
index 60b83df..4dd9d27 100644
--- a/core/lib/Drupal/Component/Utility/Html.php
+++ b/core/lib/Drupal/Component/Utility/Html.php
@@ -359,21 +359,4 @@ public static function escapeCdataElement(\DOMNode $node, $comment_start = '//',
     }
   }
 
-  /**
-   * Decodes all HTML entities including numerical ones to regular UTF-8 bytes.
-   *
-   * Double-escaped entities will only be decoded once ("&amp;lt;" becomes
-   * "&lt;", not "<"). Be careful when using this function, as it will revert
-   * previous sanitization efforts (&lt;script&gt; will become <script>).
-   *
-   * @param string $text
-   *   The text to decode entities in.
-   *
-   * @return string
-   *   The input $text, with all HTML entities decoded once.
-   */
-  public static function decodeEntities($text) {
-    return html_entity_decode($text, ENT_QUOTES, 'UTF-8');
-  }
-
 }
diff --git a/core/lib/Drupal/Component/Utility/SafeMarkup.php b/core/lib/Drupal/Component/Utility/SafeMarkup.php
index 7a7b8ea..56bd518 100644
--- a/core/lib/Drupal/Component/Utility/SafeMarkup.php
+++ b/core/lib/Drupal/Component/Utility/SafeMarkup.php
@@ -15,7 +15,7 @@
  * provides a store for known safe strings and methods to manage them
  * throughout the page request.
  *
- * Strings sanitized by self::checkPlain() or Xss::filter() are automatically
+ * Strings sanitized by String::checkPlain() or Xss::filter() are automatically
  * marked safe, as are markup strings created from render arrays via
  * drupal_render().
  *
@@ -133,7 +133,7 @@ public static function setMultiple(array $safe_strings) {
    *   self::set(), it won't be escaped again.
    */
   public static function escape($string) {
-    return static::isSafe($string) ? $string : static::checkPlain($string);
+    return static::isSafe($string) ? $string : String::checkPlain($string);
   }
 
   /**
@@ -165,121 +165,4 @@ public static function getAll() {
     return static::$safeStrings;
   }
 
-  /**
-   * Encodes special characters in a plain-text string for display as HTML.
-   *
-   * Also validates strings as UTF-8. All processed strings are also
-   * automatically flagged as safe markup strings for rendering.
-   *
-   * @param string $text
-   *   The text to be checked or processed.
-   *
-   * @return string
-   *   An HTML safe version of $text, or an empty string if $text is not valid
-   *   UTF-8.
-   *
-   * @ingroup sanitization
-   *
-   * @see drupal_validate_utf8()
-   */
-  public static function checkPlain($text) {
-    $string = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
-    static::$safeStrings[$string]['html'] = TRUE;
-    return $string;
-  }
-
-  /**
-   * Formats a string for HTML display by replacing variable placeholders.
-   *
-   * This function replaces variable placeholders in a string with the requested
-   * values and escapes the values so they can be safely displayed as HTML. It
-   * should be used on any unknown text that is intended to be printed to an
-   * HTML page (especially text that may have come from untrusted users, since
-   * in that case it prevents cross-site scripting and other security problems).
-   *
-   * In most cases, you should use t() rather than calling this function
-   * directly, since it will translate the text (on non-English-only sites) in
-   * addition to formatting it.
-   *
-   * @param string $string
-   *   A string containing placeholders. The string itself is not escaped, any
-   *   unsafe content must be in $args and inserted via placeholders.
-   * @param array $args
-   *   An associative array of replacements to make. Occurrences in $string of
-   *   any key in $args are replaced with the corresponding value, after
-   *   optional sanitization and formatting. The type of sanitization and
-   *   formatting depends on the first character of the key:
-   *   - @variable: Escaped to HTML using self::escape(). Use this as the
-   *     default choice for anything displayed on a page on the site.
-   *   - %variable: Escaped to HTML and formatted using self::placeholder(),
-   *     which makes the following HTML code:
-   *     @code
-   *       <em class="placeholder">text output here.</em>
-   *     @endcode
-   *   - !variable: Inserted as is, with no sanitization or formatting. Only
-   *     use this when the resulting string is being generated for one of:
-   *     - Non-HTML usage, such as a plain-text email.
-   *     - Non-direct HTML output, such as a plain-text variable that will be
-   *       printed as an HTML attribute value and therefore formatted with
-   *       self::checkPlain() as part of that.
-   *     - Some other special reason for suppressing sanitization.
-   *
-   * @return string
-   *   The formatted string, which is marked as safe unless sanitization of an
-   *   unsafe argument was suppressed (see above).
-   *
-   * @ingroup sanitization
-   *
-   * @see t()
-   */
-  public static function format($string, array $args = array()) {
-    $safe = TRUE;
-
-    // Transform arguments before inserting them.
-    foreach ($args as $key => $value) {
-      switch ($key[0]) {
-        case '@':
-          // Escaped only.
-          $args[$key] = static::escape($value);
-          break;
-
-        case '%':
-        default:
-          // Escaped and placeholder.
-          $args[$key] = static::placeholder($value);
-          break;
-
-        case '!':
-          // Pass-through.
-          if (!static::isSafe($value)) {
-            $safe = FALSE;
-          }
-      }
-    }
-
-    $output = strtr($string, $args);
-    if ($safe) {
-      static::$safeStrings[$output]['html'] = TRUE;
-    }
-
-    return $output;
-  }
-
-  /**
-   * Formats text for emphasized display in a placeholder inside a sentence.
-   *
-   * Used automatically by self::format().
-   *
-   * @param string $text
-   *   The text to format (plain-text).
-   *
-   * @return string
-   *   The formatted text (html).
-   */
-  public static function placeholder($text) {
-    $string = '<em class="placeholder">' . static::escape($text) . '</em>';
-    static::$safeStrings[$string]['html'] = TRUE;
-    return $string;
-  }
-
 }
diff --git a/core/lib/Drupal/Component/Utility/String.php b/core/lib/Drupal/Component/Utility/String.php
index 5bacf72..b39ca5d 100644
--- a/core/lib/Drupal/Component/Utility/String.php
+++ b/core/lib/Drupal/Component/Utility/String.php
@@ -17,6 +17,9 @@ class String {
   /**
    * Encodes special characters in a plain-text string for display as HTML.
    *
+   * Also validates strings as UTF-8. All processed strings are also
+   * automatically flagged as safe markup strings for rendering.
+   *
    * @param string $text
    *   The text to be checked or processed.
    *
@@ -24,32 +27,45 @@ class String {
    *   An HTML safe version of $text, or an empty string if $text is not
    *   valid UTF-8.
    *
-   * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
-   *   Use \Drupal\Component\Utility\SafeMarkup::checkPlain() instead.
+   * @ingroup sanitization
+   *
+   * @see drupal_validate_utf8()
+   * @see \Drupal\Component\Utility\SafeMarkup
    */
   public static function checkPlain($text) {
-    return SafeMarkup::checkPlain($text);
+    return SafeMarkup::set(htmlspecialchars($text, ENT_QUOTES, 'UTF-8'));
   }
 
   /**
    * Decodes all HTML entities including numerical ones to regular UTF-8 bytes.
    *
+   * Double-escaped entities will only be decoded once ("&amp;lt;" becomes
+   * "&lt;", not "<"). Be careful when using this function, as it will revert
+   * previous sanitization efforts (&lt;script&gt; will become <script>).
+   *
    * @param string $text
    *   The text to decode entities in.
    *
    * @return string
    *   The input $text, with all HTML entities decoded once.
-   *
-   * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
-   *   Use \Drupal\Component\Utility\Html::decodeEntities() instead.
    */
   public static function decodeEntities($text) {
-    return Html::decodeEntities($text);
+    return html_entity_decode($text, ENT_QUOTES, 'UTF-8');
   }
 
   /**
    * Formats a string for HTML display by replacing variable placeholders.
    *
+   * This function replaces variable placeholders in a string with the requested
+   * values and escapes the values so they can be safely displayed as HTML. It
+   * should be used on any unknown text that is intended to be printed to an
+   * HTML page (especially text that may have come from untrusted users, since
+   * in that case it prevents cross-site scripting and other security problems).
+   *
+   * In most cases, you should use t() rather than calling this function
+   * directly, since it will translate the text (on non-English-only sites) in
+   * addition to formatting it.
+   *
    * @param $string
    *   A string containing placeholders. The string itself is not escaped, any
    *   unsafe content must be in $args and inserted via placeholders.
@@ -78,27 +94,57 @@ public static function decodeEntities($text) {
    *   The formatted string, which is marked as safe unless sanitization of an
    *   unsafe argument was suppressed (see above).
    *
-   * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
-   *   Use \Drupal\Component\Utility\SafeMarkup::format() instead.
+   * @ingroup sanitization
+   *
+   * @see t()
    */
   public static function format($string, array $args = array()) {
-    return SafeMarkup::format($string, $args);
+    $safe = TRUE;
+
+    // Transform arguments before inserting them.
+    foreach ($args as $key => $value) {
+      switch ($key[0]) {
+        case '@':
+          // Escaped only.
+          $args[$key] = SafeMarkup::escape($value);
+          break;
+
+        case '%':
+        default:
+          // Escaped and placeholder.
+          $args[$key] = static::placeholder($value);
+          break;
+
+        case '!':
+          // Pass-through.
+          if (!SafeMarkup::isSafe($value)) {
+            $safe = FALSE;
+          }
+      }
+    }
+
+    $output = strtr($string, $args);
+    if ($safe) {
+      SafeMarkup::set($output);
+    }
+
+    return $output;
   }
 
   /**
    * Formats text for emphasized display in a placeholder inside a sentence.
    *
+   * Used automatically by self::format().
+   *
    * @param string $text
    *   The text to format (plain-text).
    *
    * @return string
    *   The formatted text (html).
-   *
-   * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
-   *   Use \Drupal\Component\Utility\SafeMarkup::placeholder() instead.
    */
   public static function placeholder($text) {
-    return SafeMarkup::placeholder($text);
+    return SafeMarkup::set('<em class="placeholder">' . SafeMarkup::escape($text) . '</em>');
   }
 
+
 }
diff --git a/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php b/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php
new file mode 100644
index 0000000..f298d88
--- /dev/null
+++ b/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Ajax\AjaxSubscriber.
+ */
+
+namespace Drupal\Core\Ajax;
+
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Subscribes to the kernel request event to add the Ajax media type.
+ *
+ * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+ *   The event to process.
+ */
+class AjaxSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Registers Ajax formats with the Request class.
+   */
+  public function onKernelRequest(GetResponseEvent $event) {
+    $request = $event->getRequest();
+    $request->setFormat('drupal_ajax', 'application/vnd.drupal-ajax');
+    $request->setFormat('drupal_dialog', 'application/vnd.drupal-dialog');
+    $request->setFormat('drupal_modal', 'application/vnd.drupal-modal');
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents(){
+    $events[KernelEvents::REQUEST][] = array('onKernelRequest', 50);
+    return $events;
+  }
+
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php
index 15d3ebf..b8a7999 100644
--- a/core/lib/Drupal/Core/Block/BlockBase.php
+++ b/core/lib/Drupal/Core/Block/BlockBase.php
@@ -10,6 +10,7 @@
 use Drupal\block\BlockInterface;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\CacheContexts;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContextAwarePluginBase;
 use Drupal\Component\Utility\Unicode;
@@ -90,8 +91,8 @@ protected function baseConfigurationDefaults() {
       'provider' => $this->pluginDefinition['provider'],
       'label_display' => BlockInterface::BLOCK_LABEL_VISIBLE,
       'cache' => array(
-        // Blocks are cacheable by default.
-        'max_age' => Cache::PERMANENT,
+        'max_age' => 0,
+        'contexts' => array(),
       ),
     );
   }
@@ -203,6 +204,36 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       '#default_value' => $this->configuration['cache']['max_age'],
       '#options' => $period,
     );
+    $contexts = \Drupal::service("cache_contexts")->getLabels();
+    // Blocks are always rendered in the "per language" and "per theme" cache
+    // contexts. No need to show those options to the end user.
+    unset($contexts['language']);
+    unset($contexts['theme']);
+    $form['cache']['contexts'] = array(
+      '#type' => 'checkboxes',
+      '#title' => $this->t('Vary by context'),
+      '#description' => $this->t('The contexts this cached block must be varied by. <em>All</em> blocks are varied by language and theme.'),
+      '#default_value' => $this->configuration['cache']['contexts'],
+      '#options' => $contexts,
+      '#states' => array(
+        'disabled' => array(
+          ':input[name="settings[cache][max_age]"]' => array('value' => (string) 0),
+        ),
+      ),
+    );
+    if (count($this->getRequiredCacheContexts()) > 0) {
+      // Remove the required cache contexts from the list of contexts a user can
+      // choose to modify by: they must always be applied.
+      $context_labels = array();
+      $all_contexts = \Drupal::service("cache_contexts")->getLabels(TRUE);
+      foreach (CacheContexts::parseTokens($this->getRequiredCacheContexts()) as $context) {
+        $context_id = $context[0];
+        $context_labels[] = $all_contexts[$context_id];
+        unset($form['cache']['contexts']['#options'][$context_id]);
+      }
+      $required_context_list = implode(', ', $context_labels);
+      $form['cache']['contexts']['#description'] .= ' ' . $this->t('This block is <em>always</em> varied by the following contexts: %required-context-list.', array('%required-context-list' => $required_context_list));
+    }
 
     // Add plugin-specific settings for this block type.
     $form += $this->blockForm($form, $form_state);
@@ -228,6 +259,10 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form
     // Remove the admin_label form item element value so it will not persist.
     $form_state->unsetValue('admin_label');
 
+    // Transform the #type = checkboxes value to a numerically indexed array.
+    $contexts = $form_state->getValue(array('cache', 'contexts'));
+    $form_state->setValue(array('cache', 'contexts'), array_values(array_filter($contexts)));
+
     $this->blockValidate($form, $form_state);
   }
 
@@ -306,6 +341,16 @@ public function setTransliteration(TransliterationInterface $transliteration) {
   }
 
   /**
+   * Returns the cache contexts required for this block.
+   *
+   * @return array
+   *   The required cache contexts IDs.
+   */
+  protected function getRequiredCacheContexts() {
+    return array();
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getCacheKeys() {
@@ -316,7 +361,9 @@ public function getCacheKeys() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return [];
+    // Return the required cache contexts, merged with the user-configured cache
+    // contexts, if any.
+    return array_merge($this->getRequiredCacheContexts(), $this->configuration['cache']['contexts']);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Cache/AccountPermissionsCacheContext.php b/core/lib/Drupal/Core/Cache/AccountPermissionsCacheContext.php
deleted file mode 100644
index e69de29..0000000
diff --git a/core/lib/Drupal/Core/Cache/CacheContexts.php b/core/lib/Drupal/Core/Cache/CacheContexts.php
index 781f24a..33f86b1 100644
--- a/core/lib/Drupal/Core/Cache/CacheContexts.php
+++ b/core/lib/Drupal/Core/Cache/CacheContexts.php
@@ -105,7 +105,6 @@ public function getLabels($include_calculated_cache_contexts = FALSE) {
    * @throws \InvalidArgumentException
    */
   public function convertTokensToKeys(array $context_tokens) {
-    $context_tokens = $this->optimizeTokens($context_tokens);
     sort($context_tokens);
     $keys = [];
     foreach (static::parseTokens($context_tokens) as $context) {
@@ -119,69 +118,6 @@ public function convertTokensToKeys(array $context_tokens) {
   }
 
   /**
-   * Optimizes cache context tokens (the minimal representative subset).
-   *
-   * A minimal representative subset means that any cache context token in the
-   * given set of cache context tokens that is a property of another cache
-   * context cache context token in the set, is removed.
-   *
-   * Hence a minimal representative subset is the most compact representation
-   * possible of a set of cache context tokens, that still captures the entire
-   * universe of variations.
-   *
-   * E.g. when caching per user ('user'), also caching per role ('user.roles')
-   * is meaningless because "per role" is implied by "per user".
-   *
-   * Examples — remember that the period indicates hierarchy and the colon can
-   * be used to get a specific value of a calculated cache context:
-   * - ['a', 'a.b'] -> ['a']
-   * - ['a', 'a.b.c'] -> ['a']
-   * - ['a.b', 'a.b.c'] -> ['a.b']
-   * - ['a', 'a.b', 'a.b.c'] -> ['a']
-   * - ['x', 'x:foo'] -> ['x']
-   * - ['a', 'a.b.c:bar'] -> ['a']
-   *
-   * @param string[] $context_tokens
-   *   A set of cache context tokens.
-   *
-   * @return string[]
-   *   A representative subset of the given set of cache context tokens..
-   */
-  public function optimizeTokens(array $context_tokens) {
-    $optimized_content_tokens = [];
-    foreach ($context_tokens as $context_token) {
-      // Context tokens without:
-      // - a period means they don't have a parent
-      // - a colon means they're not a specific value of a cache context
-      // hence no optimizations are possible.
-      if (strpos($context_token, '.') === FALSE && strpos($context_token, ':') === FALSE) {
-        $optimized_content_tokens[] = $context_token;
-      }
-      // The context token has a period or a colon. Iterate over all ancestor
-      // cache contexts. If one exists, omit the context token.
-      else {
-        $ancestor_found = FALSE;
-        // Treat a colon like a period, that allows us to consider 'a' the
-        // ancestor of 'a:foo', without any additional code for the colon.
-        $ancestor = str_replace(':', '.', $context_token);
-        do {
-          $ancestor = substr($ancestor, 0, strrpos($ancestor, '.'));
-          if (in_array($ancestor, $context_tokens)) {
-            // An ancestor cache context is in $context_tokens, hence this cache
-            // context is implied.
-            $ancestor_found = TRUE;
-          }
-
-        } while(!$ancestor_found && strpos($ancestor, '.') !== FALSE);
-        if (!$ancestor_found) {
-          $optimized_content_tokens[] = $context_token;
-        }
-      }
-    }
-    return $optimized_content_tokens;
-  }
-
-  /**
    * Retrieves a cache context service from the container.
    *
    * @param string $context_id
diff --git a/core/lib/Drupal/Core/Cache/CacheContextsPass.php b/core/lib/Drupal/Core/Cache/CacheContextsPass.php
index 576b2b5..b1cb74e 100644
--- a/core/lib/Drupal/Core/Cache/CacheContextsPass.php
+++ b/core/lib/Drupal/Core/Cache/CacheContextsPass.php
@@ -28,20 +28,6 @@ public function process(ContainerBuilder $container) {
       }
       $cache_contexts[] = substr($id, 14);
     }
-
-    // Validate.
-    sort($cache_contexts);
-    foreach ($cache_contexts as $id) {
-      // Validate the hierarchy of non-root-level cache contexts.
-      if (strpos($id, '.') !== FALSE) {
-        $parent = substr($id, 0, strrpos($id, '.'));
-        if (!in_array($parent, $cache_contexts)) {
-          throw new \InvalidArgumentException(sprintf('The service "%s" has an invalid service ID: the period indicates the hierarchy of cache contexts, therefore "%s" is considered the parent cache context, but no cache context service with that name was found.', $id, $parent));
-        }
-      }
-    }
-
-
     $container->setParameter('cache_contexts', $cache_contexts);
   }
 
diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php
index 0a0a977..61e2f56 100644
--- a/core/lib/Drupal/Core/Cache/CacheFactory.php
+++ b/core/lib/Drupal/Core/Cache/CacheFactory.php
@@ -20,13 +20,6 @@ class CacheFactory implements CacheFactoryInterface,  ContainerAwareInterface {
   use ContainerAwareTrait;
 
   /**
-   * The settings array.
-   *
-   * @var \Drupal\Core\Site\Settings
-   */
-  protected $settings;
-
-  /**
    * A map of cache bin to default cache backend service name.
    *
    * All mappings in $settings takes precedence over this, but this can be used
@@ -40,6 +33,13 @@ class CacheFactory implements CacheFactoryInterface,  ContainerAwareInterface {
   protected $defaultBinBackends;
 
   /**
+   * The cache settings.
+   *
+   * @var array
+   */
+  protected $cacheSettings;
+
+  /**
    * Constructs CacheFactory object.
    *
    * @param \Drupal\Core\Site\Settings $settings
@@ -49,7 +49,7 @@ class CacheFactory implements CacheFactoryInterface,  ContainerAwareInterface {
    *   $settings take precedence over this.
    */
   public function __construct(Settings $settings, array $default_bin_backends = array()) {
-    $this->settings = $settings;
+    $this->cacheSettings = $settings->get('cache');
     $this->defaultBinBackends = $default_bin_backends;
   }
 
@@ -69,12 +69,11 @@ public function __construct(Settings $settings, array $default_bin_backends = ar
    *   The cache backend object associated with the specified bin.
    */
   public function get($bin) {
-    $cache_settings = $this->settings->get('cache');
-    if (isset($cache_settings['bins'][$bin])) {
-      $service_name = $cache_settings['bins'][$bin];
+    if (isset($this->cacheSettings['bins'][$bin])) {
+      $service_name = $this->cacheSettings['bins'][$bin];
     }
-    elseif (isset($cache_settings['default'])) {
-      $service_name = $cache_settings['default'];
+    elseif (isset($this->cacheSettings['default'])) {
+      $service_name = $this->cacheSettings['default'];
     }
     elseif (isset($this->defaultBinBackends[$bin])) {
       $service_name = $this->defaultBinBackends[$bin];
diff --git a/core/lib/Drupal/Core/Cache/CalculatedCacheContextInterface.php b/core/lib/Drupal/Core/Cache/CalculatedCacheContextInterface.php
index 38114c3..795a512 100644
--- a/core/lib/Drupal/Core/Cache/CalculatedCacheContextInterface.php
+++ b/core/lib/Drupal/Core/Cache/CalculatedCacheContextInterface.php
@@ -28,13 +28,12 @@ public static function getLabel();
    * A cache context service's name is used as a token (placeholder) cache key,
    * and is then replaced with the string returned by this method.
    *
-   * @param string|null $parameter
-   *   The parameter, or NULL to indicate all possible parameter values.
+   * @param string $parameter
+   *   The parameter.
    *
    * @return string
-   *   The string representation of the cache context. When $parameter is NULL,
-   *   a value representing all possible parameters must be generated.
+   *   The string representation of the cache context.
    */
-  public function getContext($parameter = NULL);
+  public function getContext($parameter);
 
 }
diff --git a/core/lib/Drupal/Core/Cache/CookiesCacheContext.php b/core/lib/Drupal/Core/Cache/CookiesCacheContext.php
deleted file mode 100644
index 6760b1b..0000000
--- a/core/lib/Drupal/Core/Cache/CookiesCacheContext.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\CookiesCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the CookiesCacheContext service, for "per cookie" caching.
- */
-class CookiesCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('HTTP cookies');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($cookie = NULL) {
-    if ($cookie === NULL) {
-      return $this->requestStack->getCurrentRequest()->cookies->all();
-    }
-    else {
-      return $this->requestStack->getCurrentRequest()->cookies->get($cookie);
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/HeadersCacheContext.php b/core/lib/Drupal/Core/Cache/HeadersCacheContext.php
deleted file mode 100644
index e2b8932..0000000
--- a/core/lib/Drupal/Core/Cache/HeadersCacheContext.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\HeadersCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the HeadersCacheContext service, for "per header" caching.
- */
-class HeadersCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('HTTP headers');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($header = NULL) {
-    if ($header === NULL) {
-      return $this->requestStack->getCurrentRequest()->headers->all();
-    }
-    else {
-      return $this->requestStack->getCurrentRequest()->headers->get($header);
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/HostCacheContext.php b/core/lib/Drupal/Core/Cache/HostCacheContext.php
deleted file mode 100644
index 8a3af00..0000000
--- a/core/lib/Drupal/Core/Cache/HostCacheContext.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\HostCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the HostCacheContext service, for "per host" caching.
- *
- * A "host" is defined as the combination of URI scheme, domain name and port.
- *
- * @see Symfony\Component\HttpFoundation::getSchemeAndHttpHost()
- */
-class HostCacheContext extends RequestStackCacheContextBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Host');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return $this->requestStack->getCurrentRequest()->getSchemeAndHttpHost();
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/IpCacheContext.php b/core/lib/Drupal/Core/Cache/IpCacheContext.php
deleted file mode 100644
index c0c2e08..0000000
--- a/core/lib/Drupal/Core/Cache/IpCacheContext.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\IpCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the IpCacheContext service, for "per IP address" caching.
- */
-class IpCacheContext extends RequestStackCacheContextBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('IP address');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return $this->requestStack->getCurrentRequest()->getClientIp();
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/IsSuperUserCacheContext.php b/core/lib/Drupal/Core/Cache/IsSuperUserCacheContext.php
deleted file mode 100644
index 6569715..0000000
--- a/core/lib/Drupal/Core/Cache/IsSuperUserCacheContext.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\IsSuperUserCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the IsSuperUserCacheContext service, for "super user or not" caching.
- */
-class IsSuperUserCacheContext extends UserCacheContext {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Is super user');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return ((int) $this->user->id()) === 1 ? '1' : '0';
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/LanguageCacheContext.php b/core/lib/Drupal/Core/Cache/LanguageCacheContext.php
new file mode 100644
index 0000000..b9d19a7
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/LanguageCacheContext.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\LanguageCacheContext.
+ */
+
+namespace Drupal\Core\Cache;
+
+use Drupal\Core\Language\LanguageManagerInterface;
+
+/**
+ * Defines the LanguageCacheContext service, for "per language" caching.
+ */
+class LanguageCacheContext implements CacheContextInterface {
+
+  /**
+   * The language manager.
+   *
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   */
+  protected $languageManager;
+
+  /**
+   * Constructs a new LanguageCacheContext service.
+   *
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   */
+  public function __construct(LanguageManagerInterface $language_manager) {
+    $this->languageManager = $language_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getLabel() {
+    return t('Language');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext() {
+    $context_parts = array();
+    if ($this->languageManager->isMultilingual()) {
+      foreach ($this->languageManager->getLanguageTypes() as $type) {
+        $context_parts[] = $this->languageManager->getCurrentLanguage($type)->getId();
+      }
+    }
+    else {
+      $context_parts[] = $this->languageManager->getCurrentLanguage()->getId();
+    }
+    return implode(':', $context_parts);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/LanguagesCacheContext.php b/core/lib/Drupal/Core/Cache/LanguagesCacheContext.php
deleted file mode 100644
index 2ed1517..0000000
--- a/core/lib/Drupal/Core/Cache/LanguagesCacheContext.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\LanguagesCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-use Drupal\Core\Language\LanguageManagerInterface;
-
-/**
- * Defines the LanguagesCacheContext service, for "per language" caching.
- */
-class LanguagesCacheContext implements CalculatedCacheContextInterface  {
-
-  /**
-   * The language manager.
-   *
-   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
-   */
-  protected $languageManager;
-
-  /**
-   * Constructs a new LanguagesCacheContext service.
-   *
-   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
-   *   The language manager.
-   */
-  public function __construct(LanguageManagerInterface $language_manager) {
-    $this->languageManager = $language_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Language');
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * $type can be NULL, or one of the language types supported by the language
-   * manager, typically:
-   * - LanguageInterface::TYPE_INTERFACE
-   * - LanguageInterface::TYPE_CONTENT
-   * - LanguageInterface::TYPE_URL
-   *
-   * @see \Drupal\Core\Language\LanguageManagerInterface::getLanguageTypes()
-   *
-   * @throws \RuntimeException
-   *   In case an invalid language type is specified.
-   */
-  public function getContext($type = NULL) {
-    if ($type === NULL) {
-      $context_parts = array();
-      if ($this->languageManager->isMultilingual()) {
-        foreach ($this->languageManager->getLanguageTypes() as $type) {
-          $context_parts[] = $this->languageManager->getCurrentLanguage($type)->getId();
-        }
-      }
-      else {
-        $context_parts[] = $this->languageManager->getCurrentLanguage()->getId();
-      }
-      return implode(',', $context_parts);
-    }
-    else {
-      if (!in_array($type, $this->languageManager->getLanguageTypes())) {
-        throw new \RuntimeException(sprintf('The language type "%s" is invalid.', $type));
-      }
-      return $this->languageManager->getCurrentLanguage($type)->getId();
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index c3fc789..041330b 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -201,11 +201,4 @@ public function removeBin() {
     $this->cache = [];
   }
 
-  /**
-   * Prevents data stored in memory backends from being serialized.
-   */
-  public function __sleep() {
-    return [];
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Cache/MenuActiveTrailsCacheContext.php b/core/lib/Drupal/Core/Cache/MenuActiveTrailCacheContext.php
similarity index 68%
rename from core/lib/Drupal/Core/Cache/MenuActiveTrailsCacheContext.php
rename to core/lib/Drupal/Core/Cache/MenuActiveTrailCacheContext.php
index 3b43178..7c41bee 100644
--- a/core/lib/Drupal/Core/Cache/MenuActiveTrailsCacheContext.php
+++ b/core/lib/Drupal/Core/Cache/MenuActiveTrailCacheContext.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Cache\MenuActiveTrailsCacheContext.
+ * Contains \Drupal\Core\Cache\MenuActiveTrailCacheContext.
  */
 
 namespace Drupal\Core\Cache;
@@ -10,12 +10,12 @@
 use Symfony\Component\DependencyInjection\ContainerAware;
 
 /**
- * Defines the MenuActiveTrailsCacheContext service.
+ * Defines the MenuActiveTrailCacheContext service.
  *
  * This class is container-aware to avoid initializing the 'menu.active_trail'
  * service (and its dependencies) when it is not necessary.
  */
-class MenuActiveTrailsCacheContext extends ContainerAware implements CalculatedCacheContextInterface {
+class MenuActiveTrailCacheContext extends ContainerAware implements CalculatedCacheContextInterface {
 
   /**
    * {@inheritdoc}
@@ -27,7 +27,7 @@ public static function getLabel() {
   /**
    * {@inheritdoc}
    */
-  public function getContext($menu_name = NULL) {
+  public function getContext($menu_name) {
     $active_trail = $this->container->get('menu.active_trail')
       ->getActiveTrailIds($menu_name);
     return 'menu_trail.' . $menu_name . '|' . implode('|', $active_trail);
diff --git a/core/lib/Drupal/Core/Cache/PagerCacheContext.php b/core/lib/Drupal/Core/Cache/PagerCacheContext.php
new file mode 100644
index 0000000..a4c308c
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/PagerCacheContext.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\PagerCacheContext.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Defines a cache context for "per page in a pager" caching.
+ */
+class PagerCacheContext implements CalculatedCacheContextInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getLabel() {
+    return t('Pager');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext($pager_id) {
+    return 'pager.' . $pager_id . '.' . pager_find_page($pager_id);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/PagersCacheContext.php b/core/lib/Drupal/Core/Cache/PagersCacheContext.php
deleted file mode 100644
index cd9bb98..0000000
--- a/core/lib/Drupal/Core/Cache/PagersCacheContext.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\PagersCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines a cache context for "per page in a pager" caching.
- */
-class PagersCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Pager');
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @see pager_find_page()
-   */
-  public function getContext($pager_id = NULL) {
-    // The value of the 'page' query argument contains the information that
-    // controls *all* pagers.
-    if ($pager_id === NULL) {
-      return 'pager' . $this->requestStack->getCurrentRequest()->query->get('page', '');
-    }
-
-    return 'pager.' . $pager_id . '.' . pager_find_page($pager_id);
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/QueryArgsCacheContext.php b/core/lib/Drupal/Core/Cache/QueryArgsCacheContext.php
deleted file mode 100644
index 4c34721..0000000
--- a/core/lib/Drupal/Core/Cache/QueryArgsCacheContext.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\QueryArgsCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the QueryArgsCacheContext service, for "per query args" caching.
- *
- * A "host" is defined as the combination of URI scheme, domain name and port.
- *
- * @see Symfony\Component\HttpFoundation::getSchemeAndHttpHost()
- */
-class QueryArgsCacheContext extends RequestStackCacheContextBase implements CalculatedCacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Query arguments');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($query_arg = NULL) {
-    if ($query_arg === NULL) {
-      return $this->requestStack->getCurrentRequest()->getQueryString();
-    }
-    else {
-      return $this->requestStack->getCurrentRequest()->query->get($query_arg);
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/RequestFormatCacheContext.php b/core/lib/Drupal/Core/Cache/RequestFormatCacheContext.php
deleted file mode 100644
index 397384f..0000000
--- a/core/lib/Drupal/Core/Cache/RequestFormatCacheContext.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\RequestFormatCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the RequestFormatCacheContext service, for "per format" caching.
- */
-class RequestFormatCacheContext extends RequestStackCacheContextBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Request format');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return $this->requestStack->getCurrentRequest()->getRequestFormat();
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/RequestStackCacheContextBase.php b/core/lib/Drupal/Core/Cache/RequestStackCacheContextBase.php
deleted file mode 100644
index 34e3560..0000000
--- a/core/lib/Drupal/Core/Cache/RequestStackCacheContextBase.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\RequestStackCacheContextBase.
- */
-
-namespace Drupal\Core\Cache;
-
-use Symfony\Component\HttpFoundation\RequestStack;
-
-/**
- * Defines a base class for cache contexts depending only on the request stack.
- */
-abstract class RequestStackCacheContextBase implements CacheContextInterface {
-
-  /**
-   * The request stack.
-   *
-   * @var \Symfony\Component\HttpFoundation\RequestStack
-   */
-  protected $requestStack;
-
-  /**
-   * Constructs a new RequestStackCacheContextBase class.
-   *
-   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
-   *   The request stack.
-   */
-  public function __construct(RequestStack $request_stack) {
-    $this->requestStack = $request_stack;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/RouteCacheContext.php b/core/lib/Drupal/Core/Cache/RouteCacheContext.php
deleted file mode 100644
index 6e9e39f..0000000
--- a/core/lib/Drupal/Core/Cache/RouteCacheContext.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\RouteCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-use Drupal\Core\Routing\RouteMatchInterface;
-
-/**
- * Defines the RouteCacheContext service, for "per route" caching.
- */
-class RouteCacheContext {
-
-  /**
-   * The route match.
-   *
-   * @var \Drupal\Core\Routing\RouteMatchInterface
-   */
-  protected $routeMatch;
-
-  /**
-   * Constructs a new RouteCacheContext class.
-   *
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The route match.
-   */
-  public function __construct(RouteMatchInterface $route_match) {
-    $this->routeMatch = $route_match;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Route');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return $this->routeMatch->getRouteName() . hash('sha256', serialize($this->routeMatch->getRawParameters()->all()));
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/RouteNameCacheContext.php b/core/lib/Drupal/Core/Cache/RouteNameCacheContext.php
deleted file mode 100644
index f0bd937..0000000
--- a/core/lib/Drupal/Core/Cache/RouteNameCacheContext.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\RouteNameCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the RouteCacheContext service, for "per route name" caching.
- */
-class RouteNameCacheContext extends RouteCacheContext {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Route name');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return $this->routeMatch->getRouteName();
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/UrlCacheContext.php b/core/lib/Drupal/Core/Cache/UrlCacheContext.php
index 1381093..308d182 100644
--- a/core/lib/Drupal/Core/Cache/UrlCacheContext.php
+++ b/core/lib/Drupal/Core/Cache/UrlCacheContext.php
@@ -7,10 +7,29 @@
 
 namespace Drupal\Core\Cache;
 
+use Symfony\Component\HttpFoundation\RequestStack;
+
 /**
  * Defines the UrlCacheContext service, for "per page" caching.
  */
-class UrlCacheContext extends RequestStackCacheContextBase {
+class UrlCacheContext implements CacheContextInterface {
+
+  /**
+   * The request stack.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * Constructs a new UrlCacheContext service.
+   *
+   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
+   *   The request stack.
+   */
+  public function __construct(RequestStack $request_stack) {
+    $this->requestStack = $request_stack;
+  }
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/Cache/UserRolesCacheContext.php b/core/lib/Drupal/Core/Cache/UserRolesCacheContext.php
deleted file mode 100644
index cf7b450..0000000
--- a/core/lib/Drupal/Core/Cache/UserRolesCacheContext.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\UserRolesCacheContext.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the UserRolesCacheContext service, for "per role" caching.
- */
-class UserRolesCacheContext extends UserCacheContext implements CalculatedCacheContextInterface{
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t("User's roles");
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($role = NULL) {
-    if ($role === NULL) {
-      return 'r.' . implode(',', $this->user->getRoles());
-    }
-    else {
-      return 'r.' . $role . '.' . (in_array($role, $this->user->getRoles()) ? '0' : '1');
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Config/CachedStorage.php b/core/lib/Drupal/Core/Config/CachedStorage.php
index a21f137..5023c35 100644
--- a/core/lib/Drupal/Core/Config/CachedStorage.php
+++ b/core/lib/Drupal/Core/Config/CachedStorage.php
@@ -131,6 +131,7 @@ public function write($name, array $data) {
       // While not all written data is read back, setting the cache instead of
       // just deleting it avoids cache rebuild stampedes.
       $this->cache->set($this->getCacheKey($name), $data);
+      Cache::invalidateTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
       $this->findByPrefixCache = array();
       return TRUE;
     }
@@ -145,6 +146,7 @@ public function delete($name) {
     // rebuilding the cache before the storage is gone.
     if ($this->storage->delete($name)) {
       $this->cache->delete($this->getCacheKey($name));
+      Cache::invalidateTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
       $this->findByPrefixCache = array();
       return TRUE;
     }
@@ -160,6 +162,7 @@ public function rename($name, $new_name) {
     if ($this->storage->rename($name, $new_name)) {
       $this->cache->delete($this->getCacheKey($name));
       $this->cache->delete($this->getCacheKey($new_name));
+      Cache::invalidateTags(array($this::FIND_BY_PREFIX_CACHE_TAG));
       $this->findByPrefixCache = array();
       return TRUE;
     }
@@ -210,7 +213,20 @@ public function listAll($prefix = '') {
   protected function findByPrefix($prefix) {
     $cache_key = $this->getCacheKey($prefix);
     if (!isset($this->findByPrefixCache[$cache_key])) {
-      $this->findByPrefixCache[$cache_key] = $this->storage->listAll($prefix);
+      // The : character is not allowed in config file names, so this can not
+      // conflict.
+      if ($cache = $this->cache->get('find:' . $cache_key)) {
+        $this->findByPrefixCache[$cache_key] = $cache->data;
+      }
+      else {
+        $this->findByPrefixCache[$cache_key] = $this->storage->listAll($prefix);
+        $this->cache->set(
+          'find:' . $cache_key,
+          $this->findByPrefixCache[$cache_key],
+          Cache::PERMANENT,
+          array($this::FIND_BY_PREFIX_CACHE_TAG)
+        );
+      }
     }
     return $this->findByPrefixCache[$cache_key];
   }
diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index 3f7db46..715138f 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -786,7 +786,8 @@ protected function processExtension($type, $op, $name) {
 
     $this->setProcessedExtension($type, $op, $name);
     \Drupal::service('config.installer')
-      ->setSyncing(FALSE);
+      ->setSyncing(FALSE)
+      ->resetSourceStorage();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index ffdc760..8065613 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -9,7 +9,6 @@
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\Entity\ConfigDependencyManager;
-use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Site\Settings;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
@@ -90,66 +89,36 @@ public function __construct(ConfigFactoryInterface $config_factory, StorageInter
    * {@inheritdoc}
    */
   public function installDefaultConfig($type, $name) {
-    $extension_path = $this->drupalGetPath($type, $name);
+    $extension_path = drupal_get_path($type, $name);
     // Refresh the schema cache if the extension provides configuration schema
     // or is a theme.
     if (is_dir($extension_path . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY) || $type == 'theme') {
       $this->typedConfig->clearCachedDefinitions();
     }
 
-    $default_install_path = $this->getDefaultConfigDirectory($type, $name);
-    if (is_dir($default_install_path)) {
-      if (!$this->isSyncing()) {
-        $storage = new FileStorage($default_install_path, StorageInterface::DEFAULT_COLLECTION);
-        $prefix = '';
-      }
-      else {
-        // The configuration importer sets the source storage on the config
-        // installer. The configuration importer handles all of the
-        // configuration entity imports. We only need to ensure that simple
-        // configuration is created when the extension is installed.
-        $storage = $this->getSourceStorage();
-        $prefix = $name . '.';
-      }
+    // Gather information about all the supported collections.
+    $collection_info = $this->configManager->getConfigCollectionInfo();
 
-      // Gets a profile storage to search for overrides if necessary.
-      $profile_storage = $this->getProfileStorage($name);
-
-      // Gather information about all the supported collections.
-      $collection_info = $this->configManager->getConfigCollectionInfo();
-      foreach ($collection_info->getCollectionNames() as $collection) {
-        $config_to_create = $this->getConfigToCreate($storage, $collection, $prefix, $profile_storage);
-        // If we're installing a profile ensure configuration that is overriding
-        // is excluded.
-        if ($name == $this->drupalGetProfile()) {
-          $existing_configuration = $this->getActiveStorages($collection)->listAll();
-          $config_to_create = array_diff_key($config_to_create, array_flip($existing_configuration));
-        }
-        if (!empty($config_to_create)) {
-          $this->createConfiguration($collection, $config_to_create);
-        }
+    // Read enabled extensions directly from configuration to avoid circular
+    // dependencies with ModuleHandler and ThemeHandler.
+    $extension_config = $this->configFactory->get('core.extension');
+    $modules = (array) $extension_config->get('module');
+    // Unless we are installing the profile, remove it from the list.
+    if ($install_profile = Settings::get('install_profile')) {
+      if ($name !== $install_profile) {
+        unset($modules[$install_profile]);
       }
     }
+    $enabled_extensions = array_keys($modules);
+    $enabled_extensions += array_keys((array) $extension_config->get('theme'));
 
-    // During a drupal installation optional configuration is installed at the
-    // end of the installation process.
-    // @see install_install_profile()
-    if (!$this->isSyncing() && !$this->drupalInstallationAttempted()) {
-      $optional_install_path = $extension_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
-      if (is_dir($optional_install_path)) {
-        // Install any optional config the module provides.
-        $storage = new FileStorage($optional_install_path, StorageInterface::DEFAULT_COLLECTION);
-        $this->installOptionalConfig($storage, '');
-      }
-      // Install any optional configuration entities whose type this extension
-      // provides. This searches all the installed modules config/optional
-      // directories.
-      $provides_config_entity_type = array_reduce($this->configManager->getEntityManager()->getDefinitions(), function ($return, EntityTypeInterface $entity_type) use ($name) {
-        return $return ?: $entity_type->getProvider() && $entity_type->getConfigPrefix();
-      }, FALSE);
-      if ($provides_config_entity_type) {
-        $storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, FALSE);
-        $this->installOptionalConfig($storage, $name . '.');
+    // Core can provide configuration.
+    $enabled_extensions[] = 'core';
+
+    foreach ($collection_info->getCollectionNames(TRUE) as $collection) {
+      $config_to_install = $this->listDefaultConfigToInstall($type, $name, $collection, $enabled_extensions);
+      if (!empty($config_to_install)) {
+        $this->createConfiguration($collection, $config_to_install);
       }
     }
 
@@ -158,76 +127,49 @@ public function installDefaultConfig($type, $name) {
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function installOptionalConfig(StorageInterface $storage = NULL, $prefix = '') {
-    if (!$storage) {
-      // Search the install profile's optional configuration too.
-      $storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, TRUE);
-      // The extension install storage ensures that overrides are used.
-      $profile_storage = NULL;
-    }
-    else {
-      // Creates a profile storage to search for overrides.
-      $profile_install_path = $this->drupalGetPath('module', $this->drupalGetProfile()) . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
-      $profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION);
-    }
-
-    $collection_info = $this->configManager->getConfigCollectionInfo();
-    $enabled_extensions = $this->getEnabledExtensions();
-
-    foreach ($collection_info->getCollectionNames() as $collection) {
-      if (!$this->configManager->supportsConfigurationEntities($collection)) {
-        continue;
-      }
-      $existing_config = $this->getActiveStorages($collection)->listAll($prefix);
-      $config_to_create = $this->getConfigToCreate($storage, $collection, $prefix, $profile_storage);
-      $all_config = array_merge($existing_config, array_keys($config_to_create));
-      foreach ($config_to_create as $config_name => $data) {
-        // Exclude configuration that:
-        // - already exists
-        // - is a not configuration entity
-        // - or its dependencies cannot be met.
-        if (in_array($config_name, $existing_config) ||
-          !$this->configManager->getEntityTypeIdByName($config_name) ||
-          !$this->validateDependencies($config_name, $data, $enabled_extensions, $all_config)) {
-          unset($config_to_create[$config_name]);
-        }
-      }
-      if (!empty($config_to_create)) {
-        $this->createConfiguration($collection, $config_to_create, TRUE);
-      }
-    }
-  }
-
-  /**
-   * Gets configuration data from the provided storage to create.
+   * Lists default configuration for an extension that is available to install.
    *
-   * @param StorageInterface $storage
-   *   The configuration storage to read configuration from.
+   * This looks in the extension's config/install directory and all of the
+   * currently enabled extensions config/install directories for configuration
+   * that begins with the extension's name.
+   *
+   * @param string $type
+   *   The extension type; e.g., 'module' or 'theme'.
+   * @param string $name
+   *   The name of the module or theme to install default configuration for.
    * @param string $collection
-   *  The configuration collection to use.
-   * @param string $prefix
-   *   (optional) Limit to configuration starting with the provided string.
+   *  The configuration collection to install.
+   * @param array $enabled_extensions
+   *   A list of all the currently enabled modules and themes.
    *
    * @return array
-   *   An array of configuration data read from the source storage keyed by the
-   *   configuration object name.
+   *   The list of configuration objects to create.
    */
-  protected function getConfigToCreate(StorageInterface $storage, $collection, $prefix = '', StorageInterface $profile_storage = NULL) {
-    if ($storage->getCollectionName() != $collection) {
-      $storage = $storage->createCollection($collection);
-    }
-    $data = $storage->readMultiple($storage->listAll($prefix));
+  protected function listDefaultConfigToInstall($type, $name, $collection, array $enabled_extensions) {
+    // Get all default configuration owned by this extension.
+    $source_storage = $this->getSourceStorage($collection);
+    $config_to_install = $source_storage->listAll($name . '.');
+
+    // If not installing the core base system default configuration, work out if
+    // this extension provides default configuration for any other enabled
+    // extensions.
+    $extension_path = drupal_get_path($type, $name);
+    if ($type !== 'core' && is_dir($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY)) {
+      $default_storage = new FileStorage($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection);
+      $extension_provided_config = array_filter($default_storage->listAll(), function ($config_name) use ($config_to_install, $enabled_extensions) {
+        // Ensure that we have not already discovered the config to install.
+        if (in_array($config_name, $config_to_install)) {
+          return FALSE;
+        }
+        // Ensure the configuration is provided by an enabled module.
+        $provider = Unicode::substr($config_name, 0, strpos($config_name, '.'));
+        return in_array($provider, $enabled_extensions);
+      });
 
-    // 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);
-      }
-      $data = $profile_storage->readMultiple(array_keys($data)) + $data;
+      $config_to_install = array_merge($config_to_install, $extension_provided_config);
     }
-    return $data;
+
+    return $config_to_install;
   }
 
   /**
@@ -235,23 +177,24 @@ protected function getConfigToCreate(StorageInterface $storage, $collection, $pr
    *
    * @param string $collection
    *   The configuration collection.
-   * @param array $config_to_create
-   *   An array of configuration data to create, keyed by name.
+   * @param array $config_to_install
+   *   A list of configuration object names to create.
    */
-  protected function createConfiguration($collection, array $config_to_create) {
+  protected function createConfiguration($collection, array $config_to_install) {
     // Order the configuration to install in the order of dependencies.
+    $data = $this->getSourceStorage($collection)->readMultiple($config_to_install);
     $config_entity_support = $this->configManager->supportsConfigurationEntities($collection);
     if ($config_entity_support) {
       $dependency_manager = new ConfigDependencyManager();
-      $config_names = $dependency_manager
-        ->setData($config_to_create)
+      $config_to_install = $dependency_manager
+        ->setData($data)
         ->sortAll();
     }
-    else {
-      $config_names = array_keys($config_to_create);
-    }
 
-    foreach ($config_names as $name) {
+    // Remove configuration that already exists in the active storage.
+    $config_to_install = array_diff($config_to_install, $this->getActiveStorages($collection)->listAll());
+
+    foreach ($config_to_install as $name) {
       // Allow config factory overriders to use a custom configuration object if
       // they are responsible for the collection.
       $overrider = $this->configManager->getConfigCollectionInfo()->getOverrideService($collection);
@@ -261,17 +204,18 @@ protected function createConfiguration($collection, array $config_to_create) {
       else {
         $new_config = new Config($name, $this->getActiveStorages($collection), $this->eventDispatcher, $this->typedConfig);
       }
-      if ($config_to_create[$name] !== FALSE) {
-        $new_config->setData($config_to_create[$name]);
+      if ($data[$name] !== FALSE) {
+        $new_config->setData($data[$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
         // default configuration entities to exist will be unstable after the
         // module has been enabled and before the config entity has been
         // imported.
-        if ($this->isSyncing()) {
+        if ($this->isSyncing) {
           continue;
         }
         /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $entity_storage */
@@ -302,15 +246,16 @@ protected function createConfiguration($collection, array $config_to_create) {
    * {@inheritdoc}
    */
   public function installCollectionDefaultConfig($collection) {
-    $storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection, $this->drupalInstallationAttempted());
-    // Only install configuration for enabled extensions.
-    $enabled_extensions = $this->getEnabledExtensions();
-    $config_to_install = array_filter($storage->listAll(), function ($config_name) use ($enabled_extensions) {
+    $config_to_install = $this->getSourceStorage($collection)->listAll();
+    $extension_config = $this->configFactory->get('core.extension');
+    $enabled_extensions = array_keys((array) $extension_config->get('module'));
+    $enabled_extensions += array_keys((array) $extension_config->get('theme'));
+    $config_to_install = array_filter($config_to_install, function ($config_name) use ($enabled_extensions) {
       $provider = Unicode::substr($config_name, 0, strpos($config_name, '.'));
       return in_array($provider, $enabled_extensions);
     });
     if (!empty($config_to_install)) {
-      $this->createConfiguration($collection, $storage->readMultiple($config_to_install));
+      $this->createConfiguration($collection, $config_to_install);
       // Reset all the static caches and list caches.
       $this->configFactory->reset();
     }
@@ -325,13 +270,33 @@ public function setSourceStorage(StorageInterface $storage) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function resetSourceStorage() {
+    $this->sourceStorage = null;
+    return $this;
+  }
+
+  /**
    * Gets the configuration storage that provides the default configuration.
    *
-   * @return \Drupal\Core\Config\StorageInterface|null
+   * @param string $collection
+   *   (optional) The configuration collection. Defaults to the default
+   *   collection.
+   *
+   * @return \Drupal\Core\Config\StorageInterface
    *   The configuration storage that provides the default configuration.
-   *   Returns null if the source storage has not been set.
    */
-  public function getSourceStorage() {
+  public function getSourceStorage($collection = StorageInterface::DEFAULT_COLLECTION) {
+    if (!isset($this->sourceStorage)) {
+      // Default to using the ExtensionInstallStorage which searches extension's
+      // config directories for default configuration. Only include the profile
+      // configuration during Drupal installation.
+      $this->sourceStorage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection, drupal_installation_attempted());
+    }
+    if ($this->sourceStorage->getCollectionName() != $collection) {
+      $this->sourceStorage = $this->sourceStorage->createCollection($collection);
+    }
     return $this->sourceStorage;
   }
 
@@ -356,9 +321,6 @@ protected function getActiveStorages($collection = StorageInterface::DEFAULT_COL
    * {@inheritdoc}
    */
   public function setSyncing($status) {
-    if (!$status) {
-      $this->sourceStorage = NULL;
-    }
     $this->isSyncing = $status;
     return $this;
   }
@@ -371,30 +333,24 @@ public function isSyncing() {
   }
 
   /**
-   * Finds pre-existing configuration objects for the provided extension.
-   *
-   * Extensions can not be installed if configuration objects exist in the
-   * active storage with the same names. This can happen in a number of ways,
-   * commonly:
-   * - if a user has created configuration with the same name as that provided
-   *   by the extension.
-   * - if the extension provides default configuration that does not depend on
-   *   it and the extension has been uninstalled and is about to the
-   *   reinstalled.
-   *
-   * @return array
-   *   Array of configuration object names that already exist keyed by
-   *   collection.
+   * {@inheritdoc}
    */
-  protected function findPreExistingConfiguration(StorageInterface $storage) {
+  public function findPreExistingConfiguration($type, $name) {
     $existing_configuration = array();
     // Gather information about all the supported collections.
     $collection_info = $this->configManager->getConfigCollectionInfo();
 
-    foreach ($collection_info->getCollectionNames() as $collection) {
-      $config_to_create = array_keys($this->getConfigToCreate($storage, $collection));
+    // Read enabled extensions directly from configuration to avoid circular
+    // dependencies on ModuleHandler and ThemeHandler.
+    $extension_config = $this->configFactory->get('core.extension');
+    $enabled_extensions = array_keys((array) $extension_config->get('module'));
+    $enabled_extensions += array_keys((array) $extension_config->get('theme'));
+    // Add the extension that will be enabled to the list of enabled extensions.
+    $enabled_extensions[] = $name;
+    foreach ($collection_info->getCollectionNames(TRUE) as $collection) {
+      $config_to_install = $this->listDefaultConfigToInstall($type, $name, $collection, $enabled_extensions);
       $active_storage = $this->getActiveStorages($collection);
-      foreach ($config_to_create as $config_name) {
+      foreach ($config_to_install as $config_name) {
         if ($active_storage->exists($config_name)) {
           $existing_configuration[$collection][] = $config_name;
         }
@@ -402,225 +358,4 @@ protected function findPreExistingConfiguration(StorageInterface $storage) {
     }
     return $existing_configuration;
   }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function checkConfigurationToInstall($type, $name) {
-    if ($this->isSyncing()) {
-      // Configuration is assumed to already be checked by the config importer
-      // validation events.
-      return;
-    }
-    $config_install_path = $this->getDefaultConfigDirectory($type, $name);
-    if (!is_dir($config_install_path)) {
-      return;
-    }
-
-    $storage = new FileStorage($config_install_path, StorageInterface::DEFAULT_COLLECTION);
-
-    $enabled_extensions = $this->getEnabledExtensions();
-    // Add the extension that will be enabled to the list of enabled extensions.
-    $enabled_extensions[] = $name;
-    // Gets a profile storage to search for overrides if necessary.
-    $profile_storage = $this->getProfileStorage($name);
-
-    // Check the dependencies of configuration provided by the module.
-    $invalid_default_config = $this->findDefaultConfigWithUnmetDependencies($storage, $enabled_extensions, $profile_storage);
-    if (!empty($invalid_default_config)) {
-      throw UnmetDependenciesException::create($name, $invalid_default_config);
-    }
-
-    // Install profiles can not have config clashes. Configuration that
-    // has the same name as a module's configuration will be used instead.
-    if ($name != $this->drupalGetProfile()) {
-      // Throw an exception if the module being installed contains configuration
-      // that already exists. Additionally, can not continue installing more
-      // modules because those may depend on the current module being installed.
-      $existing_configuration = $this->findPreExistingConfiguration($storage);
-      if (!empty($existing_configuration)) {
-        throw PreExistingConfigException::create($name, $existing_configuration);
-      }
-    }
-  }
-
-  /**
-   * Finds default configuration with unmet dependencies.
-   *
-   * @param array $enabled_extensions
-   *   A list of all the currently enabled modules and themes.
-   *
-   * @return array
-   *   List of configuration that has unmet dependencies
-   */
-  protected function findDefaultConfigWithUnmetDependencies(StorageInterface $storage, array $enabled_extensions, StorageInterface $profile_storage = NULL) {
-    $config_to_create = $this->getConfigToCreate($storage, StorageInterface::DEFAULT_COLLECTION, '', $profile_storage);
-    $all_config = array_merge($this->configFactory->listAll(), array_keys($config_to_create));
-    return array_filter(array_keys($config_to_create), function($config_name) use ($enabled_extensions, $all_config, $config_to_create) {
-      return !$this->validateDependencies($config_name, $config_to_create[$config_name], $enabled_extensions, $all_config);
-    });
-  }
-
-  /**
-   * Validates an array of config data that contains dependency information.
-   *
-   * @param string $config_name
-   *   The name of the configuration object that is being validated.
-   * @param array $data
-   *   Configuration data.
-   * @param array $enabled_extensions
-   *   A list of all the currently enabled modules and themes.
-   * @param array $all_config
-   *   A list of all the active configuration names.
-   *
-   * @return bool
-   *   TRUE if the dependencies are met, FALSE if not.
-   */
-  protected function validateDependencies($config_name, array $data, array $enabled_extensions, array $all_config) {
-    // All the migrate tests will fail if we check since they install the
-    // migrate_drupal module but only set up the dependencies for the single
-    // migration they are testing.
-    if (strpos($config_name, 'migrate.migration.') === 0) {
-      return TRUE;
-    }
-    if (isset($data['dependencies'])) {
-      $all_dependencies = $data['dependencies'];
-
-      // Ensure enforced dependencies are included.
-      if (isset($all_dependencies['enforced'])) {
-        $all_dependencies = array_merge($all_dependencies, $data['dependencies']['enforced']);
-        unset($all_dependencies['enforced']);
-      }
-      // Ensure the configuration entity type provider is in the list of
-      // dependencies.
-      list($provider) = explode('.', $config_name, 2);
-      if (!isset($all_dependencies['module'])) {
-        $all_dependencies['module'][] = $provider;
-      }
-      elseif (!in_array($provider, $all_dependencies['module'])) {
-        $all_dependencies['module'][] = $provider;
-      }
-
-      foreach ($all_dependencies as $type => $dependencies) {
-        $list_to_check = [];
-        switch ($type) {
-          case 'module':
-          case 'theme':
-            $list_to_check = $enabled_extensions;
-            break;
-          case 'config':
-            $list_to_check = $all_config;
-            break;
-        }
-        if (!empty($list_to_check)) {
-          $missing = array_diff($dependencies, $list_to_check);
-          if (!empty($missing)) {
-            return FALSE;
-          }
-        }
-      }
-    }
-    return TRUE;
-  }
-
-  /**
-   * Gets the list of enabled extensions including both modules and themes.
-   *
-   * @return array
-   *   A list of enabled extensions which includes both modules and themes.
-   */
-  protected function getEnabledExtensions() {
-    // Read enabled extensions directly from configuration to avoid circular
-    // dependencies on ModuleHandler and ThemeHandler.
-    $extension_config = $this->configFactory->get('core.extension');
-    $enabled_extensions = (array) $extension_config->get('module');
-    $enabled_extensions += (array) $extension_config->get('theme');
-    // Core can provide configuration.
-    $enabled_extensions['core'] = 'core';
-    return array_keys($enabled_extensions);
-  }
-
-  /**
-   * Gets the profile storage to use to check for profile overrides.
-   *
-   * @param string $installing_name
-   *   (optional) The name of the extension currently being installed.
-   *
-   * @return \Drupal\Core\Config\StorageInterface|null
-   *   A storage to access configuration from the installation profile. If a
-   *   Drupal installation is not in progress or we're installing the profile
-   *   itself, then it will return NULL as the profile storage should not be
-   *   used.
-   */
-  protected function getProfileStorage($installing_name = '') {
-    $profile = $this->drupalGetProfile();
-    if ($this->drupalInstallationAttempted() && $profile != $installing_name) {
-      // Profiles should not contain optional configuration so always use the
-      // install directory.
-      $profile_install_path = $this->getDefaultConfigDirectory('module', $profile);
-      $profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION);
-    }
-    else {
-      $profile_storage = NULL;
-    }
-    return $profile_storage;
-  }
-
-  /**
-   * Gets an extension's default configuration directory.
-   *
-   * @param string $type
-   *   Type of extension to install.
-   * @param string $name
-   *   Name of extension to install.
-   *
-   * @return string
-   *   The extension's default configuration directory.
-   */
-  protected function getDefaultConfigDirectory($type, $name) {
-    return $this->drupalGetPath($type, $name) . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
-  }
-
-  /**
-   * Wrapper for drupal_get_path().
-   *
-   * @param $type
-   *   The type of the item; one of 'core', 'profile', 'module', 'theme', or
-   *   'theme_engine'.
-   * @param $name
-   *   The name of the item for which the path is requested. Ignored for
-   *   $type 'core'.
-   *
-   * @return string
-   *   The path to the requested item or an empty string if the item is not
-   *   found.
-   */
-  protected function drupalGetPath($type, $name) {
-    return drupal_get_path($type, $name);
-  }
-
-  /**
-   * Gets the install profile from settings.
-   *
-   * @return string|null $profile
-   *   The name of the installation profile or NULL if no installation profile
-   *   is currently active. This is the case for example during the first steps
-   *   of the installer or during unit tests.
-   */
-  protected function drupalGetProfile() {
-    // Settings is safe to use because settings.php is written before any module
-    // is installed.
-    return Settings::get('install_profile');
-  }
-
-  /**
-   * Wrapper for drupal_installation_attempted().
-   *
-   * @return bool
-   *   TRUE if a Drupal installation is currently being attempted.
-   */
-  protected function drupalInstallationAttempted() {
-    return drupal_installation_attempted();
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
index 6d8e489..1d1e7e0 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
@@ -38,24 +38,6 @@
   public function installDefaultConfig($type, $name);
 
   /**
-   * Installs optional configuration.
-   *
-   * Optional configuration is only installed if:
-   * - the configuration does not exist already.
-   * - it's a configuration entity.
-   * - its dependencies can be met.
-   *
-   * @param \Drupal\Core\Config\StorageInterface
-   *   (optional) The configuration storage to search for optional
-   *   configuration. If not provided, all enabled extension's optional
-   *   configuration directories will be searched.
-   * @param string $prefix
-   *   (optional) If set, limits the installed configuration to only
-   *   configuration beginning with the provided value.
-   */
-  public function installOptionalConfig(StorageInterface $storage = NULL, $prefix = '');
-
-  /**
    * Installs all default configuration in the specified collection.
    *
    * The function is useful if the site needs to respond to an event that has
@@ -78,6 +60,13 @@ public function installCollectionDefaultConfig($collection);
   public function setSourceStorage(StorageInterface $storage);
 
   /**
+   * Resets the configuration storage that provides the default configuration.
+   *
+   * @return $this
+   */
+  public function resetSourceStorage();
+
+  /**
    * Sets the status of the isSyncing flag.
    *
    * @param bool $status
@@ -96,16 +85,25 @@ public function setSyncing($status);
   public function isSyncing();
 
   /**
-   * Checks the configuration that will be installed for an extension.
+   * Finds pre-existing configuration objects for the provided extension.
+   *
+   * Extensions can not be installed if configuration objects exist in the
+   * active storage with the same names. This can happen in a number of ways,
+   * commonly:
+   * - if a user has created configuration with the same name as that provided
+   *   by the extension.
+   * - if the extension provides default configuration that does not depend on
+   *   it and the extension has been uninstalled and is about to the
+   *   reinstalled.
    *
    * @param string $type
    *   Type of extension to install.
    * @param string $name
    *   Name of extension to install.
    *
-   * @throws \Drupal\Core\Config\UnmetDependenciesException
-   * @throws \Drupal\Core\Config\PreExistingConfigException
+   * @return array
+   *   Array of configuration objects that already exist keyed by collection.
    */
-  public function checkConfigurationToInstall($type, $name);
+  public function findPreExistingConfiguration($type, $name);
 
 }
diff --git a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
index 15490b4..cb2833e 100644
--- a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
+++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
@@ -45,7 +45,7 @@ class ExtensionInstallStorage extends InstallStorage {
    *   default collection.
    * @param bool $include_profile
    *   (optional) Whether to include the install profile in extensions to
-   *   search and to get overrides from.
+   *   search.
    */
   public function __construct(StorageInterface $config_storage, $directory = self::CONFIG_INSTALL_DIRECTORY, $collection = StorageInterface::DEFAULT_COLLECTION, $include_profile = TRUE) {
     $this->configStorage = $config_storage;
@@ -82,24 +82,27 @@ protected function getAllFolders() {
       $this->folders = array();
       $this->folders += $this->getComponentNames('core', array('core'));
 
-      $install_profile = Settings::get('install_profile');
       $extensions = $this->configStorage->read('core.extension');
       if (!empty($extensions['module'])) {
         $modules = $extensions['module'];
-        // Remove the install profile as this is handled later.
-        unset($modules[$install_profile]);
+        if (!$this->includeProfile) {
+          if ($install_profile = Settings::get('install_profile')) {
+            unset($modules[$install_profile]);
+          }
+        }
         $this->folders += $this->getComponentNames('module', array_keys($modules));
       }
       if (!empty($extensions['theme'])) {
         $this->folders += $this->getComponentNames('theme', array_keys($extensions['theme']));
       }
 
-      if ($this->includeProfile) {
-        // The install profile can override module default configuration. We do
-        // this by replacing the config file path from the module/theme with the
-        // install profile version if there are any duplicates.
-        $profile_folders = $this->getComponentNames('profile', array(drupal_get_profile()));
-        $this->folders = $profile_folders + $this->folders;
+      // The install profile can override module default configuration. We do
+      // this by replacing the config file path from the module/theme with the
+      // install profile version if there are any duplicates.
+      $profile_folders = $this->getComponentNames('profile', array(drupal_get_profile()));
+      $folders_to_replace = array_intersect_key($profile_folders, $this->folders);
+      if (!empty($folders_to_replace)) {
+        $this->folders = array_merge($this->folders, $folders_to_replace);
       }
     }
     return $this->folders;
diff --git a/core/lib/Drupal/Core/Config/InstallStorage.php b/core/lib/Drupal/Core/Config/InstallStorage.php
index 06618d7..d4e7d5c 100644
--- a/core/lib/Drupal/Core/Config/InstallStorage.php
+++ b/core/lib/Drupal/Core/Config/InstallStorage.php
@@ -28,11 +28,6 @@ class InstallStorage extends FileStorage {
   const CONFIG_INSTALL_DIRECTORY = 'config/install';
 
   /**
-   * Extension sub-directory containing optional configuration for installation.
-   */
-  const CONFIG_OPTIONAL_DIRECTORY = 'config/optional';
-
-  /**
    * Extension sub-directory containing configuration schema.
    */
   const CONFIG_SCHEMA_DIRECTORY = 'config/schema';
diff --git a/core/lib/Drupal/Core/Config/StorageCacheInterface.php b/core/lib/Drupal/Core/Config/StorageCacheInterface.php
index 62db502..674547f 100644
--- a/core/lib/Drupal/Core/Config/StorageCacheInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageCacheInterface.php
@@ -13,6 +13,14 @@
 interface StorageCacheInterface {
 
   /**
+   * Cache tag.
+   *
+   * Used by Drupal\Core\Config\CachedStorage::findByPrefix so that cached items
+   * can be cleared during writes, deletes and renames.
+   */
+  const FIND_BY_PREFIX_CACHE_TAG = 'configFindByPrefix';
+
+  /**
    * Reset the static cache of the listAll() cache.
    */
   public function resetListCache();
diff --git a/core/lib/Drupal/Core/Config/UnmetDependenciesException.php b/core/lib/Drupal/Core/Config/UnmetDependenciesException.php
deleted file mode 100644
index 6a10003..0000000
--- a/core/lib/Drupal/Core/Config/UnmetDependenciesException.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Config\UnmetDependenciesException.
- */
-
-namespace Drupal\Core\Config;
-
-use Drupal\Component\Utility\String;
-use Drupal\Core\StringTranslation\TranslationInterface;
-
-/**
- * An exception thrown if configuration has unmet dependencies.
- */
-class UnmetDependenciesException extends ConfigException {
-
-  /**
-   * A list of configuration objects that have unmet dependencies.
-   *
-   * @var array
-   */
-  protected $configObjects = [];
-
-  /**
-   * The name of the extension that is being installed.
-   *
-   * @var string
-   */
-  protected $extension;
-
-  /**
-   * Gets the list of configuration objects that have unmet dependencies.
-   *
-   * @return array
-   *   A list of configuration objects that have unmet dependencies.
-   */
-  public function getConfigObjects() {
-    return $this->configObjects;
-  }
-
-  /**
-   * Gets the name of the extension that is being installed.
-   *
-   * @return string
-   *   The name of the extension that is being installed.
-   */
-  public function getExtension() {
-    return $this->extension;
-  }
-
-  /**
-   * Gets a translated message from the exception.
-   *
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   *
-   * @return string
-   */
-  public function getTranslatedMessage(TranslationInterface $string_translation, $extension) {
-    return $string_translation->formatPlural(
-      count($this->getConfigObjects()),
-      'Unable to install @extension, %config_names has unmet dependencies.',
-      'Unable to install @extension, %config_names have unmet dependencies.',
-      [
-        '%config_names' => implode(', ', $this->getConfigObjects()),
-        '@extension' => $extension,
-      ]
-    );
-  }
-
-  /**
-   * Creates an exception for an extension and a list of configuration objects.
-   *
-   * @param $extension
-   *   The name of the extension that is being installed.
-   * @param array $config_objects
-   *   A list of configuration object names that have unmet dependencies
-   *
-   * @return \Drupal\Core\Config\PreExistingConfigException
-   */
-  public static function create($extension, array $config_objects) {
-    $message = String::format('Configuration objects (@config_names) provided by @extension have unmet dependencies',
-      array(
-        '@config_names' => implode(', ', $config_objects),
-        '@extension' => $extension
-      )
-    );
-    $e = new static($message);
-    $e->configObjects = $config_objects;
-    $e->extension = $extension;
-    return $e;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
index 4c3f838..eaff2e1 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
@@ -68,6 +68,9 @@ class Connection extends DatabaseConnection {
   public function __construct(\PDO $connection, array $connection_options) {
     parent::__construct($connection, $connection_options);
 
+    // We don't need a specific PDOStatement class here, we simulate it below.
+    $this->statementClass = NULL;
+
     // This driver defaults to transaction support, except if explicitly passed FALSE.
     $this->transactionSupport = $this->transactionalDDLSupport = !isset($connection_options['transactions']) || $connection_options['transactions'] !== FALSE;
 
@@ -267,71 +270,14 @@ public static function sqlFunctionRegexp($pattern, $subject) {
   }
 
   /**
-   * {@inheritdoc}
+   * SQLite-specific implementation of DatabaseConnection::prepare().
+   *
+   * We don't use prepared statements at all at this stage. We just create
+   * a Statement object, that will create a PDOStatement
+   * using the semi-private PDOPrepare() method below.
    */
-  protected function expandArguments(&$query, &$args) {
-    $modified = parent::expandArguments($query, $args);
-
-    // The PDO SQLite driver always replaces placeholders with strings, which
-    // breaks numeric expressions (e.g., COUNT(*) >= :count). Replace numeric
-    // placeholders in the query to work around this bug.
-    // @see http://bugs.php.net/bug.php?id=45259
-    if (empty($args)) {
-      return $modified;
-    }
-    // Check if $args is a simple numeric array.
-    if (range(0, count($args) - 1) === array_keys($args)) {
-      // In that case, we have unnamed placeholders.
-      $count = 0;
-      $new_args = array();
-      foreach ($args as $value) {
-        if (is_float($value) || is_int($value) || is_numeric($value)) {
-          if (is_float($value)) {
-            // Force the conversion to float so as not to loose precision
-            // in the automatic cast.
-            $value = sprintf('%F', $value);
-          }
-          $query = substr_replace($query, $value, strpos($query, '?'), 1);
-        }
-        else {
-          $placeholder = ':db_statement_placeholder_' . $count++;
-          $query = substr_replace($query, $placeholder, strpos($query, '?'), 1);
-          $new_args[$placeholder] = $value;
-        }
-      }
-      $args = $new_args;
-      $modified = TRUE;
-    }
-    // Otherwise this is using named placeholders.
-    else {
-      foreach ($args as $placeholder => $value) {
-        if (is_float($value) || is_int($value) || is_numeric($value)) {
-          if (is_float($value)) {
-            // Force the conversion to float so as not to loose precision
-            // in the automatic cast.
-            $value = sprintf('%F', $value);
-          }
-
-          // We will remove this placeholder from the query as PDO throws an
-          // exception if the number of placeholders in the query and the
-          // arguments does not match.
-          unset($args[$placeholder]);
-          // PDO allows placeholders to not be prefixed by a colon. See
-          // http://marc.info/?l=php-internals&m=111234321827149&w=2 for
-          // more.
-          if ($placeholder[0] != ':') {
-            $placeholder = ":$placeholder";
-          }
-          // When replacing the placeholders, make sure we search for the
-          // exact placeholder. For example, if searching for
-          // ':db_placeholder_1', do not replace ':db_placeholder_11'.
-          $query = preg_replace('/' . preg_quote($placeholder, '/') . '\b/', $value, $query);
-
-          $modified = TRUE;
-        }
-      }
-    }
-    return $modified;
+  public function prepare($statement, array $driver_options = array()) {
+    return new Statement($this->connection, $this, $statement, $driver_options);
   }
 
   public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php
new file mode 100644
index 0000000..0be036d
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php
@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Statement
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\StatementPrefetch;
+use Drupal\Core\Database\StatementInterface;
+
+/**
+ * Specific SQLite implementation of DatabaseConnection.
+ *
+ * The PDO SQLite driver only closes SELECT statements when the PDOStatement
+ * destructor is called and SQLite does not allow data change (INSERT,
+ * UPDATE etc) on a table which has open SELECT statements. This is a
+ * user-space mock of PDOStatement that buffers all the data and doesn't
+ * have those limitations.
+ */
+class Statement extends StatementPrefetch implements \Iterator, StatementInterface {
+
+  /**
+   * SQLite specific implementation of getStatement().
+   *
+   * The PDO SQLite layer doesn't replace numeric placeholders in queries
+   * correctly, and this makes numeric expressions (such as COUNT(*) >= :count)
+   * fail. We replace numeric placeholders in the query ourselves to work
+   * around this bug.
+   *
+   * See http://bugs.php.net/bug.php?id=45259 for more details.
+   */
+  protected function getStatement($query, &$args = array()) {
+    if (count($args)) {
+      // Check if $args is a simple numeric array.
+      if (range(0, count($args) - 1) === array_keys($args)) {
+        // In that case, we have unnamed placeholders.
+        $count = 0;
+        $new_args = array();
+        foreach ($args as $value) {
+          if (is_float($value) || is_int($value)) {
+            if (is_float($value)) {
+              // Force the conversion to float so as not to loose precision
+              // in the automatic cast.
+              $value = sprintf('%F', $value);
+            }
+            $query = substr_replace($query, $value, strpos($query, '?'), 1);
+          }
+          else {
+            $placeholder = ':db_statement_placeholder_' . $count++;
+            $query = substr_replace($query, $placeholder, strpos($query, '?'), 1);
+            $new_args[$placeholder] = $value;
+          }
+        }
+        $args = $new_args;
+      }
+      else {
+        // Else, this is using named placeholders.
+        foreach ($args as $placeholder => $value) {
+          if (is_float($value) || is_int($value)) {
+            if (is_float($value)) {
+              // Force the conversion to float so as not to loose precision
+              // in the automatic cast.
+              $value = sprintf('%F', $value);
+            }
+
+            // We will remove this placeholder from the query as PDO throws an
+            // exception if the number of placeholders in the query and the
+            // arguments does not match.
+            unset($args[$placeholder]);
+            // PDO allows placeholders to not be prefixed by a colon. See
+            // http://marc.info/?l=php-internals&m=111234321827149&w=2 for
+            // more.
+            if ($placeholder[0] != ':') {
+              $placeholder = ":$placeholder";
+            }
+            // When replacing the placeholders, make sure we search for the
+            // exact placeholder. For example, if searching for
+            // ':db_placeholder_1', do not replace ':db_placeholder_11'.
+            $query = preg_replace('/' . preg_quote($placeholder) . '\b/', $value, $query);
+          }
+        }
+      }
+    }
+
+    return $this->dbh->prepare($query);
+  }
+
+  public function execute($args = array(), $options = array()) {
+    try {
+      $return = parent::execute($args, $options);
+    }
+    catch (\PDOException $e) {
+      if (!empty($e->errorInfo[1]) && $e->errorInfo[1] === 17) {
+        // The schema has changed. SQLite specifies that we must resend the query.
+        $return = parent::execute($args, $options);
+      }
+      else {
+        // Rethrow the exception.
+        throw $e;
+      }
+    }
+
+    // In some weird cases, SQLite will prefix some column names by the name
+    // of the table. We post-process the data, by renaming the column names
+    // using the same convention as MySQL and PostgreSQL.
+    $rename_columns = array();
+    foreach ($this->columnNames as $k => $column) {
+      // In some SQLite versions, SELECT DISTINCT(field) will return "(field)"
+      // instead of "field".
+      if (preg_match("/^\((.*)\)$/", $column, $matches)) {
+        $rename_columns[$column] = $matches[1];
+        $this->columnNames[$k] = $matches[1];
+        $column = $matches[1];
+      }
+
+      // Remove "table." prefixes.
+      if (preg_match("/^.*\.(.*)$/", $column, $matches)) {
+        $rename_columns[$column] = $matches[1];
+        $this->columnNames[$k] = $matches[1];
+      }
+    }
+    if ($rename_columns) {
+      // DatabaseStatementPrefetch already extracted the first row,
+      // put it back into the result set.
+      if (isset($this->currentRow)) {
+        $this->data[0] = &$this->currentRow;
+      }
+
+      // Then rename all the columns across the result set.
+      foreach ($this->data as $k => $row) {
+        foreach ($rename_columns as $old_column => $new_column) {
+          $this->data[$k][$new_column] = $this->data[$k][$old_column];
+          unset($this->data[$k][$old_column]);
+        }
+      }
+
+      // Finally, extract the first row again.
+      $this->currentRow = $this->data[0];
+      unset($this->data[0]);
+    }
+
+    return $return;
+  }
+}
diff --git a/core/lib/Drupal/Core/Datetime/DrupalDateTime.php b/core/lib/Drupal/Core/Datetime/DrupalDateTime.php
index 74bd68b..ac22dab 100644
--- a/core/lib/Drupal/Core/Datetime/DrupalDateTime.php
+++ b/core/lib/Drupal/Core/Datetime/DrupalDateTime.php
@@ -62,9 +62,9 @@ public function __construct($time = 'now', $timezone = NULL, $settings = array()
    * knowledge of the preferred user timezone.
    */
   protected function prepareTimezone($timezone) {
-    if (empty($timezone)) {
-      // Fallback to user or system default timezone.
-      $timezone = drupal_get_user_timezone();
+    $user_timezone = drupal_get_user_timezone();
+    if (empty($timezone) && !empty($user_timezone)) {
+      $timezone = $user_timezone;
     }
     return parent::prepareTimezone($timezone);
   }
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityForm.php b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
index 3740600..35834ab 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityForm.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
@@ -50,12 +50,6 @@ public static function create(ContainerInterface $container) {
    */
   public function form(array $form, FormStateInterface $form_state) {
     $form = parent::form($form, $form_state);
-    // Content entity forms do not use the parent's #after_build callback
-    // because they only need to rebuild the entity in the validation and the
-    // submit handler because Field API uses its own #after_build callback for
-    // its widgets.
-    unset($form['#after_build']);
-
     $this->getFormDisplay($form_state)->buildForm($this->entity, $form, $form_state);
     // Allow modules to act before and after form language is updated.
     $form['#entity_builders']['update_form_langcode'] = [$this, 'updateFormLangcode'];
diff --git a/core/lib/Drupal/Core/Entity/EntityForm.php b/core/lib/Drupal/Core/Entity/EntityForm.php
index fb015c7..1a137c4 100644
--- a/core/lib/Drupal/Core/Entity/EntityForm.php
+++ b/core/lib/Drupal/Core/Entity/EntityForm.php
@@ -131,13 +131,13 @@ protected function init(FormStateInterface $form_state) {
   /**
    * Returns the actual form array to be built.
    *
-   * @see \Drupal\Core\Entity\EntityForm::processForm()
-   * @see \Drupal\Core\Entity\EntityForm::afterBuild()
+   * @see \Drupal\Core\Entity\EntityForm::build()
    */
   public function form(array $form, FormStateInterface $form_state) {
-    // Add #process and #after_build callbacks.
+    $entity = $this->entity;
+
+    // Add a process callback.
     $form['#process'][] = '::processForm';
-    $form['#after_build'][] = '::afterBuild';
 
     return $form;
   }
@@ -156,23 +156,6 @@ public function processForm($element, FormStateInterface $form_state, $form) {
   }
 
   /**
-   * Form element #after_build callback: Updates the entity with submitted data.
-   *
-   * Updates the internal $this->entity object with submitted values when the
-   * form is being rebuilt (e.g. submitted via AJAX), so that subsequent
-   * processing (e.g. AJAX callbacks) can rely on it.
-   */
-  public function afterBuild(array $element, FormStateInterface $form_state) {
-    // Rebuild the entity if #after_build is being called as part of a form
-    // rebuild, i.e. if we are processing input.
-    if ($form_state->isProcessingInput()) {
-      $this->entity = $this->buildEntity($element, $form_state);
-    }
-
-    return $element;
-  }
-
-  /**
    * Returns the action form element for the current entity form.
    */
   protected function actionsElement(array $form, FormStateInterface $form_state) {
diff --git a/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php
index 16e9613..32f9565 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\EventSubscriber;
 
+use Drupal\Core\ContentNegotiation;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
@@ -20,6 +21,39 @@
 class ContentControllerSubscriber implements EventSubscriberInterface {
 
   /**
+   * Content negotiation library.
+   *
+   * @var \Drupal\Core\ContentNegotiation
+   */
+  protected $negotiation;
+
+  /**
+   * Constructs a new ContentControllerSubscriber object.
+   *
+   * @param \Drupal\Core\ContentNegotiation $negotiation
+   *   The Content Negotiation service.
+   */
+  public function __construct(ContentNegotiation $negotiation) {
+    $this->negotiation = $negotiation;
+  }
+
+  /**
+   * Sets the derived request format on the request.
+   *
+   * @todo Remove when https://www.drupal.org/node/2331919 lands.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   *   The event to process.
+   */
+  public function onRequestDeriveFormat(GetResponseEvent $event) {
+    $request = $event->getRequest();
+
+    if (!$request->attributes->get('_format')) {
+      $request->setRequestFormat($this->negotiation->getContentType($request));
+    }
+  }
+
+  /**
    * Sets the _controller on a request when a _form is defined.
    *
    * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
@@ -40,6 +74,7 @@ public function onRequestDeriveFormWrapper(GetResponseEvent $event) {
    *   An array of event listener definitions.
    */
   static function getSubscribedEvents() {
+    $events[KernelEvents::REQUEST][] = array('onRequestDeriveFormat', 31);
     $events[KernelEvents::REQUEST][] = array('onRequestDeriveFormWrapper', 29);
 
     return $events;
diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
index b3d2202..03f2691 100644
--- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\ContentNegotiation;
 use Drupal\Core\Render\BareHtmlPageRendererInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Utility\Error;
@@ -205,7 +206,8 @@ protected function getFormat(Request $request) {
     // 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);
+    $conneg = new ContentNegotiation();
+    $format = $conneg->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/ExceptionJsonSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
index 9610e8d..7befb00 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
@@ -39,7 +39,7 @@ protected static function getPriority() {
    *   The event to process.
    */
   public function on403(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_FORBIDDEN);
+    $response = new JsonResponse(NULL, Response::HTTP_FORBIDDEN);
     $event->setResponse($response);
   }
 
@@ -50,7 +50,7 @@ public function on403(GetResponseForExceptionEvent $event) {
    *   The event to process.
    */
   public function on404(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_NOT_FOUND);
+    $response = new JsonResponse(NULL, Response::HTTP_NOT_FOUND);
     $event->setResponse($response);
   }
 
@@ -61,7 +61,7 @@ public function on404(GetResponseForExceptionEvent $event) {
    *   The event to process.
    */
   public function on405(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_METHOD_NOT_ALLOWED);
+    $response = new JsonResponse(NULL, Response::HTTP_METHOD_NOT_ALLOWED);
     $event->setResponse($response);
   }
 
diff --git a/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php b/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
index a14d327..c9d9fa9 100644
--- a/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
+++ b/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\EventSubscriber;
 
+use Drupal\Core\ContentNegotiation;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
@@ -90,7 +91,16 @@ public function onException(GetResponseForExceptionEvent $event) {
 
     $handled_formats = $this->getHandledFormats();
 
-    $format = $event->getRequest()->getRequestFormat();
+    // @todo Injecting this service would force all implementing classes to also
+    // handle its injection. However, 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. That change will NOT
+    // be an API change for any implementing classes.  (Whereas if we injected
+    // this class it would be an API change.  That's why we're not doing it.)
+    $conneg = new ContentNegotiation();
+    $format = $conneg->getContentType($event->getRequest());
 
     if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
       $method = 'on' . $exception->getStatusCode();
diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php
index 3485f19..0383a37 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php
@@ -16,6 +16,8 @@
 use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
+use Drupal\Core\ContentNegotiation;
+
 /**
  * Main subscriber for VIEW HTTP responses.
  *
@@ -26,19 +28,30 @@
 class ViewSubscriber implements EventSubscriberInterface {
 
   /**
+   * The content negotiation.
+   *
+   * @var \Drupal\Core\ContentNegotiation
+   */
+  protected $negotiation;
+
+  /**
    * The title resolver.
    *
    * @var \Drupal\Core\Controller\TitleResolverInterface
    */
   protected $titleResolver;
 
+
   /**
    * Constructs a new ViewSubscriber.
    *
+   * @param \Drupal\Core\ContentNegotiation $negotiation
+   *   The content negotiation.
    * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
    *   The title resolver.
    */
-  public function __construct(TitleResolverInterface $title_resolver) {
+  public function __construct(ContentNegotiation $negotiation, TitleResolverInterface $title_resolver) {
+    $this->negotiation = $negotiation;
     $this->titleResolver = $title_resolver;
   }
 
@@ -51,14 +64,14 @@ public function __construct(TitleResolverInterface $title_resolver) {
    * from an JSON-type response is a JSON string, so just wrap it into a
    * Response object.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
+   * @param Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
    *   The Event to process.
    */
   public function onView(GetResponseForControllerResultEvent $event) {
     $request = $event->getRequest();
 
     if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
-      $method = 'on' . $request->getRequestFormat();
+      $method = 'on' . $this->negotiation->getContentType($request);
 
       if (method_exists($this, $method)) {
         $event->setResponse($this->$method($event));
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 172bfc0..412a7b3 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -151,9 +151,17 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
           )));
         }
 
-        // Check the validity of the default configuration. This will throw
-        // exceptions if the configuration is not valid.
-        $config_installer->checkConfigurationToInstall('module', $module);
+        // Install profiles can not have config clashes. Configuration that
+        // has the same name as a module's configuration will be used instead.
+        if ($module != drupal_get_profile()) {
+          // Validate default configuration of this module. Bail if unable to
+          // install. Should not continue installing more modules because those
+          // may depend on this one.
+          $existing_configuration = $config_installer->findPreExistingConfiguration('module', $module);
+          if (!empty($existing_configuration)) {
+            throw PreExistingConfigException::create($module, $existing_configuration);
+          }
+        }
 
         $extension_config
           ->set("module.$module", 0)
@@ -241,6 +249,12 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
             ->setSyncing(TRUE)
             ->setSourceStorage($source_storage);
         }
+        else {
+          // If we're not in a config synchronization reset the source storage
+          // so that the extension install storage will pick up the new
+          // configuration.
+          $config_installer->resetSourceStorage();
+        }
         \Drupal::service('config.installer')->installDefaultConfig('module', $module);
 
         // If the module has no current updates, but has some that were
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 0c7ade4..dcb1fe3 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -258,7 +258,10 @@ public function install(array $theme_list, $install_dependencies = TRUE) {
 
       // Validate default configuration of the theme. If there is existing
       // configuration then stop installing.
-      $this->configInstaller->checkConfigurationToInstall('theme', $key);
+      $existing_configuration = $this->configInstaller->findPreExistingConfiguration('theme', $key);
+      if (!empty($existing_configuration)) {
+        throw PreExistingConfigException::create($key, $existing_configuration);
+      }
 
       // The value is not used; the weight is ignored for themes currently.
       $extension_config
@@ -285,6 +288,16 @@ public function install(array $theme_list, $install_dependencies = TRUE) {
       // Only install default configuration if this theme has not been installed
       // already.
       if (!isset($installed_themes[$key])) {
+        // The default config installation storage only knows about the
+        // currently installed list of themes, so it has to be reset in order to
+        // pick up the default config of the newly installed theme. However, do
+        // not reset the source storage when synchronizing configuration, since
+        // that would needlessly trigger a reload of the whole configuration to
+        // be imported.
+        if (!$this->configInstaller->isSyncing()) {
+          $this->configInstaller->resetSourceStorage();
+        }
+
         // Install default configuration of the theme.
         $this->configInstaller->installDefaultConfig('theme', $key);
       }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php
index fbf1206..d142872 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php
@@ -117,7 +117,7 @@ public function settingsSummary() {
    * {@inheritdoc}
    */
   protected function viewValue(FieldItemInterface $item) {
-    // The 'languages' cache context is not necessary because the language is
+    // The language cache context is not necessary because the language is
     // either displayed in its configured form (loaded directly from config
     // storage by LanguageManager::getLanguages()) or in its native language
     // name. That only depends on formatter settings and no language condition.
diff --git a/core/lib/Drupal/Core/File/FileSystem.php b/core/lib/Drupal/Core/File/FileSystem.php
index aedfdf6..0365bca 100644
--- a/core/lib/Drupal/Core/File/FileSystem.php
+++ b/core/lib/Drupal/Core/File/FileSystem.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\File;
 
-use Drupal\Core\Site\Settings;
 use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
 use Psr\Log\LoggerInterface;
 
@@ -27,13 +26,6 @@ class FileSystem implements FileSystemInterface {
   const CHMOD_FILE = 0664;
 
   /**
-   * The site settings.
-   *
-   * @var \Drupal\Core\Site\Settings
-   */
-  protected $settings;
-
-  /**
    * The file logger channel.
    *
    * @var \Psr\Log\LoggerInterface
@@ -48,19 +40,31 @@ class FileSystem implements FileSystemInterface {
   protected $streamWrapperManager;
 
   /**
+   * The file chmod configuration.
+   *
+   * @var array
+   */
+  private $fileChmodConfiguration;
+
+  /**
    * Constructs a new FileSystem.
    *
    * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager
    *   The stream wrapper manager.
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The site settings.
+   * @param array $file_chmod_configuration
+   *   The file chmod configuration.
    * @param \Psr\Log\LoggerInterface $logger
    *   The file logger channel.
    */
-  public function __construct(StreamWrapperManagerInterface $stream_wrapper_manager, Settings $settings, LoggerInterface $logger) {
+  public function __construct(StreamWrapperManagerInterface $stream_wrapper_manager, array $file_chmod_configuration, LoggerInterface $logger) {
     $this->streamWrapperManager = $stream_wrapper_manager;
-    $this->settings = $settings;
     $this->logger = $logger;
+
+    $file_chmod_configuration += [
+      'directory' => static::CHMOD_DIRECTORY,
+      'file' => static::CHMOD_FILE,
+    ];
+    $this->fileChmodConfiguration = $file_chmod_configuration;
   }
 
   /**
@@ -89,10 +93,10 @@ public function moveUploadedFile($filename, $uri) {
   public function chmod($uri, $mode = NULL) {
     if (!isset($mode)) {
       if (is_dir($uri)) {
-        $mode = $this->settings->get('file_chmod_directory', static::CHMOD_DIRECTORY);
+        $mode = $this->fileChmodConfiguration['directory'];
       }
       else {
-        $mode = $this->settings->get('file_chmod_file', static::CHMOD_FILE);
+        $mode = $this->fileChmodConfiguration['file'];
       }
     }
 
@@ -174,7 +178,7 @@ public function basename($uri, $suffix = NULL) {
    */
   public function mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
     if (!isset($mode)) {
-      $mode = $this->settings->get('file_chmod_directory', static::CHMOD_DIRECTORY);
+      $mode = $this->fileChmodConfiguration['directory'];
     }
 
     // If the URI has a scheme, don't override the umask - schemes can handle
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index 8eb78dd..b67a37b 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -801,8 +801,8 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
     // The #after_build flag allows any piece of a form to be altered
     // after normal input parsing has been completed.
     if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
-      foreach ($element['#after_build'] as $callback) {
-        $element = call_user_func_array($form_state->prepareCallback($callback), array($element, &$form_state));
+      foreach ($element['#after_build'] as $callable) {
+        $element = call_user_func_array($callable, array($element, &$form_state));
       }
       $element['#after_build_done'] = TRUE;
     }
diff --git a/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php
index 9d651cd..dd2d262 100644
--- a/core/lib/Drupal/Core/Form/FormState.php
+++ b/core/lib/Drupal/Core/Form/FormState.php
@@ -1241,7 +1241,6 @@ public function cleanValues() {
         unset($values[$last_parent]);
       }
     }
-    return $this;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Menu/MenuActiveTrailInterface.php b/core/lib/Drupal/Core/Menu/MenuActiveTrailInterface.php
index be32e64..49f4e99 100644
--- a/core/lib/Drupal/Core/Menu/MenuActiveTrailInterface.php
+++ b/core/lib/Drupal/Core/Menu/MenuActiveTrailInterface.php
@@ -18,9 +18,8 @@
   /**
    * Gets the active trail IDs of the specified menu tree.
    *
-   * @param string|NULL $menu_name
-   *   (optional) The menu name of the requested tree. If omitted, all menu
-   *   trees will be searched.
+   * @param string $menu_name
+   *   The menu name of the requested tree.
    *
    * @return array
    *   An array containing the active trail: a list of plugin IDs.
diff --git a/core/lib/Drupal/Core/Queue/QueueFactory.php b/core/lib/Drupal/Core/Queue/QueueFactory.php
index 70824c3..9ff72d8 100644
--- a/core/lib/Drupal/Core/Queue/QueueFactory.php
+++ b/core/lib/Drupal/Core/Queue/QueueFactory.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\Queue;
 
-use Drupal\Core\Site\Settings;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 
@@ -26,18 +25,24 @@ class QueueFactory implements ContainerAwareInterface {
   protected $queues = array();
 
   /**
-   * The settings object.
+   * The queue configuration.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var array
    */
-  protected $settings;
-
+  protected $queueConfiguration;
 
   /**
    * Constructs a queue factory.
+   *
+   * @param array $queue_configuration
+   *   The queue configuration, more information in
+   *   sites/default/default.services.yml
    */
-  function __construct(Settings $settings) {
-    $this->settings = $settings;
+  function __construct(array $queue_configuration) {
+    $queue_configuration += [
+      'default' => 'queue.database',
+    ];
+    $this->queueConfiguration = $queue_configuration;
   }
 
   /**
@@ -57,12 +62,12 @@ public function get($name, $reliable = FALSE) {
     if (!isset($this->queues[$name])) {
       // If it is a reliable queue, check the specific settings first.
       if ($reliable) {
-        $service_name = $this->settings->get('queue_reliable_service_' . $name);
+        $service_name = isset($this->queueConfiguration['reliable_service_' . $name]) ? $this->queueConfiguration['queue_reliable_service_' . $name] : NULL;
       }
       // If no reliable queue was defined, check the service and global
       // settings, fall back to queue.database.
       if (empty($service_name)) {
-        $service_name = $this->settings->get('queue_service_' . $name, $this->settings->get('queue_default', 'queue.database'));
+        $service_name = isset($this->queueConfiguration['service_' . $name]) ? $this->queueConfiguration['service_' . $name] : $this->queueConfiguration['default'];
       }
       $this->queues[$name] = $this->container->get($service_name)->get($name);
     }
diff --git a/core/lib/Drupal/Core/Render/Element/Pager.php b/core/lib/Drupal/Core/Render/Element/Pager.php
index eeb0f9d..006064a 100644
--- a/core/lib/Drupal/Core/Render/Element/Pager.php
+++ b/core/lib/Drupal/Core/Render/Element/Pager.php
@@ -46,7 +46,7 @@ public function getInfo() {
    * @return array
    */
   public static function preRenderPager(array $pager) {
-    $pager['#cache']['contexts'][] = 'url.query_args.pagers:' . $pager['#element'];
+    $pager['#cache']['contexts'][] = 'pager:' . $pager['#element'];
     return $pager;
   }
 
diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
index 249b47b..269b64e 100644
--- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
+++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php
@@ -10,7 +10,6 @@
 use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheContexts;
 use Drupal\Core\Controller\TitleResolverInterface;
 use Drupal\Core\Display\PageVariantInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -65,13 +64,6 @@ class HtmlRenderer implements MainContentRendererInterface {
   protected $renderer;
 
   /**
-   * The cache contexts service.
-   *
-   * @var \Drupal\Core\Cache\CacheContexts
-   */
-  protected $cacheContexts;
-
-  /**
    * Constructs a new HtmlRenderer.
    *
    * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
@@ -84,16 +76,13 @@ class HtmlRenderer implements MainContentRendererInterface {
    *   The module handler.
    * @param \Drupal\Core\Render\RendererInterface $renderer
    *   The renderer service.
-   * @param \Drupal\Core\Cache\CacheContexts $cache_contexts
-   *   The cache contexts service.
    */
-  public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ModuleHandlerInterface $module_handler, RendererInterface $renderer, CacheContexts $cache_contexts) {
+  public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ModuleHandlerInterface $module_handler, RendererInterface $renderer) {
     $this->titleResolver = $title_resolver;
     $this->displayVariantManager = $display_variant_manager;
     $this->eventDispatcher = $event_dispatcher;
     $this->moduleHandler = $module_handler;
     $this->renderer = $renderer;
-    $this->cacheContexts = $cache_contexts;
   }
 
   /**
@@ -160,7 +149,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
 
     $response = new Response($content, 200,[
       'X-Drupal-Cache-Tags' => implode(' ', $cache_tags),
-      'X-Drupal-Cache-Contexts' => implode(' ', $this->cacheContexts->optimizeTokens($cache_contexts)),
+      'X-Drupal-Cache-Contexts' => implode(' ', $cache_contexts),
       'X-Generator' => 'Drupal ' . $version . ' (https://www.drupal.org)'
     ]);
     // If an explicit non-infinite max-age is specified by a part of the page,
diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php
index b1d300e..a7f7346 100644
--- a/core/lib/Drupal/Core/Render/Renderer.php
+++ b/core/lib/Drupal/Core/Render/Renderer.php
@@ -358,7 +358,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
 
     // Cache the processed element if #cache is set, and the metadata necessary
     // to generate a cache ID is present.
-    if (isset($elements['#cache']) && isset($elements['#cache']['keys'])) {
+    if (isset($elements['#cache']) && (isset($elements['#cache']['keys']) || isset($elements['#cache']['cid']))) {
       $this->cacheSet($elements, $pre_bubbling_cid);
     }
 
@@ -546,7 +546,7 @@ protected function cacheSet(array &$elements, $pre_bubbling_cid) {
     $data = $this->getCacheableRenderArray($elements);
 
     $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'render';
-    $expire = ($elements['#cache']['max-age'] === Cache::PERMANENT) ? Cache::PERMANENT : REQUEST_TIME + $elements['#cache']['max-age'];
+    $expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : Cache::PERMANENT;
     $cache = $this->cacheFactory->get($bin);
 
     // Two-tier caching: detect different CID post-bubbling, create redirect,
@@ -713,7 +713,9 @@ protected function cacheSet(array &$elements, $pre_bubbling_cid) {
   /**
    * Creates the cache ID for a renderable element.
    *
-   * Creates the cache ID string based on #cache['keys'] + #cache['contexts'].
+   * This creates the cache ID string, either by returning the #cache['cid']
+   * property if present or by building the cache ID out of the #cache['keys'] +
+   * #cache['contexts'].
    *
    * @param array $elements
    *   A renderable array.
@@ -727,9 +729,12 @@ protected function createCacheID(array $elements) {
       return FALSE;
     }
 
-    if (isset($elements['#cache']['keys'])) {
+    if (isset($elements['#cache']['cid'])) {
+      return $elements['#cache']['cid'];
+    }
+    elseif (isset($elements['#cache']['keys'])) {
       $cid_parts = $elements['#cache']['keys'];
-      if (!empty($elements['#cache']['contexts'])) {
+      if (isset($elements['#cache']['contexts'])) {
         $contexts = $this->cacheContexts->convertTokensToKeys($elements['#cache']['contexts']);
         $cid_parts = array_merge($cid_parts, $contexts);
       }
diff --git a/core/lib/Drupal/Core/Render/RendererInterface.php b/core/lib/Drupal/Core/Render/RendererInterface.php
index 21b223d..33502ba 100644
--- a/core/lib/Drupal/Core/Render/RendererInterface.php
+++ b/core/lib/Drupal/Core/Render/RendererInterface.php
@@ -117,8 +117,10 @@ public function renderPlain(&$elements);
    *     - 'contexts': An array of one or more cache context IDs. These are
    *       converted to a final value depending on the request. (e.g. 'user' is
    *       mapped to the current user's ID.)
-   *     - 'max-age': A time in seconds. Zero seconds means it is not cacheable.
-   *       \Drupal\Core\Cache\Cache::PERMANENT means it is cacheable forever.
+   *     - 'cid': Specify the cache ID directly. Either 'keys' or 'cid' is
+   *       required. If 'cid' is set, 'keys' is ignored. Use only if you have
+   *       special requirements.
+   *     - 'expire': Set to one of the cache lifetime constants.
    *     - 'bin': Specify a cache bin to cache the element in. Default is
    *       'default'.
    *     When there is a render cache hit, there is no rendering work left to be
diff --git a/core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php b/core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php
index 5c0618c..11760dd 100644
--- a/core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php
+++ b/core/lib/Drupal/Core/Routing/AcceptHeaderMatcher.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Routing;
 
 use Drupal\Component\Utility\String;
+use Drupal\Core\ContentNegotiation;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
 use Symfony\Component\Routing\Route;
@@ -19,6 +20,23 @@
 class AcceptHeaderMatcher implements RouteFilterInterface {
 
   /**
+   * The content negotiation library.
+   *
+   * @var \Drupal\Core\ContentNegotiation
+   */
+  protected $contentNegotiation;
+
+  /**
+   * Constructs a new AcceptHeaderMatcher.
+   *
+   * @param \Drupal\Core\ContentNegotiation $content_negotiation
+   *   The content negotiation library.
+   */
+  public function __construct(ContentNegotiation $content_negotiation) {
+    $this->contentNegotiation = $content_negotiation;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function filter(RouteCollection $collection, Request $request) {
@@ -26,7 +44,7 @@ public function filter(RouteCollection $collection, Request $request) {
     // @todo replace by proper content negotiation library.
     $acceptable_mime_types = $request->getAcceptableContentTypes();
     $acceptable_formats = array_filter(array_map(array($request, 'getFormat'), $acceptable_mime_types));
-    $primary_format = $request->getRequestFormat();
+    $primary_format = $this->contentNegotiation->getContentType($request);
 
     foreach ($collection as $name => $route) {
       // _format could be a |-delimited list of supported formats.
diff --git a/core/lib/Drupal/Core/Routing/RoutePreloader.php b/core/lib/Drupal/Core/Routing/RoutePreloader.php
index 1f223bf..7952d17 100644
--- a/core/lib/Drupal/Core/Routing/RoutePreloader.php
+++ b/core/lib/Drupal/Core/Routing/RoutePreloader.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Routing;
 
+use Drupal\Core\ContentNegotiation;
 use Drupal\Core\State\StateInterface;
 use Symfony\Component\EventDispatcher\Event;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -37,6 +38,13 @@ class RoutePreloader implements EventSubscriberInterface {
   protected $state;
 
   /**
+   * The content negotiation.
+   *
+   * @var \Drupal\Core\ContentNegotiation
+   */
+  protected $negotiation;
+
+  /**
    * Contains the non-admin routes while rebuilding the routes.
    *
    * @var array
@@ -50,10 +58,13 @@ class RoutePreloader implements EventSubscriberInterface {
    *   The route provider.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state key value store.
+   * @param \Drupal\Core\ContentNegotiation $negotiation
+   *   The content negotiation.
    */
-  public function __construct(RouteProviderInterface $route_provider, StateInterface $state) {
+  public function __construct(RouteProviderInterface $route_provider, StateInterface $state, ContentNegotiation $negotiation) {
     $this->routeProvider = $route_provider;
     $this->state = $state;
+    $this->negotiation = $negotiation;
   }
 
   /**
@@ -64,7 +75,7 @@ public function __construct(RouteProviderInterface $route_provider, StateInterfa
    */
   public function onRequest(KernelEvent $event) {
     // Just preload on normal HTML pages, as they will display menu links.
-    if ($event->getRequest()->getRequestFormat() == 'html') {
+    if ($this->negotiation->getContentType($event->getRequest()) == 'html') {
       $this->loadNonAdminRoutes();
     }
   }
diff --git a/core/lib/Drupal/Core/Session/MetadataBag.php b/core/lib/Drupal/Core/Session/MetadataBag.php
index 4b44739..2526d18 100644
--- a/core/lib/Drupal/Core/Session/MetadataBag.php
+++ b/core/lib/Drupal/Core/Session/MetadataBag.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\Session;
 
-use Drupal\Core\Site\Settings;
 use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag as SymfonyMetadataBag;
 
 /**
@@ -23,12 +22,11 @@ class MetadataBag extends SymfonyMetadataBag {
   /**
    * Constructs a new metadata bag instance.
    *
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The settings instance.
+   * @param int $session_write_interval
+   *   The session write interval.
    */
-  public function __construct(Settings $settings) {
-    $update_threshold = $settings->get('session_write_interval', 180);
-    parent::__construct('_sf2_meta', $update_threshold);
+  public function __construct($session_write_interval = 180) {
+    parent::__construct('_sf2_meta', $session_write_interval);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Session/SessionHandler.php b/core/lib/Drupal/Core/Session/SessionHandler.php
index 8d9aa96..8107e9d 100644
--- a/core/lib/Drupal/Core/Session/SessionHandler.php
+++ b/core/lib/Drupal/Core/Session/SessionHandler.php
@@ -41,16 +41,26 @@ class SessionHandler extends AbstractProxy implements \SessionHandlerInterface {
   protected $obsoleteSessionIds = array();
 
   /**
+   * The session write interval.
+   *
+   * @var int
+   */
+  protected $sessionWriteInterval;
+
+  /**
    * Constructs a new SessionHandler instance.
    *
    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
    *   The request stack.
    * @param \Drupal\Core\Database\Connection $connection
    *   The database connection.
+   * @param int $session_write_interval
+   *   The session write interval.
    */
-  public function __construct(RequestStack $request_stack, Connection $connection) {
+  public function __construct(RequestStack $request_stack, Connection $connection, $session_write_interval = 180) {
     $this->requestStack = $request_stack;
     $this->connection = $connection;
+    $this->sessionWriteInterval = $session_write_interval;
   }
 
   /**
@@ -126,7 +136,7 @@ public function write($sid, $value) {
         ->execute();
 
       // Likewise, do not update access time more than once per 180 seconds.
-      if ($user->isAuthenticated() && REQUEST_TIME - $user->getLastAccessedTime() > Settings::get('session_write_interval', 180)) {
+      if ($user->isAuthenticated() && REQUEST_TIME - $user->getLastAccessedTime() > $this->sessionWriteInterval) {
         /** @var \Drupal\user\UserStorageInterface $storage */
         $storage = \Drupal::entityManager()->getStorage('user');
         $storage->updateLastAccessTimestamp($user, REQUEST_TIME);
diff --git a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php b/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
deleted file mode 100644
index 295857d..0000000
--- a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\StackMiddleware\NegotationMiddleware.
- */
-
-namespace Drupal\Core\StackMiddleware;
-
-use Drupal\Core\ContentNegotiation;
-use Drupal\Core\ContentNegotiationInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-
-/**
- * Provides a middleware to determine the content type upon the accept header.
- *
- * @todo This is a temporary solution, remove this in https://www.drupal.org/node/2364011
- */
-class NegotiationMiddleware implements HttpKernelInterface {
-
-  /**
-   * The wrapped HTTP kernel.
-   *
-   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
-   */
-  protected $app;
-
-  /**
-   * The content negotiator.
-   *
-   * @var \Drupal\Core\ContentNegotiation
-   */
-  protected $negotiator;
-
-  /**
-   * Contains a hashmap of format as key and mimetype as value.
-   *
-   * @var array
-   */
-  protected $formats;
-
-  /**
-   * Constructs a new NegotiationMiddleware.
-   *
-   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $app
-   *   The wrapper HTTP kernel
-   * @param \Drupal\Core\ContentNegotiation $negotiator
-   *   The content negotiator.
-   */
-  public function __construct(HttpKernelInterface $app, ContentNegotiation $negotiator) {
-    $this->app = $app;
-    $this->negotiator = $negotiator;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) {
-    foreach ($this->formats as $format => $mime_type) {
-      $request->setFormat($format, $mime_type);
-    }
-
-    $request->setRequestFormat($this->negotiator->getContentType($request));
-    return $this->app->handle($request, $type, $catch);
-  }
-
-  /**
-   * Registers a format for a given MIME type.
-   *
-   * @param string $format
-   *   The format.
-   * @param string $mime_type
-   *   The MIME type.
-   *
-   * @return $this
-   */
-  public function registerFormat($format, $mime_type) {
-    $this->formats[$format] = $mime_type;
-    return $this;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/StackMiddleware/PageCache.php b/core/lib/Drupal/Core/StackMiddleware/PageCache.php
index d4ec291..b381018 100644
--- a/core/lib/Drupal/Core/StackMiddleware/PageCache.php
+++ b/core/lib/Drupal/Core/StackMiddleware/PageCache.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\ContentNegotiation;
 use Drupal\Core\PageCache\RequestPolicyInterface;
 use Drupal\Core\PageCache\ResponsePolicyInterface;
 use Drupal\Core\Site\Settings;
@@ -52,6 +53,13 @@ class PageCache implements HttpKernelInterface {
   protected $responsePolicy;
 
   /**
+   * The content negotiation library.
+   *
+   * @var \Drupal\Core\ContentNegotiation
+   */
+  protected $contentNegotiation;
+
+  /**
    * Constructs a ReverseProxyMiddleware object.
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
@@ -62,12 +70,15 @@ class PageCache implements HttpKernelInterface {
    *   A policy rule determining the cacheability of a request.
    * @param \Drupal\Core\PageCache\ResponsePolicyInterface $response_policy
    *   A policy rule determining the cacheability of the response.
+   * @param \Drupal\Core\ContentNegotiation $content_negotiation
+   *   The content negotiation library.
    */
-  public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy) {
+  public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy, ContentNegotiation $content_negotiation) {
     $this->httpKernel = $http_kernel;
     $this->cache = $cache;
     $this->requestPolicy = $request_policy;
     $this->responsePolicy = $response_policy;
+    $this->contentNegotiation = $content_negotiation;
   }
 
   /**
@@ -321,7 +332,7 @@ protected function set(Request $request, Response $response, $expire, array $tag
   protected function getCacheId(Request $request) {
     $cid_parts = array(
       $request->getUri(),
-      $request->getRequestFormat(),
+      $this->contentNegotiation->getContentType($request),
     );
     return implode(':', $cid_parts);
   }
diff --git a/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php b/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
index 344364d..f0504f0 100644
--- a/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
+++ b/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
@@ -6,7 +6,6 @@
 
 namespace Drupal\Core\StackMiddleware;
 
-use Drupal\Core\Site\Settings;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
@@ -23,23 +22,28 @@ class ReverseProxyMiddleware implements HttpKernelInterface {
   protected $httpKernel;
 
   /**
-   * The site settings.
+   * The reverse proxy configuration.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var array
    */
-  protected $settings;
+  private $reverseProxyConfiguration;
 
   /**
    * Constructs a ReverseProxyMiddleware object.
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
    *   The decorated kernel.
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The site settings.
+   * @param array $reverse_proxy_configuration
+   *   The reverse proxy configuration.
    */
-  public function __construct(HttpKernelInterface $http_kernel, Settings $settings) {
+  public function __construct(HttpKernelInterface $http_kernel, array $reverse_proxy_configuration = []) {
     $this->httpKernel = $http_kernel;
-    $this->settings = $settings;
+
+    $reverse_proxy_configuration += [
+      'header' => 'X_FORWARDED_FOR',
+      'addresses' => [],
+    ];
+    $this->reverseProxyConfiguration = $reverse_proxy_configuration;
   }
 
   /**
@@ -47,10 +51,10 @@ public function __construct(HttpKernelInterface $http_kernel, Settings $settings
    */
   public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
     // Initialize proxy settings.
-    if ($this->settings->get('reverse_proxy', FALSE)) {
-      $reverse_proxy_header = $this->settings->get('reverse_proxy_header', 'X_FORWARDED_FOR');
+    if (!empty($this->reverseProxyConfiguration['enabled'])) {
+      $reverse_proxy_header = $this->reverseProxyConfiguration['header'];
       $request::setTrustedHeaderName($request::HEADER_CLIENT_IP, $reverse_proxy_header);
-      $proxies = $this->settings->get('reverse_proxy_addresses', array());
+      $proxies = $this->reverseProxyConfiguration['addresses'];
       if (count($proxies) > 0) {
         $request::setTrustedProxies($proxies);
       }
diff --git a/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php b/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php
index ebb20e4..85a6e3f 100644
--- a/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php
+++ b/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php
@@ -53,17 +53,6 @@ protected function formatPlural($count, $singular, $plural, array $args = array(
   }
 
   /**
-   * Formats a translated string containing a count of items.
-   *
-   * See the
-   * \Drupal\Core\StringTranslation\TranslationInterface::formatPluralTranslated()
-   * documentation for details.
-   */
-  protected function formatPluralTranslated($count, $translated, array $args = array(), array $options = array()) {
-    return $this->getStringTranslation()->formatPluralTranslated($count, $translated, $args, $options);
-  }
-
-  /**
    * Gets the string translation service.
    *
    * @return \Drupal\Core\StringTranslation\TranslationInterface
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php b/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
index 3e866bb..bc560cf 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
@@ -41,7 +41,7 @@ public function translate($string, array $args = array(), array $options = array
    *
    * This function ensures that the string is pluralized correctly. Since t() is
    * called by this function, make sure not to pass already-localized strings to
-   * it. See formatPluralTranslated() for that.
+   * it.
    *
    * For example:
    * @code
@@ -70,54 +70,19 @@ public function translate($string, array $args = array(), array $options = array
    *   An associative array of replacements to make after translation. Instances
    *   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. See \Drupal\Component\Utility\String::format(). Note that you do
-   *   not need to include @count in this array; this replacement is done
-   *   automatically for the plural cases.
+   *   themed. See format_string(). Note that you do not need to include @count
+   *   in this array; this replacement is done automatically for the plural case.
    * @param array $options
    *   An associative array of additional options. See t() for allowed keys.
    *
    * @return string
    *   A translated string.
    *
-   * @see self::translate()
+   * @see self::translate
+   * @see \Drupal\Component\Utility\String
    * @see t()
-   * @see \Drupal\Component\Utility\SafeMarkup::format()
-   * @see self::formatPluralTranslated
+   * @see format_string()
    */
   public function formatPlural($count, $singular, $plural, array $args = array(), array $options = array());
 
-  /**
-   * Formats an already translated string containing a count of items.
-   *
-   * This function ensures that the string is pluralized correctly. As opposed
-   * to the formatPlural() method, this method is designed to be invoked with
-   * a string already translated (such as with configuration translation).
-   *
-   * @param int $count
-   *   The item count to display.
-   * @param string $translation
-   *   The string containing the translation of a singular/plural pair. It may
-   *   contain any number of possible variants (depending on the language
-   *   translated to) separated by the value of the LOCALE_PLURAL_DELIMITER
-   *   constant.
-   * @param array $args
-   *   Associative array of replacements to make in the translation. Instances
-   *   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. See \Drupal\Component\Utility\String::format(). Note that you do
-   *   not need to include @count in this array; this replacement is done
-   *   automatically for the plural cases.
-   * @param array $options
-   *   An associative array of additional options. The 'context' key is not
-   *   supported because the passed string is already translated. Use the
-   *   'langcode' key to ensure the proper plural logic is used.
-   *
-   * @return string
-   *   The correct substring for the given $count with $args replaced.
-   *
-   * @see self::formatPlural()
-   * @see \Drupal\Component\Utility\SafeMarkup::format()
-   */
-  public function formatPluralTranslated($count, $translation, array $args = array(), array $options = array());
-
 }
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
index edb391c..cdfc2df 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\StringTranslation;
 
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
 
@@ -129,30 +130,6 @@ public function getStringTranslation($langcode, $string, $context) {
    * {@inheritdoc}
    */
   public function translate($string, array $args = array(), array $options = array()) {
-    $string = $this->doTranslate($string, $options);
-    if (empty($args)) {
-      return SafeMarkup::set($string);
-    }
-    else {
-      return SafeMarkup::format($string, $args);
-    }
-  }
-
-  /**
-   * Translates a string to the current language or to a given language.
-   *
-   * @param string $string
-   *   A string containing the English string to translate.
-   * @param array $options
-   *   An associative array of additional options, with the following elements:
-   *   - 'langcode': The language code to translate to a language other than
-   *      what is used to display the page.
-   *   - 'context': The context the source string belongs to.
-   *
-   * @return string
-   *   The translated string.
-   */
-  protected function doTranslate($string, array $options = array()) {
     // Merge in defaults.
     if (empty($options['langcode'])) {
       $options['langcode'] = $this->defaultLangcode;
@@ -161,27 +138,30 @@ protected function doTranslate($string, array $options = array()) {
       $options['context'] = '';
     }
     $translation = $this->getStringTranslation($options['langcode'], $string, $options['context']);
-    return $translation === FALSE ? $string : $translation;
-  }
+    $string = $translation === FALSE ? $string : $translation;
 
-  /**
-   * {@inheritdoc}
-   */
-  public function formatPlural($count, $singular, $plural, array $args = array(), array $options = array()) {
-    $translatable_string = implode(LOCALE_PLURAL_DELIMITER, array($singular, $plural));
-    $translated_strings = $this->doTranslate($translatable_string, $options);
-    return $this->formatPluralTranslated($count, $translated_strings, $args, $options);
+    if (empty($args)) {
+      return SafeMarkup::set($string);
+    }
+    else {
+      return String::format($string, $args);
+    }
   }
 
   /**
    * {@inheritdoc}
    */
-  public function formatPluralTranslated($count, $translation, array $args = array(), array $options = array()) {
+  public function formatPlural($count, $singular, $plural, array $args = array(), array $options = array()) {
     $args['@count'] = $count;
-    $translated_array = explode(LOCALE_PLURAL_DELIMITER, $translation);
+    // Join both forms to search a translation.
+    $translatable_string = implode(LOCALE_PLURAL_DELIMITER, array($singular, $plural));
+    // Translate as usual.
+    $translated_strings = $this->translate($translatable_string, $args, $options);
+    // Split joined translation strings into array.
+    $translated_array = explode(LOCALE_PLURAL_DELIMITER, $translated_strings);
 
     if ($count == 1) {
-      return SafeMarkup::format($translated_array[0], $args);
+      return SafeMarkup::set($translated_array[0]);
     }
 
     // Get the plural index through the gettext formula.
@@ -203,8 +183,7 @@ public function formatPluralTranslated($count, $translation, array $args = array
         $return = $translated_array[1];
       }
     }
-
-    return SafeMarkup::format($return, $args);
+    return SafeMarkup::set($return);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php b/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php
index 24f5085..b1bc189 100644
--- a/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php
+++ b/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php
@@ -18,28 +18,10 @@
 class CustomStrings extends StaticTranslation {
 
   /**
-   * The settings read only object.
-   *
-   * @var \Drupal\Core\Site\Settings
-   */
-  protected $settings;
-
-  /**
-   * Constructs a CustomStrings object.
-   *
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The settings read only object.
-   */
-  public function __construct(Settings $settings) {
-    parent::__construct();
-    $this->settings = $settings;
-  }
-
-  /**
    * {@inheritdoc}
    */
   protected function getLanguage($langcode) {
-    return $this->settings->get('locale_custom_strings_' . $langcode, array());
+    return Settings::get('locale_custom_strings_' . $langcode, array());
   }
 
 }
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/BinaryData.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Binary.php
similarity index 91%
rename from core/lib/Drupal/Core/TypedData/Plugin/DataType/BinaryData.php
rename to core/lib/Drupal/Core/TypedData/Plugin/DataType/Binary.php
index a18c7d5..f18a6af 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/BinaryData.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Binary.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\Core\TypedData\Plugin\DataType\BinaryData.
+ * Contains \Drupal\Core\TypedData\Plugin\DataType\Binary.
  */
 
 namespace Drupal\Core\TypedData\Plugin\DataType;
@@ -23,7 +23,7 @@
  *   label = @Translation("Binary")
  * )
  */
-class BinaryData extends PrimitiveBase implements BinaryInterface {
+class Binary extends PrimitiveBase implements BinaryInterface {
 
   /**
    * The file resource URI.
@@ -63,7 +63,7 @@ public function setValue($value, $notify = TRUE) {
     }
     elseif (is_string($value)) {
       // Note: For performance reasons we store the given URI and access the
-      // resource upon request. See BinaryData::getValue()
+      // resource upon request. See Binary::getValue()
       $this->uri = $value;
       $this->handle = NULL;
     }
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/BooleanData.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Boolean.php
similarity index 79%
rename from core/lib/Drupal/Core/TypedData/Plugin/DataType/BooleanData.php
rename to core/lib/Drupal/Core/TypedData/Plugin/DataType/Boolean.php
index adcef37..874fcbb 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/BooleanData.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Boolean.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\Core\TypedData\Plugin\DataType\BooleanData.
+ * Contains \Drupal\Core\TypedData\Plugin\DataType\Boolean.
  */
 
 namespace Drupal\Core\TypedData\Plugin\DataType;
@@ -21,7 +21,7 @@
  *   label = @Translation("Boolean")
  * )
  */
-class BooleanData extends PrimitiveBase implements BooleanInterface {
+class Boolean extends PrimitiveBase implements BooleanInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/DateTimeIso8601.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/DateTimeIso8601.php
index f01c230..8c35457 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/DateTimeIso8601.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/DateTimeIso8601.php
@@ -20,7 +20,7 @@
  *   label = @Translation("Date")
  * )
  */
-class DateTimeIso8601 extends StringData implements DateTimeInterface {
+class DateTimeIso8601 extends String implements DateTimeInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/DurationIso8601.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/DurationIso8601.php
index 0f26418..eeedad4 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/DurationIso8601.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/DurationIso8601.php
@@ -19,7 +19,7 @@
  *   label = @Translation("Duration")
  * )
  */
-class DurationIso8601 extends StringData implements DurationInterface {
+class DurationIso8601 extends String implements DurationInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Email.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Email.php
index b4c5682..91740e5 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Email.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Email.php
@@ -20,6 +20,6 @@
  *   constraints = {"Email" = {}}
  * )
  */
-class Email extends StringData implements StringInterface {
+class Email extends String implements StringInterface {
 
 }
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/FloatData.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Float.php
similarity index 80%
rename from core/lib/Drupal/Core/TypedData/Plugin/DataType/FloatData.php
rename to core/lib/Drupal/Core/TypedData/Plugin/DataType/Float.php
index e350a59..3980f0a 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/FloatData.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Float.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\Core\TypedData\Plugin\DataType\FloatData.
+ * Contains \Drupal\Core\TypedData\Plugin\DataType\Float.
  */
 
 namespace Drupal\Core\TypedData\Plugin\DataType;
@@ -21,7 +21,7 @@
  *   label = @Translation("Float")
  * )
  */
-class FloatData extends PrimitiveBase implements FloatInterface {
+class Float extends PrimitiveBase implements FloatInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/IntegerData.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Integer.php
similarity index 79%
rename from core/lib/Drupal/Core/TypedData/Plugin/DataType/IntegerData.php
rename to core/lib/Drupal/Core/TypedData/Plugin/DataType/Integer.php
index 2244e96..b5fe36a 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/IntegerData.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Integer.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\Core\TypedData\Plugin\DataType\IntegerData.
+ * Contains \Drupal\Core\TypedData\Plugin\DataType\Integer.
  */
 
 namespace Drupal\Core\TypedData\Plugin\DataType;
@@ -21,7 +21,7 @@
  *   label = @Translation("Integer")
  * )
  */
-class IntegerData extends PrimitiveBase implements IntegerInterface {
+class Integer extends PrimitiveBase implements IntegerInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/StringData.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/String.php
similarity index 79%
rename from core/lib/Drupal/Core/TypedData/Plugin/DataType/StringData.php
rename to core/lib/Drupal/Core/TypedData/Plugin/DataType/String.php
index 134b3f2..dd0060f 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/StringData.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/String.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\Core\TypedData\Plugin\DataType\StringData.
+ * Contains \Drupal\Core\TypedData\Plugin\DataType\String.
  */
 
 namespace Drupal\Core\TypedData\Plugin\DataType;
@@ -21,7 +21,7 @@
  *   label = @Translation("String")
  * )
  */
-class StringData extends PrimitiveBase implements StringInterface {
+class String extends PrimitiveBase implements StringInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/TimeSpan.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/TimeSpan.php
index 66a8d27..94362dd 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/TimeSpan.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/TimeSpan.php
@@ -25,7 +25,7 @@
  *
  * @see \Drupal\Core\TypedData\Type\DurationIso8601
  */
-class TimeSpan extends IntegerData implements DurationInterface {
+class TimeSpan extends Integer implements DurationInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Timestamp.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Timestamp.php
index 512c90d..800344b 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Timestamp.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Timestamp.php
@@ -18,7 +18,7 @@
  *   label = @Translation("String")
  * )
  */
-class Timestamp extends IntegerData implements DateTimeInterface {
+class Timestamp extends Integer implements DateTimeInterface {
 
   /**
    * The data value as a UNIX timestamp.
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Uri.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Uri.php
index ac3d48d..e9a0891 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Uri.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Uri.php
@@ -21,6 +21,6 @@
  *   label = @Translation("URI")
  * )
  */
-class Uri extends StringData implements UriInterface {
+class Uri extends String implements UriInterface {
 
 }
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
index 18310bd..7fe362e 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
@@ -132,14 +132,14 @@ public function createInstance($data_type, array $configuration = array()) {
    *
    * @see \Drupal::typedDataManager()
    * @see \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance()
-   * @see \Drupal\Core\TypedData\Plugin\DataType\BinaryData
-   * @see \Drupal\Core\TypedData\Plugin\DataType\BooleanData
-   * @see \Drupal\Core\TypedData\Plugin\DataType\Date
+   * @see \Drupal\Core\TypedData\Plugin\DataType\Integer
+   * @see \Drupal\Core\TypedData\Plugin\DataType\Float
+   * @see \Drupal\Core\TypedData\Plugin\DataType\String
+   * @see \Drupal\Core\TypedData\Plugin\DataType\Boolean
    * @see \Drupal\Core\TypedData\Plugin\DataType\Duration
-   * @see \Drupal\Core\TypedData\Plugin\DataType\FloatData
-   * @see \Drupal\Core\TypedData\Plugin\DataType\IntegerData
-   * @see \Drupal\Core\TypedData\Plugin\DataType\StringData
+   * @see \Drupal\Core\TypedData\Plugin\DataType\Date
    * @see \Drupal\Core\TypedData\Plugin\DataType\Uri
+   * @see \Drupal\Core\TypedData\Plugin\DataType\Binary
    */
   public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL) {
     $typed_data = $this->createInstance($definition->getDataType(), array(
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 91e8e1c..8fe1dcf 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -27,7 +27,7 @@
         if (typeof element_settings.selector === 'undefined') {
           element_settings.selector = '#' + base;
         }
-        $(element_settings.selector).once('drupal-ajax').each(function () {
+        $(element_settings.selector).once('drupal-ajax', function () {
           element_settings.element = this;
           Drupal.ajax[element_settings.selector] = new Drupal.ajax(base, this, element_settings);
         });
@@ -41,7 +41,7 @@
       }
 
       // Bind Ajax behaviors to all items showing the class.
-      $('.use-ajax').once('ajax').each(function () {
+      $('.use-ajax').once('ajax', function () {
         var element_settings = {};
         // Clicked links look better with the throbber than the progress bar.
         element_settings.progress = {'type': 'throbber'};
@@ -59,7 +59,7 @@
       });
 
       // This class means to submit the form to the action using Ajax.
-      $('.use-ajax-submit').once('ajax').each(function () {
+      $('.use-ajax-submit').once('ajax', function () {
         var element_settings = {};
 
         // Ajax submits specified in this manner automatically submit to the
diff --git a/core/misc/collapse.js b/core/misc/collapse.js
index 1a98e54..9115dd6 100644
--- a/core/misc/collapse.js
+++ b/core/misc/collapse.js
@@ -98,7 +98,7 @@
       if (Modernizr.details) {
         return;
       }
-      var $collapsibleDetails = $(context).find('details').once('collapse').addClass('collapse-processed');
+      var $collapsibleDetails = $(context).find('details').once('collapse');
       if ($collapsibleDetails.length) {
         for (var i = 0; i < $collapsibleDetails.length; i++) {
           CollapsibleDetails.instances.push(new CollapsibleDetails($collapsibleDetails[i]));
diff --git a/core/misc/drupal.js b/core/misc/drupal.js
index 70ac77d..61d3299 100644
--- a/core/misc/drupal.js
+++ b/core/misc/drupal.js
@@ -111,10 +111,10 @@ if (window.jQuery) {
    * to be processed, in order to allow special behaviors to detach from the
    * content.
    *
-   * 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.
+   * Such implementations should look for the class name that was added in their
+   * corresponding Drupal.behaviors.behaviorName.attach implementation, i.e.
+   * behaviorName-processed, to ensure the behavior is detached only from
+   * previously processed elements.
    *
    * @param context
    *   An element to detach behaviors from. If none is given, the document element
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index d0c6241..9717354 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -225,7 +225,7 @@
     }
     // Trigger an event to allow other scripts to react to this display change.
     // Force the extra parameter as a bool.
-    $('table').findOnce('tabledrag').trigger('columnschange', !!displayWeight);
+    $('table.tabledrag-processed').trigger('columnschange', !!displayWeight);
   };
 
   /**
@@ -250,7 +250,7 @@
    * Undo showColumns().
    */
   Drupal.tableDrag.prototype.hideColumns = function () {
-    var $tables = $('table').findOnce('tabledrag');
+    var $tables = $('table.tabledrag-processed');
     // Hide weight/parent cells and headers.
     $tables.find('.tabledrag-hide').css('display', 'none');
     // Show TableDrag handles.
@@ -268,7 +268,7 @@
    * Undo hideColumns().
    */
   Drupal.tableDrag.prototype.showColumns = function () {
-    var $tables = $('table').findOnce('tabledrag');
+    var $tables = $('table.tabledrag-processed');
     // Show weight/parent cells and headers.
     $tables.find('.tabledrag-hide').css('display', '');
     // Hide TableDrag handles.
diff --git a/core/misc/tableresponsive.js b/core/misc/tableresponsive.js
index 93b7f83..1bf6d07 100644
--- a/core/misc/tableresponsive.js
+++ b/core/misc/tableresponsive.js
@@ -30,7 +30,7 @@
     this.table = table;
     this.$table = $(table);
     this.showText = Drupal.t('Show all columns');
-    this.hideText = Drupal.t('Hide lower priority columns');
+    this.hideText = Drupal.t('Hide unimportant columns');
     // Store a reference to the header elements of the table so that the DOM is
     // traversed only once to find them.
     this.$headers = this.$table.find('th');
diff --git a/core/misc/tableselect.js b/core/misc/tableselect.js
index 8f91d5e..60bb0e1 100644
--- a/core/misc/tableselect.js
+++ b/core/misc/tableselect.js
@@ -5,7 +5,7 @@
   Drupal.behaviors.tableSelect = {
     attach: function (context, settings) {
       // Select the inner-most table in case of nested tables.
-      $(context).find('th.select-all').closest('table').once('table-select').each(Drupal.tableSelect);
+      $(context).find('th.select-all').closest('table').once('table-select', Drupal.tableSelect);
     }
   };
 
diff --git a/core/misc/vertical-tabs.css b/core/misc/vertical-tabs.css
index ec5d3c1..c957450 100644
--- a/core/misc/vertical-tabs.css
+++ b/core/misc/vertical-tabs.css
@@ -1,7 +1,3 @@
-/**
- * @file
- * Vertical Tabs.
- */
 
 .vertical-tabs {
   margin: 1em 0 1em 15em; /* LTR */
@@ -11,7 +7,7 @@
    margin-left: 0;
    margin-right: 15em;
 }
-.vertical-tabs__menu {
+.vertical-tabs-list {
   float: left; /* LTR */
   width: 15em;
   margin: -1px 0 -1px -15em; /* LTR */
@@ -19,50 +15,52 @@
   border-top: 1px solid #ccc;
   list-style: none;
 }
-[dir="rtl"] .vertical-tabs__menu {
+[dir="rtl"] .vertical-tabs-list {
   float: right;
   margin-left: 0;
   margin-right: -15em;
 }
-.vertical-tabs__pane {
+.vertical-tabs-pane {
   margin: 0;
   border: 0;
 }
-.vertical-tabs__pane > summary {
+.vertical-tabs-pane > summary {
   display: none;
 }
 
-/* Layout of each tab. */
-.vertical-tabs__menu-item {
+/* Layout of each tab */
+.vertical-tab-button {
+  margin: 0;
+  padding: 0;
   border: 1px solid #ccc;
   border-top: 0;
   background: #eee;
 }
-.vertical-tabs__menu-item a {
+.vertical-tab-button a {
   display: block;
   padding: 0.5em 0.6em;
   text-decoration: none;
 }
-.vertical-tabs__menu-item a:focus .vertical-tabs__menu-item-title,
-.vertical-tabs__menu-item a:active .vertical-tabs__menu-item-title,
-.vertical-tabs__menu-item a:hover .vertical-tabs__menu-item-title {
+.vertical-tab-button a:focus strong,
+.vertical-tab-button a:active strong,
+.vertical-tab-button a:hover strong {
   text-decoration: underline;
 }
-.vertical-tabs__menu-item a:hover {
+.vertical-tab-button a:hover {
   outline: 1px dotted;
 }
-.vertical-tabs__menu-item.is-selected {
+.vertical-tab-button.selected {
   border-right-width: 0; /* LTR */
   background-color: #fff;
 }
-[dir="rtl"] .vertical-tabs__menu-item.is-selected {
+[dir="rtl"] .vertical-tab-button.selected {
   border-left-width: 0;
   border-right-width: 1px;
 }
-.vertical-tabs__menu-item.is-selected .vertical-tabs__menu-item-title {
+.vertical-tab-button.selected strong {
   color: #000;
 }
-.vertical-tabs__menu-item-summary {
+.vertical-tab-button .summary {
   display: block;
   margin-bottom: 0;
   line-height: normal;
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index faed095..11fca70 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -20,9 +20,9 @@
         return;
       }
 
-      $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs').each(function () {
-        var $this = $(this).addClass('vertical-tabs__panes');
-        var focusID = $this.find(':hidden.vertical-tabs__active-tab').val();
+      $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs', function () {
+        var $this = $(this).addClass('vertical-tabs-panes');
+        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
@@ -32,7 +32,7 @@
         }
 
         // Create the tab column.
-        var tab_list = $('<ul class="vertical-tabs__menu"></ul>');
+        var tab_list = $('<ul class="vertical-tabs-list"></ul>');
         $this.wrap('<div class="vertical-tabs clearfix"></div>').before(tab_list);
 
         // Transform each details into a tab.
@@ -48,7 +48,7 @@
             // prop() can't be used on browsers not supporting details element,
             // the style won't apply to them if prop() is used.
             .attr('open', true)
-            .addClass('vertical-tabs__pane')
+            .addClass('vertical-tabs-pane')
             .data('verticalTab', vertical_tab);
           if (this.id === focusID) {
             tab_focus = $that;
@@ -63,10 +63,10 @@
           // element that matches the URL fragment, activate that tab.
           var $locationHash = $this.find(window.location.hash);
           if (window.location.hash && $locationHash.length) {
-            tab_focus = $locationHash.closest('.vertical-tabs__pane');
+            tab_focus = $locationHash.closest('.vertical-tabs-pane');
           }
           else {
-            tab_focus = $this.find('> .vertical-tabs__pane:first');
+            tab_focus = $this.find('> .vertical-tabs-pane:first');
           }
         }
         if (tab_focus.length) {
@@ -102,7 +102,7 @@
       if (event.keyCode === 13) {
         self.focus();
         // Set focus on the first input field of the visible details/tab pane.
-        $(".vertical-tabs__pane :input:visible:enabled:first").trigger('focus');
+        $(".vertical-tabs-pane :input:visible:enabled:first").trigger('focus');
       }
     });
 
@@ -119,17 +119,17 @@
      */
     focus: function () {
       this.details
-        .siblings('.vertical-tabs__pane')
+        .siblings('.vertical-tabs-pane')
         .each(function () {
           var tab = $(this).data('verticalTab');
           tab.details.hide();
-          tab.item.removeClass('is-selected');
+          tab.item.removeClass('selected');
         })
         .end()
         .show()
-        .siblings(':hidden.vertical-tabs__active-tab')
+        .siblings(':hidden.vertical-tabs-active-tab')
         .val(this.details.attr('id'));
-      this.item.addClass('is-selected');
+      this.item.addClass('selected');
       // Mark the active tab for screen readers.
       $('#active-vertical-tab').remove();
       this.link.append('<span id="active-vertical-tab" class="visually-hidden">' + Drupal.t('(active tab)') + '</span>');
@@ -153,10 +153,10 @@
       // 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')
+      this.item.parent().children('.vertical-tab-button').removeClass('first')
         .filter(':visible:first').addClass('first');
       // Display the details element.
-      this.details.removeClass('vertical-tab--hidden').show();
+      this.details.removeClass('vertical-tab-hidden').show();
       // Focus this tab.
       this.focus();
       return this;
@@ -171,12 +171,12 @@
       // 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')
+      this.item.parent().children('.vertical-tab-button').removeClass('first')
         .filter(':visible:first').addClass('first');
       // Hide the details element.
-      this.details.addClass('vertical-tab--hidden').hide();
+      this.details.addClass('vertical-tab-hidden').hide();
       // Focus the first visible tab (if there is one).
-      var $firstTab = this.details.siblings('.vertical-tabs__pane:not(.vertical-tab--hidden):first');
+      var $firstTab = this.details.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
       if ($firstTab.length) {
         $firstTab.data('verticalTab').focus();
       }
@@ -203,10 +203,10 @@
    */
   Drupal.theme.verticalTab = function (settings) {
     var tab = {};
-    tab.item = $('<li class="vertical-tabs__menu-item" tabindex="-1"></li>')
+    tab.item = $('<li class="vertical-tab-button" tabindex="-1"></li>')
       .append(tab.link = $('<a href="#"></a>')
-        .append(tab.title = $('<strong class="vertical-tabs__menu-item-title"></strong>').text(settings.title))
-        .append(tab.summary = $('<span class="vertical-tabs__menu-item-summary"></span>')
+        .append(tab.title = $('<strong></strong>').text(settings.title))
+        .append(tab.summary = $('<span class="summary"></span>')
         )
       );
     return tab;
diff --git a/core/modules/aggregator/config/optional/views.view.aggregator_rss_feed.yml b/core/modules/aggregator/config/install/views.view.aggregator_rss_feed.yml
similarity index 100%
rename from core/modules/aggregator/config/optional/views.view.aggregator_rss_feed.yml
rename to core/modules/aggregator/config/install/views.view.aggregator_rss_feed.yml
diff --git a/core/modules/aggregator/config/optional/views.view.aggregator_sources.yml b/core/modules/aggregator/config/install/views.view.aggregator_sources.yml
similarity index 100%
rename from core/modules/aggregator/config/optional/views.view.aggregator_sources.yml
rename to core/modules/aggregator/config/install/views.view.aggregator_sources.yml
diff --git a/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php b/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php
index d2092a3..539e349 100644
--- a/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php
+++ b/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php
@@ -96,6 +96,13 @@ public function defaultConfiguration() {
     return array(
       'block_count' => 10,
       'feed' => NULL,
+      // Modify the default max age for the 'Aggregator Feed' blocks:
+      // modifications made to feeds or feed items will automatically invalidate
+      // corresponding cache tags, therefore allowing us to cache these blocks
+      // forever.
+      'cache' => array(
+        'max_age' => \Drupal\Core\Cache\Cache::PERMANENT,
+      ),
     );
   }
 
diff --git a/core/modules/aggregator/src/Plugin/views/argument/Fid.php b/core/modules/aggregator/src/Plugin/views/argument/Fid.php
index 7561694..f9d2481 100644
--- a/core/modules/aggregator/src/Plugin/views/argument/Fid.php
+++ b/core/modules/aggregator/src/Plugin/views/argument/Fid.php
@@ -8,7 +8,7 @@
 namespace Drupal\aggregator\Plugin\views\argument;
 
 use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Drupal\Component\Utility\String;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -19,7 +19,7 @@
  *
  * @ViewsArgument("aggregator_fid")
  */
-class Fid extends NumericArgument {
+class Fid extends Numeric {
 
   /**
    * The entity manager service.
diff --git a/core/modules/aggregator/src/Plugin/views/argument/Iid.php b/core/modules/aggregator/src/Plugin/views/argument/Iid.php
index 1c95afa..7fca201 100644
--- a/core/modules/aggregator/src/Plugin/views/argument/Iid.php
+++ b/core/modules/aggregator/src/Plugin/views/argument/Iid.php
@@ -8,7 +8,7 @@
 namespace Drupal\aggregator\Plugin\views\argument;
 
 use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Drupal\Component\Utility\String;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -19,7 +19,7 @@
  *
  * @ViewsArgument("aggregator_iid")
  */
-class Iid extends NumericArgument {
+class Iid extends Numeric {
 
   /**
    * The entity manager service.
diff --git a/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php b/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php
index 5790294..44c14f1 100644
--- a/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php
+++ b/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php
@@ -145,7 +145,7 @@ function testPerUserLoginFloodControl() {
    */
   function testLocale() {
     ConfigurableLanguage::createFromLangcode('de')->save();
-    $this->config('system.site')->set('default_langcode', 'de')->save();
+    $this->config('system.site')->set('langcode', 'de')->save();
 
     $account = $this->drupalCreateUser();
     $url = Url::fromRoute('router_test.11');
diff --git a/core/modules/block/js/block.admin.js b/core/modules/block/js/block.admin.js
index 89739c7..422a83a 100644
--- a/core/modules/block/js/block.admin.js
+++ b/core/modules/block/js/block.admin.js
@@ -74,7 +74,7 @@
   Drupal.behaviors.blockHighlightPlacement = {
     attach: function (context, settings) {
       if (settings.blockPlacement) {
-        $('#blocks').once('block-highlight').each(function () {
+        $('#blocks').once('block-highlight', function () {
           var $container = $(this);
           // Just scrolling the document.body will not work in Firefox. The html
           // element is needed as well.
diff --git a/core/modules/block/js/block.js b/core/modules/block/js/block.js
index 2b727c4..c25842f 100644
--- a/core/modules/block/js/block.js
+++ b/core/modules/block/js/block.js
@@ -91,7 +91,7 @@
       };
 
       // Add the behavior to each region select list.
-      $(context).find('select.block-region-select').once('block-region-select').each(function () {
+      $(context).find('select.block-region-select').once('block-region-select', function () {
         $(this).on('change', function (event) {
           // Make our new row and select field.
           var row = $(this).closest('tr');
diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php
index 08d7508..3ff21f6 100644
--- a/core/modules/block/src/BlockForm.php
+++ b/core/modules/block/src/BlockForm.php
@@ -247,7 +247,6 @@ protected function buildVisibilityInterface(array $form, FormStateInterface $for
     if (isset($form['request_path'])) {
       $form['request_path']['#title'] = $this->t('Pages');
       $form['request_path']['negate']['#type'] = 'radios';
-      $form['request_path']['negate']['#default_value'] = (int) $form['request_path']['negate']['#default_value'];
       $form['request_path']['negate']['#title_display'] = 'invisible';
       $form['request_path']['negate']['#options'] = [
         $this->t('Show for the listed pages'),
@@ -297,13 +296,6 @@ public function validate(array $form, FormStateInterface $form_state) {
   protected function validateVisibility(array $form, FormStateInterface $form_state) {
     // Validate visibility condition settings.
     foreach ($form_state->getValue('visibility') as $condition_id => $values) {
-      // All condition plugins use 'negate' as a Boolean in their schema.
-      // However, certain form elements may return it as 0/1. Cast here to
-      // ensure the data is in the expected type.
-      if (array_key_exists('negate', $values)) {
-        $values['negate'] = (bool) $values['negate'];
-      }
-
       // Allow the condition to validate the form.
       $condition = $form_state->get(['conditions', $condition_id]);
       $condition_values = (new FormState())
diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php
index 1c1ce7b..8430393 100644
--- a/core/modules/block/src/BlockViewBuilder.php
+++ b/core/modules/block/src/BlockViewBuilder.php
@@ -36,12 +36,6 @@ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = N
    * {@inheritdoc}
    */
   public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
-    // @todo Remove when https://www.drupal.org/node/2453059 lands.
-    $default_cache_contexts = [
-      'languages',
-      'theme',
-    ];
-
     /** @var \Drupal\block\BlockInterface[] $entities */
     $build = array();
     foreach ($entities as  $entity) {
@@ -69,20 +63,21 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
         '#base_plugin_id' => $base_id,
         '#derivative_plugin_id' => $derivative_id,
         '#id' => $entity->id(),
-        '#cache' => [
-          'contexts' => Cache::mergeContexts($default_cache_contexts, $plugin->getCacheContexts()),
-          'tags' => Cache::mergeTags(
-            $this->getCacheTags(), // Block view builder cache tag.
-            $entity->getCacheTags(), // Block entity cache tag.
-            $plugin->getCacheTags() // Block plugin cache tags.
-          ),
-          'max-age' => $plugin->getCacheMaxAge(),
-        ],
         // Add the entity so that it can be used in the #pre_render method.
         '#block' => $entity,
       );
       $build[$entity_id]['#configuration']['label'] = String::checkPlain($configuration['label']);
 
+      // Set cache tags; these always need to be set, whether the block is
+      // cacheable or not, so that the page cache is correctly informed.
+      $build[$entity_id]['#cache']['tags'] = Cache::mergeTags(
+        $this->getCacheTags(), // Block view builder cache tag.
+        $entity->getCacheTags(), // Block entity cache tag.
+        $plugin->getCacheTags() // Block plugin cache tags.
+      );
+
+      $build[$entity_id]['#cache']['max-age'] = $plugin->getCacheMaxAge();
+
       if ($plugin->isCacheable()) {
         $build[$entity_id]['#pre_render'][] = array($this, 'buildBlock');
         // Generic cache keys, with the block plugin's custom keys appended.
@@ -91,7 +86,16 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
           'block',
           $entity->id(),
         );
-        $build[$entity_id]['#cache']['keys'] = array_merge($default_cache_keys, $plugin->getCacheKeys());
+        $default_cache_contexts = array(
+          'language',
+          'theme',
+        );
+        $max_age = $plugin->getCacheMaxAge();
+        $build[$entity_id]['#cache'] += array(
+          'keys' => array_merge($default_cache_keys, $plugin->getCacheKeys()),
+          'contexts' => array_merge($default_cache_contexts, $plugin->getCacheContexts()),
+          'expire' => ($max_age === Cache::PERMANENT) ? Cache::PERMANENT : REQUEST_TIME + $max_age,
+        );
       }
       else {
         $build[$entity_id] = $this->buildBlock($build[$entity_id]);
diff --git a/core/modules/block/src/Tests/BlockCacheTest.php b/core/modules/block/src/Tests/BlockCacheTest.php
index 5165149..615751d 100644
--- a/core/modules/block/src/Tests/BlockCacheTest.php
+++ b/core/modules/block/src/Tests/BlockCacheTest.php
@@ -75,7 +75,10 @@ protected function setUp() {
    * Test "user.roles" cache context.
    */
   function testCachePerRole() {
-    \Drupal::state()->set('block_test.cache_contexts', ['user.roles']);
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+      'contexts' => array('user.roles'),
+    ));
 
     // Enable our test block. Set some content for it to display.
     $current_content = $this->randomMachineName();
@@ -122,7 +125,9 @@ function testCachePerRole() {
    * Test a cacheable block without any cache context.
    */
   function testCacheGlobal() {
-    \Drupal::state()->set('block_test.cache_contexts', []);
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+    ));
 
     $current_content = $this->randomMachineName();
     \Drupal::state()->set('block_test.content', $current_content);
@@ -165,7 +170,10 @@ function testNoCache() {
    * Test "user" cache context.
    */
   function testCachePerUser() {
-    \Drupal::state()->set('block_test.cache_contexts', ['user']);
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+      'contexts' => array('user'),
+    ));
 
     $current_content = $this->randomMachineName();
     \Drupal::state()->set('block_test.content', $current_content);
@@ -194,7 +202,10 @@ function testCachePerUser() {
    * Test "url" cache context.
    */
   function testCachePerPage() {
-    \Drupal::state()->set('block_test.cache_contexts', ['url']);
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+      'contexts' => array('url'),
+    ));
 
     $current_content = $this->randomMachineName();
     \Drupal::state()->set('block_test.content', $current_content);
diff --git a/core/modules/block/src/Tests/BlockInterfaceTest.php b/core/modules/block/src/Tests/BlockInterfaceTest.php
index b54746e..08980c5 100644
--- a/core/modules/block/src/Tests/BlockInterfaceTest.php
+++ b/core/modules/block/src/Tests/BlockInterfaceTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\block\Tests;
 
 use Drupal\Component\Utility\String;
-use Drupal\Core\Cache\Cache;
 use Drupal\Core\Form\FormState;
 use Drupal\simpletest\KernelTestBase;
 use Drupal\block\BlockInterface;
@@ -46,7 +45,8 @@ public function testBlockInterface() {
       'provider' => 'block_test',
       'label_display' => BlockInterface::BLOCK_LABEL_VISIBLE,
       'cache' => array(
-        'max_age' => Cache::PERMANENT,
+        'max_age' => 0,
+        'contexts' => array(),
       ),
       'display_message' => 'no message set',
     );
@@ -65,6 +65,9 @@ public function testBlockInterface() {
     $period = array_map(array(\Drupal::service('date.formatter'), 'formatInterval'), array_combine($period, $period));
     $period[0] = '<' . t('no caching') . '>';
     $period[\Drupal\Core\Cache\Cache::PERMANENT] = t('Forever');
+    $contexts = \Drupal::service("cache_contexts")->getLabels();
+    unset($contexts['theme']);
+    unset($contexts['language']);
     $expected_form = array(
       'provider' => array(
         '#type' => 'value',
@@ -95,9 +98,21 @@ public function testBlockInterface() {
           '#type' => 'select',
           '#title' => t('Maximum age'),
           '#description' => t('The maximum time this block may be cached.'),
-          '#default_value' => Cache::PERMANENT,
+          '#default_value' => 0,
           '#options' => $period,
         ),
+        'contexts' => array(
+          '#type' => 'checkboxes',
+          '#title' => t('Vary by context'),
+          '#description' => t('The contexts this cached block must be varied by. <em>All</em> blocks are varied by language and theme.'),
+          '#default_value' => array(),
+          '#options' => $contexts,
+          '#states' => array(
+            'disabled' => array(
+              ':input[name="settings[cache][max_age]"]' => array('value' => (string) 0),
+            ),
+          ),
+        ),
       ),
       'display_message' => array(
         '#type' => 'textfield',
diff --git a/core/modules/block/src/Tests/BlockStorageUnitTest.php b/core/modules/block/src/Tests/BlockStorageUnitTest.php
index f1d435a..ff4ba29 100644
--- a/core/modules/block/src/Tests/BlockStorageUnitTest.php
+++ b/core/modules/block/src/Tests/BlockStorageUnitTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\block\Tests;
 
-use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\Entity\ConfigEntityStorage;
 use Drupal\simpletest\KernelTestBase;
 use Drupal\block_test\Plugin\Block\TestHtmlBlock;
@@ -100,7 +99,8 @@ protected function createTests() {
         'provider' => 'block_test',
         'label_display' => BlockInterface::BLOCK_LABEL_VISIBLE,
         'cache' => array(
-          'max_age' => Cache::PERMANENT,
+          'max_age' => 0,
+          'contexts' => array(),
         ),
       ),
       'visibility' => array(),
@@ -149,7 +149,6 @@ protected function deleteTests() {
    * Tests the installation of default blocks.
    */
   public function testDefaultBlocks() {
-    \Drupal::service('theme_handler')->install(['classy']);
     $entities = $this->controller->loadMultiple();
     $this->assertTrue(empty($entities), 'There are no blocks initially.');
 
diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php
index 94283c4..e6709da 100644
--- a/core/modules/block/src/Tests/BlockTest.php
+++ b/core/modules/block/src/Tests/BlockTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\block\Tests;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Cache\Cache;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Component\Utility\String;
 use Drupal\block\Entity\Block;
@@ -39,15 +40,9 @@ function testBlockVisibility() {
     $edit['visibility[request_path][pages]'] = 'user*';
     $edit['visibility[request_path][negate]'] = TRUE;
     $edit['visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']'] = TRUE;
-    $this->drupalGet('admin/structure/block/add/' . $block_name . '/' . $default_theme);
-    $this->assertFieldChecked('edit-visibility-request-path-negate-0');
-
-    $this->drupalPostForm(NULL, $edit, t('Save block'));
+    $this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
     $this->assertText('The block configuration has been saved.', 'Block was saved');
 
-    $this->clickLink('Configure');
-    $this->assertFieldChecked('edit-visibility-request-path-negate-1');
-
     $this->drupalGet('');
     $this->assertText($title, 'Block was displayed on the front page.');
 
@@ -319,7 +314,7 @@ public function testBlockCacheTags() {
     $config->save();
 
     // Place the "Powered by Drupal" block.
-    $block = $this->drupalPlaceBlock('system_powered_by_block', array('id' => 'powered'));
+    $block = $this->drupalPlaceBlock('system_powered_by_block', array('id' => 'powered', 'cache' => array('max_age' => 315360000)));
 
     // Prime the page cache.
     $this->drupalGet('<front>');
@@ -360,7 +355,7 @@ public function testBlockCacheTags() {
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
 
     // Place the "Powered by Drupal" block another time; verify a cache miss.
-    $block_2 = $this->drupalPlaceBlock('system_powered_by_block', array('id' => 'powered-2'));
+    $block_2 = $this->drupalPlaceBlock('system_powered_by_block', array('id' => 'powered-2', 'cache' => array('max_age' => 315360000)));
     $this->drupalGet('<front>');
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
 
diff --git a/core/modules/block/src/Tests/BlockViewBuilderTest.php b/core/modules/block/src/Tests/BlockViewBuilderTest.php
index 02fec0f..e0ee522 100644
--- a/core/modules/block/src/Tests/BlockViewBuilderTest.php
+++ b/core/modules/block/src/Tests/BlockViewBuilderTest.php
@@ -149,6 +149,15 @@ protected function verifyRenderCacheHandling() {
     $request_method = $request->server->get('REQUEST_METHOD');
     $request->setMethod('GET');
 
+    // Test that entities with caching disabled do not generate a cache entry.
+    $build = $this->getBlockRenderArray();
+    $this->assertTrue(isset($build['#cache']) && array_keys($build['#cache']) == array('tags', 'max-age'), 'The render array element of uncacheable blocks is not cached, but does have cache tags & max-age set.');
+
+    // Enable block caching.
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+    ));
+
     // Test that a cache entry is created.
     $build = $this->getBlockRenderArray();
     $cid = 'entity_view:block:test_block:en:core';
@@ -185,10 +194,19 @@ public function testBlockViewBuilderAlter() {
 
     // Enable the block view alter hook that adds a suffix, for basic testing.
     \Drupal::state()->set('block_test_view_alter_suffix', TRUE);
-    Cache::invalidateTags($this->block->getCacheTags());
+
+    // Basic: non-empty block.
     $build = $this->getBlockRenderArray();
     $this->assertTrue(isset($build['#suffix']) && $build['#suffix'] === '<br>Goodbye!', 'A block with content is altered.');
     $this->assertIdentical(drupal_render($build), 'Llamas &gt; unicorns!<br>Goodbye!');
+
+    // Basic: empty block.
+    \Drupal::state()->set('block_test.content', NULL);
+    $build = $this->getBlockRenderArray();
+    $this->assertTrue(isset($build['#suffix']) && $build['#suffix'] === '<br>Goodbye!', 'A block without content is altered.');
+    $this->assertIdentical(drupal_render($build), '<br>Goodbye!');
+
+    // Disable the block view alter hook that adds a suffix, for basic testing.
     \Drupal::state()->set('block_test_view_alter_suffix', FALSE);
 
     // Force a request via GET so we can get drupal_render() cache working.
@@ -196,13 +214,13 @@ public function testBlockViewBuilderAlter() {
     $request_method = $request->server->get('REQUEST_METHOD');
     $request->setMethod('GET');
 
-    \Drupal::state()->set('block_test.content', NULL);
-    Cache::invalidateTags($this->block->getCacheTags());
-
     $default_keys = array('entity_view', 'block', 'test_block');
     $default_tags = array('block_view', 'config:block.block.test_block');
 
     // Advanced: cached block, but an alter hook adds an additional cache key.
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+    ));
     $alter_add_key = $this->randomMachineName();
     \Drupal::state()->set('block_test_view_alter_cache_key', $alter_add_key);
     $cid = 'entity_view:block:test_block:' . $alter_add_key . ':en:core';
@@ -245,6 +263,75 @@ public function testBlockViewBuilderAlter() {
   }
 
   /**
+   * Tests block render cache handling with configurable cache contexts.
+   *
+   * This is only intended to test that an existing block can be configured with
+   * additional contexts, not to test that each context works correctly.
+   *
+   * @see \Drupal\block\Tests\BlockCacheTest
+   */
+  public function testBlockViewBuilderCacheContexts() {
+    $cache_contexts = \Drupal::service("cache_contexts");
+
+    // Force a request via GET so we can get drupal_render() cache working.
+    $request = \Drupal::request();
+    $request_method = $request->server->get('REQUEST_METHOD');
+    $request->setMethod('GET');
+
+    // First: no cache context.
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+    ));
+    $build = $this->getBlockRenderArray();
+    $cid = implode(':', $build['#cache']['keys']);
+    drupal_render($build);
+    $this->assertTrue($this->container->get('cache.render', $cid), 'The block render element has been cached.');
+
+    // Second: the "per URL" cache context.
+    $this->setBlockCacheConfig(array(
+      'max_age' => 600,
+      'contexts' => array('url'),
+    ));
+    $old_cid = $cid;
+    $build = $this->getBlockRenderArray();
+    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts->convertTokensToKeys($build['#cache']['contexts']));
+    $cid = implode(':', $cid_parts);
+    drupal_render($build);
+    $this->assertTrue($this->container->get('cache.render', $cid), 'The block render element has been cached.');
+    $this->assertNotEqual($cid, $old_cid, 'The cache ID has changed.');
+
+    // Third: the same block configuration, but a different URL.
+    $original_url_cache_context = $this->container->get('cache_context.url');
+    $request_stack = new RequestStack();
+    $request_stack->push(Request::create('/foo'));
+    $temp_context = new UrlCacheContext($request_stack);
+    $this->container->set('cache_context.url', $temp_context);
+    $old_cid = $cid;
+    $build = $this->getBlockRenderArray();
+    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts->convertTokensToKeys($build['#cache']['contexts']));
+    $cid = implode(':', $cid_parts);
+    drupal_render($build);
+    $this->assertTrue($this->container->get('cache.render', $cid), 'The block render element has been cached.');
+    $this->assertNotEqual($cid, $old_cid, 'The cache ID has changed.');
+    $this->container->set('cache_context.url', $original_url_cache_context);
+
+    // Restore the previous request method.
+    $request->setMethod($request_method);
+  }
+
+  /**
+   * Sets the test block's cache configuration.
+   *
+   * @param array $cache_config
+   *   The desired cache configuration.
+   */
+  protected function setBlockCacheConfig(array $cache_config) {
+    $block = $this->block->getPlugin();
+    $block->setConfigurationValue('cache', $cache_config);
+    $this->block->save();
+  }
+
+  /**
    * Get a fully built render array for a block.
    *
    * @return array
diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
index d424853..9e6c8c3 100644
--- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
@@ -273,7 +273,7 @@ public function testBlockRendering() {
   public function testBlockContextualLinks() {
     $this->drupalLogin($this->drupalCreateUser(array('administer views', 'access contextual links', 'administer blocks')));
     $block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
-    $cached_block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
+    $cached_block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array('cache' => array('max_age' => 3600)));
     $this->drupalGet('test-page');
 
     $id = 'block:block=' . $block->id() . ':|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1';
diff --git a/core/modules/block/tests/modules/block_test/block_test.info.yml b/core/modules/block/tests/modules/block_test/block_test.info.yml
index fceed36..9a8895f 100644
--- a/core/modules/block/tests/modules/block_test/block_test.info.yml
+++ b/core/modules/block/tests/modules/block_test/block_test.info.yml
@@ -4,5 +4,3 @@ description: 'Provides test blocks.'
 package: Testing
 version: VERSION
 core: 8.x
-dependencies:
-  - block
diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestCacheBlock.php b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestCacheBlock.php
index abe4cc7..815f3a4 100644
--- a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestCacheBlock.php
+++ b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestCacheBlock.php
@@ -32,11 +32,4 @@ public function build() {
     return $build;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return \Drupal::state()->get('block_test.cache_contexts', []);
-  }
-
 }
diff --git a/core/modules/block_content/config/schema/block_content.views.schema.yml b/core/modules/block_content/config/schema/block_content.views.schema.yml
new file mode 100644
index 0000000..af39d53
--- /dev/null
+++ b/core/modules/block_content/config/schema/block_content.views.schema.yml
@@ -0,0 +1,18 @@
+# Schema for the views plugins of the Block Content module.
+
+# @todo Fix this when https://www.drupal.org/node/2322949 is fixed.
+views.field.block_content:
+  type: views_field
+  label: 'Block Content'
+  mapping:
+    link_to_entity:
+      type: boolean
+      label: 'Link this field to the original piece of block content'
+
+views.field.block_content_type:
+  type: views.field.block_content
+  label: 'Block content type'
+  mapping:
+    machine_name:
+      type: string
+      label: 'Output machine name'
diff --git a/core/modules/block_content/src/BlockContentViewsData.php b/core/modules/block_content/src/BlockContentViewsData.php
index b79b53d..200d18f 100644
--- a/core/modules/block_content/src/BlockContentViewsData.php
+++ b/core/modules/block_content/src/BlockContentViewsData.php
@@ -21,12 +21,12 @@ public function getViewsData() {
 
     $data = parent::getViewsData();
 
-    $data['block_content_field_data']['id']['field']['id'] = 'field';
+    $data['block_content_field_data']['id']['field']['id'] = 'block_content';
 
-    $data['block_content_field_data']['info']['field']['id'] = 'field';
+    $data['block_content_field_data']['info']['field']['id'] = 'block_content';
     $data['block_content_field_data']['info']['field']['link_to_entity default'] = TRUE;
 
-    $data['block_content_field_data']['type']['field']['id'] = 'field';
+    $data['block_content_field_data']['type']['field']['id'] = 'block_content_type';
 
     // @todo Figure out the way to integrate this automatic in
     //   content_translation https://www.drupal.org/node/2410261.
diff --git a/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
index 1525723..e59eefd 100644
--- a/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
+++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
@@ -98,6 +98,12 @@ public function defaultConfiguration() {
       'status' => TRUE,
       'info' => '',
       'view_mode' => 'full',
+      // Modify the default max age for custom block blocks: modifications made
+      // to them will automatically invalidate corresponding cache tags, thus
+      // allowing us to cache custom block blocks forever.
+      'cache' => array(
+        'max_age' => \Drupal\Core\Cache\Cache::PERMANENT,
+      ),
     );
   }
 
diff --git a/core/modules/block_content/src/Plugin/views/field/BlockContent.php b/core/modules/block_content/src/Plugin/views/field/BlockContent.php
new file mode 100644
index 0000000..03baa24
--- /dev/null
+++ b/core/modules/block_content/src/Plugin/views/field/BlockContent.php
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_content\Plugin\views\field\BlockContent.
+ */
+
+namespace Drupal\block_content\Plugin\views\field;
+
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\views\ResultRow;
+use Drupal\views\ViewExecutable;
+use Drupal\views\Plugin\views\display\DisplayPluginBase;
+use Drupal\views\Plugin\views\field\FieldPluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Field handler to provide simple renderer that allows linking to a block_content.
+ * Definition terms:
+ * - link_to_entity default: Should this field have the checkbox
+ *   "link to entity" enabled by default.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("block_content")
+ */
+class BlockContent extends FieldPluginBase {
+
+  /**
+   * The language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * Constructs a new BlockContent.
+   *
+   * @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\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The language manager.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->languageManager = $language_manager;
+    $this->entityManager = $entity_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('language_manager'),
+      $container->get('entity.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
+    parent::init($view, $display, $options);
+
+    // Don't add the additional fields to groupby
+    if (!empty($this->options['link_to_entity'])) {
+      $this->additional_fields['id'] = array('table' => 'block_content', 'field' => 'id');
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    $options['link_to_entity'] = array('default' => isset($this->definition['link_to_entity default']) ? $this->definition['link_to_entity default'] : FALSE);
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+    $form['link_to_entity'] = array(
+      '#title' => $this->t('Link this field to the original piece of block content'),
+      '#description' => $this->t("Enable to override this field's links."),
+      '#type' => 'checkbox',
+      '#default_value' => !empty($this->options['link_to_entity']),
+    );
+
+    parent::buildOptionsForm($form, $form_state);
+  }
+
+  /**
+   * Prepares link to the block_content.
+   *
+   * @param string $data
+   *   The XSS safe string for the link text.
+   * @param \Drupal\views\ResultRow $values
+   *   The values retrieved from a single row of a view's query result.
+   *
+   * @return string
+   *   Returns a string for the link text.
+   */
+  protected function renderLink($data, ResultRow $values) {
+    if (!empty($this->options['link_to_entity']) && !empty($this->additional_fields['id'])) {
+      if ($data !== NULL && $data !== '') {
+        $id = $this->getValue($values, 'id');
+        $block_content = $this->entityManager->getStorage('block_content')->load($id);
+        $this->options['alter']['make_link'] = TRUE;
+        $this->options['alter']['path'] = $block_content->url();
+        if (isset($this->aliases['langcode'])) {
+          $languages = $this->languageManager->getLanguages();
+          $langcode = $this->getValue($values, 'langcode');
+          if (isset($languages[$langcode])) {
+            $this->options['alter']['language'] = $languages[$langcode];
+          }
+          else {
+            unset($this->options['alter']['language']);
+          }
+        }
+      }
+      else {
+        $this->options['alter']['make_link'] = FALSE;
+      }
+    }
+    return $data;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render(ResultRow $values) {
+    $value = $this->getValue($values);
+    return $this->renderLink($this->sanitizeValue($value), $values);
+  }
+
+}
diff --git a/core/modules/block_content/src/Plugin/views/field/Type.php b/core/modules/block_content/src/Plugin/views/field/Type.php
new file mode 100644
index 0000000..969d084
--- /dev/null
+++ b/core/modules/block_content/src/Plugin/views/field/Type.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_content\Plugin\views\field\Type.
+ */
+
+namespace Drupal\block_content\Plugin\views\field;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\views\ResultRow;
+
+/**
+ * Field handler to translate a block content type into its readable form.
+ *
+ * @todo Remove this when https://www.drupal.org/node/2363811 is fixed.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("block_content_type")
+ */
+class Type extends BlockContent {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    $options['machine_name'] = array('default' => FALSE);
+
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+    parent::buildOptionsForm($form, $form_state);
+
+    $form['machine_name'] = array(
+      '#title' => $this->t('Output machine name'),
+      '#description' => $this->t('Display field as the block content type machine name.'),
+      '#type' => 'checkbox',
+      '#default_value' => !empty($this->options['machine_name']),
+    );
+  }
+
+  /**
+   * Renders block content type name.
+   *
+   * @param string $data
+   *   The block content type machine_name.
+   * @param \Drupal\views\ResultRow $values
+   *   The values retrieved from a single row of a view's query result.
+   *
+   * @return string
+   *   The block content type as human readable name or machine_name.
+   */
+  public function renderName($data, ResultRow $values) {
+    if ($this->options['machine_name'] != 1 && $data !== NULL && $data !== '') {
+      $type = $this->entityManager->getStorage('block_content_type')->load($data);
+      return $type ? $this->t($this->sanitizeValue($type->label())) : '';
+    }
+    return $this->sanitizeValue($data);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render(ResultRow $values) {
+    $value = $this->getValue($values);
+    return $this->renderLink($this->renderName($value, $values), $values);
+  }
+
+}
diff --git a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php
index 5629039..16921ba 100644
--- a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php
@@ -64,7 +64,7 @@ protected function getAdditionalCacheTagsForEntity(EntityInterface $entity) {
    * Tests that the block is cached with the correct contexts and tags.
    */
   public function testBlock() {
-    $block = $this->drupalPlaceBlock('block_content:' . $this->entity->uuid());
+    $block = $this->drupalPlaceBlock('block_content:' . $this->entity->uuid(), ['cache' => []]);
     $build = $this->container->get('entity.manager')->getViewBuilder('block')->view($block, 'block');
 
     // Render the block.
@@ -80,7 +80,7 @@ public function testBlock() {
     // Expected keys, contexts, and tags for the block.
     // @see \Drupal\block\BlockViewBuilder::viewMultiple()
     $expected_block_cache_keys = ['entity_view', 'block', $block->id()];
-    $expected_block_cache_contexts = ['languages', 'theme'];
+    $expected_block_cache_contexts = ['language', 'theme'];
     $expected_block_cache_tags = Cache::mergeTags(['block_view', 'rendered'], $block->getCacheTags(), $block->getPlugin()->getCacheTags());
 
     // Expected contexts and tags for the BlockContent entity.
diff --git a/core/modules/block_content/src/Tests/BlockContentPageViewTest.php b/core/modules/block_content/src/Tests/BlockContentPageViewTest.php
index 0564c60..90adab7 100644
--- a/core/modules/block_content/src/Tests/BlockContentPageViewTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentPageViewTest.php
@@ -19,7 +19,7 @@ class BlockContentPageViewTest extends BlockContentTestBase {
    *
    * @var array
    */
-  public static $modules = array('block_content_test');
+  public static $modules = array('block', 'block_content', 'block_content_test');
 
   /**
    * Checks block edit and fallback functionality.
diff --git a/core/modules/block_content/src/Tests/Views/FieldTypeTest.php b/core/modules/block_content/src/Tests/Views/FieldTypeTest.php
index 98f2aee..301fa45 100644
--- a/core/modules/block_content/src/Tests/Views/FieldTypeTest.php
+++ b/core/modules/block_content/src/Tests/Views/FieldTypeTest.php
@@ -27,11 +27,11 @@ public function testFieldType() {
     $block_content = $this->createBlockContent();
     $expected_result[] = array(
       'id' => $block_content->id(),
-      'type' => $block_content->bundle(),
+      'block_content_field_data_type' => $block_content->bundle(),
     );
     $column_map = array(
       'id' => 'id',
-      'type:target_id' => 'type',
+      'block_content_field_data_type' => 'block_content_field_data_type',
     );
 
     $view = Views::getView('test_field_type');
diff --git a/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml b/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml
index 16e4bc7..747efa4 100644
--- a/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml
+++ b/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml
@@ -4,5 +4,3 @@ description: "Support module for custom block related testing."
 package: Testing
 version: VERSION
 core: 8.x
-dependencies:
-  - block_content
diff --git a/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml b/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml
index 42858f7..ed83291 100644
--- a/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml
+++ b/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml
@@ -4,7 +4,7 @@ dependencies:
   module:
     - block_content
   theme:
-    - classy
+    - stark
 id: foobargorilla
 theme: classy
 region: content
@@ -16,6 +16,9 @@ settings:
   label: 'Foobar Gorilla'
   provider: block_content
   label_display: visible
+  cache:
+    max_age: -1
+    contexts: {  }
   status: true
   info: ''
   view_mode: default
diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml
index efcabc3..f2158b7 100644
--- a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml
+++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml
@@ -41,7 +41,7 @@ display:
           table: block_content
           field: id
           relationship: id
-          plugin_id: field
+          plugin_id: block_content
           entity_type: block_content
           entity_field: id
       arguments:
diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml
index 566f2c5..e812ec2 100644
--- a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml
+++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml
@@ -43,7 +43,7 @@ display:
           table: block_content
           field: id
           relationship: revision_id
-          plugin_id: field
+          plugin_id: block_content
           entity_type: block_content
           entity_field: id
       arguments:
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 cbd4511..2e12c10 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
@@ -116,7 +116,8 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          plugin_id: field
+          link_to_entity: false
+          plugin_id: block_content
           entity_type: block_content
           entity_field: id
       sorts:
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 52c52a5..057cd61 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
@@ -71,6 +71,7 @@ display:
             html: false
           hide_empty: false
           empty_zero: false
+          link_to_entity: true
           relationship: none
           group_type: group
           admin_label: ''
@@ -86,11 +87,8 @@ display:
           empty: ''
           hide_alter_empty: true
           entity_type: block_content
-          type: string
-          settings:
-            link_to_entity: true
           entity_field: title
-          plugin_id: field
+          plugin_id: block_content
       filters:
         info:
           id: info
diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml
index 9cccd50..64d649f 100644
--- a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml
+++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml
@@ -19,7 +19,7 @@ display:
           field: type
           id: type
           table: block_content_field_data
-          plugin_id: field
+          plugin_id: block_content_type
           entity_type: block_content
           entity_field: type
     display_plugin: default
diff --git a/core/modules/book/book.services.yml b/core/modules/book/book.services.yml
index 89b25fc..440d021 100644
--- a/core/modules/book/book.services.yml
+++ b/core/modules/book/book.services.yml
@@ -23,7 +23,7 @@ services:
     arguments: ['@book.manager']
     tags:
       - { name: access_check, applies_to: _access_book_removable }
-  cache_context.route.book_navigation:
+  cache_context.book.navigation:
     class: Drupal\book\Cache\BookNavigationCacheContext
     arguments: ['@request_stack']
     tags:
diff --git a/core/modules/book/config/install/core.entity_view_mode.node.print.yml b/core/modules/book/config/install/core.entity_view_mode.node.print.yml
index de47b0c..512d581 100644
--- a/core/modules/book/config/install/core.entity_view_mode.node.print.yml
+++ b/core/modules/book/config/install/core.entity_view_mode.node.print.yml
@@ -5,8 +5,4 @@ cache: true
 targetEntityType: node
 dependencies:
   module:
-    - book
     - node
-  enforced:
-    module:
-      - book
diff --git a/core/modules/book/src/Plugin/Block/BookNavigationBlock.php b/core/modules/book/src/Plugin/Block/BookNavigationBlock.php
index 30153be..4ce4c3f 100644
--- a/core/modules/book/src/Plugin/Block/BookNavigationBlock.php
+++ b/core/modules/book/src/Plugin/Block/BookNavigationBlock.php
@@ -181,22 +181,13 @@ public function build() {
   /**
    * {@inheritdoc}
    */
-  public function getCacheContexts() {
+  protected function getRequiredCacheContexts() {
     // The "Book navigation" block must be cached per role and book navigation
     // context.
     return [
       'user.roles',
-      'route.book_navigation',
+      'book.navigation',
     ];
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Make cacheable as part of https://drupal.org/node/1805054
-   */
-  public function getCacheMaxAge() {
-    return 0;
-  }
-
 }
diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js
index ff75541..e3dbf2b 100644
--- a/core/modules/ckeditor/js/ckeditor.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.admin.js
@@ -11,8 +11,8 @@
   Drupal.behaviors.ckeditorAdmin = {
     attach: function (context) {
       // Process the CKEditor configuration fragment once.
-      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration').once('ckeditor-configuration');
-      if ($configurationForm.length) {
+      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration');
+      if ($configurationForm.once('ckeditor-configuration').length) {
         var $textarea = $configurationForm
           // Hide the textarea that contains the serialized representation of the
           // CKEditor configuration.
@@ -55,7 +55,7 @@
       // really means that all CKEditor toolbar buttons have been removed. Hence,
       // all editor features will be removed, so any reactions from filters will
       // be undone.
-      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration').findOnce('ckeditor-configuration');
+      var $configurationForm = $(context).find('.ckeditor-toolbar-configuration.ckeditor-configuration-processed');
       if ($configurationForm.length && Drupal.ckeditor.models && Drupal.ckeditor.models.Model) {
         var config = Drupal.ckeditor.models.Model.toJSON().activeEditorConfig;
         var buttons = Drupal.ckeditor.views.controller.getButtonList(config);
diff --git a/core/modules/ckeditor/src/Tests/CKEditorTest.php b/core/modules/ckeditor/src/Tests/CKEditorTest.php
index 279b56f..ab303b6 100644
--- a/core/modules/ckeditor/src/Tests/CKEditorTest.php
+++ b/core/modules/ckeditor/src/Tests/CKEditorTest.php
@@ -406,7 +406,7 @@ function testJSTranslation() {
   protected function assertCKEditorLanguage($langcode = 'fr') {
     // Set French as the site default language.
     ConfigurableLanguage::createFromLangcode('fr')->save();
-    $this->config('system.site')->set('default_langcode', 'fr')->save();
+    $this->config('system.site')->set('langcode', 'fr')->save();
 
     // Reset the language manager so new negotiations attempts will fall back on
     // French. Reinject the language manager CKEditor to use the current one.
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 3ad9a0a..5ab742d 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -699,6 +699,13 @@ function template_preprocess_comment(&$variables) {
     $variables['user_picture'] = array();
   }
 
+  if (isset($variables['elements']['signature'])) {
+    $variables['signature'] = $variables['elements']['signature'];
+    unset($variables['elements']['signature']);
+  }
+  else {
+    $variables['signature'] = '';
+  }
   if (isset($comment->in_preview)) {
     $variables['title'] = \Drupal::l($comment->getSubject(), new Url('<front>'));
     $variables['permalink'] = \Drupal::l(t('Permalink'), new Url('<front>'));
diff --git a/core/modules/comment/config/optional/views.view.comments_recent.yml b/core/modules/comment/config/install/views.view.comments_recent.yml
similarity index 100%
rename from core/modules/comment/config/optional/views.view.comments_recent.yml
rename to core/modules/comment/config/install/views.view.comments_recent.yml
diff --git a/core/modules/comment/src/CommentInterface.php b/core/modules/comment/src/CommentInterface.php
index c141706..e7a4ee9 100644
--- a/core/modules/comment/src/CommentInterface.php
+++ b/core/modules/comment/src/CommentInterface.php
@@ -45,7 +45,7 @@ public function getParentComment();
   /**
    * Returns the entity to which the comment is attached.
    *
-   * @return \Drupal\Core\Entity\FieldableEntityInterface
+   * @return \Drupal\Core\Entity\EntityInterface
    *   The entity on which the comment is attached.
    */
   public function getCommentedEntity();
diff --git a/core/modules/comment/src/CommentViewBuilder.php b/core/modules/comment/src/CommentViewBuilder.php
index a247e02..bf0f526 100644
--- a/core/modules/comment/src/CommentViewBuilder.php
+++ b/core/modules/comment/src/CommentViewBuilder.php
@@ -102,6 +102,18 @@ public function buildComponents(array &$build, array $entities, array $displays,
         );
       }
 
+      $account = comment_prepare_author($entity);
+      $config = \Drupal::config('user.settings');
+      $build['#cache']['tags'] = Cache::mergeTags(isset($build['#cache']['tags']) ? $build['#cache']['tags'] : [],  $config->getCacheTags());
+      if ($config->get('signatures') && $account->getSignature()) {
+        $build[$id]['signature'] = array(
+          '#type' => 'processed_text',
+          '#text' => $account->getSignature(),
+          '#format' => $account->getSignatureFormat(),
+          '#langcode' => $entity->language()->getId(),
+        );
+      }
+
       if (!isset($build[$id]['#attached'])) {
         $build[$id]['#attached'] = array();
       }
diff --git a/core/modules/comment/src/Plugin/views/field/NodeNewComments.php b/core/modules/comment/src/Plugin/views/field/NodeNewComments.php
index 695bd91..40b8a59 100644
--- a/core/modules/comment/src/Plugin/views/field/NodeNewComments.php
+++ b/core/modules/comment/src/Plugin/views/field/NodeNewComments.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Database\Connection;
 use Drupal\comment\CommentInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\Plugin\views\field\NumericField;
+use Drupal\views\Plugin\views\field\Numeric;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
@@ -23,7 +23,7 @@
  *
  * @ViewsField("node_new_comments")
  */
-class NodeNewComments extends NumericField {
+class NodeNewComments extends Numeric {
 
   /**
    * {@inheritdoc}
@@ -133,12 +133,11 @@ public function preRender(&$values) {
     if ($nids) {
       $result = $this->database->query("SELECT n.nid, COUNT(c.cid) as num_comments FROM {node} n INNER JOIN {comment_field_data} c ON n.nid = c.entity_id AND c.entity_type = 'node' AND c.default_langcode = 1
         LEFT JOIN {history} h ON h.nid = n.nid AND h.uid = :h_uid WHERE n.nid IN ( :nids[] )
-        AND c.changed > GREATEST(COALESCE(h.timestamp, :timestamp1), :timestamp2) AND c.status = :status GROUP BY n.nid", array(
+        AND c.changed > GREATEST(COALESCE(h.timestamp, :timestamp), :timestamp) AND c.status = :status GROUP BY n.nid", array(
         ':status' => CommentInterface::PUBLISHED,
         ':h_uid' => $user->id(),
         ':nids[]' => $nids,
-        ':timestamp1' => HISTORY_READ_LIMIT,
-        ':timestamp2' => HISTORY_READ_LIMIT,
+        ':timestamp' => HISTORY_READ_LIMIT,
       ));
       foreach ($result as $node) {
         foreach ($ids[$node->id()] as $id) {
diff --git a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
index 3df2879..c04b939 100644
--- a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
+++ b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
@@ -42,7 +42,7 @@ protected function setUp() {
 
     // Install tables and config needed to render comments.
     $this->installSchema('comment', array('comment_entity_statistics'));
-    $this->installConfig(array('system', 'filter', 'comment'));
+    $this->installConfig(array('system', 'filter'));
 
     // Comment rendering generates links, so build the router.
     $this->installSchema('system', array('router'));
@@ -110,6 +110,7 @@ public function testCacheTags() {
       'comment_view',
       'comment:' . $comment->id(),
       'config:filter.format.plain_text',
+      'config:user.settings',
       'user_view',
       'user:2',
     );
diff --git a/core/modules/comment/src/Tests/CommentFieldAccessTest.php b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
index 7faecad..d1be85d 100644
--- a/core/modules/comment/src/Tests/CommentFieldAccessTest.php
+++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
@@ -79,7 +79,7 @@ class CommentFieldAccessTest extends EntityUnitTestBase {
    */
   protected function setUp() {
     parent::setUp();
-    $this->installConfig(array('user', 'comment'));
+    $this->installConfig(array('user'));
     $this->installSchema('comment', array('comment_entity_statistics'));
   }
 
diff --git a/core/modules/comment/src/Tests/CommentPreviewTest.php b/core/modules/comment/src/Tests/CommentPreviewTest.php
index d038514..ae65f88 100644
--- a/core/modules/comment/src/Tests/CommentPreviewTest.php
+++ b/core/modules/comment/src/Tests/CommentPreviewTest.php
@@ -39,8 +39,11 @@ function testCommentPreview() {
     $this->setCommentSettings('default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Comment paging changed.');
     $this->drupalLogout();
 
-    // Login as web user and add a user picture.
+    // Login as web user and add a signature and a user picture.
     $this->drupalLogin($this->webUser);
+    $this->config('user.settings')->set('signatures', 1)->save();
+    $test_signature = $this->randomMachineName();
+    $edit['signature[value]'] = '<a href="http://example.com/">' . $test_signature. '</a>';
     $image = current($this->drupalGetTestFiles('image'));
     $edit['files[user_picture_0]'] = drupal_realpath($image->uri);
     $this->drupalPostForm('user/' . $this->webUser->id() . '/edit', $edit, t('Save'));
@@ -60,6 +63,9 @@ function testCommentPreview() {
     $this->assertFieldByName('subject[0][value]', $edit['subject[0][value]'], 'Subject field displayed.');
     $this->assertFieldByName('comment_body[0][value]', $edit['comment_body[0][value]'], 'Comment field displayed.');
 
+    // Check that the signature is displaying with the correct text format.
+    $this->assertLink($test_signature);
+
     // Check that the user picture is displayed.
     $this->assertFieldByXPath("//article[contains(@class, 'preview')]//div[contains(@class, 'user-picture')]//img", NULL, 'User picture displayed.');
   }
diff --git a/core/modules/comment/templates/comment.html.twig b/core/modules/comment/templates/comment.html.twig
index 3a7d19b..75604b9 100644
--- a/core/modules/comment/templates/comment.html.twig
+++ b/core/modules/comment/templates/comment.html.twig
@@ -22,6 +22,7 @@
  * - submitted: Submission information created from author and created
  *   during template_preprocess_comment().
  * - user_picture: The comment author's profile picture.
+ * - signature: The comment author's signature.
  * - status: Comment status. Possible values are:
  *   unpublished, published, or preview.
  * - title: Comment title, linked to the comment.
@@ -102,6 +103,12 @@
 
   <div{{ content_attributes }}>
     {{ content|without('links') }}
+
+    {% if signature %}
+      <div>
+        {{ signature }}
+      </div>
+    {% endif %}
   </div>
   {% if content.links %}
     {{ content.links }}
diff --git a/core/modules/config/src/Tests/ConfigEntityListTest.php b/core/modules/config/src/Tests/ConfigEntityListTest.php
index 9287174..275136d 100644
--- a/core/modules/config/src/Tests/ConfigEntityListTest.php
+++ b/core/modules/config/src/Tests/ConfigEntityListTest.php
@@ -26,16 +26,6 @@ class ConfigEntityListTest extends WebTestBase {
   public static $modules = array('config_test');
 
   /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    // Delete the override config_test entity since it is not required by this
-    // test.
-    \Drupal::entityManager()->getStorage('config_test')->load('override')->delete();
-  }
-
-  /**
    * Tests entity list builder methods.
    */
   function testList() {
diff --git a/core/modules/config/src/Tests/ConfigEntityTest.php b/core/modules/config/src/Tests/ConfigEntityTest.php
index ac93e87..7cf16e6 100644
--- a/core/modules/config/src/Tests/ConfigEntityTest.php
+++ b/core/modules/config/src/Tests/ConfigEntityTest.php
@@ -319,44 +319,6 @@ function testCRUDUI() {
     $this->drupalPostForm('admin/structure/config_test/manage/0/delete', array(), 'Delete');
     $this->assertFalse(entity_load('config_test', '0'), 'Test entity deleted');
 
-    // Create a configuration entity with a property that uses AJAX to show
-    // extra form elements.
-    $this->drupalGet('admin/structure/config_test/add');
-
-    // Test that the dependent element is not shown initially.
-    $this->assertFieldByName('size');
-    $this->assertNoFieldByName('size_value');
-
-    $id = strtolower($this->randomMachineName());
-    $edit = [
-      'id' => $id,
-      'label' => $this->randomString(),
-      'size' => 'custom',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, 'size');
-
-    // Check that the dependent element is shown after selecting a 'size' value.
-    $this->assertFieldByName('size');
-    $this->assertFieldByName('size_value');
-
-    // Test the same scenario but it in a non-JS case by using a 'js-hidden'
-    // submit button.
-    $this->drupalGet('admin/structure/config_test/add');
-    $this->assertFieldByName('size');
-    $this->assertNoFieldByName('size_value');
-
-    $this->drupalPostForm(NULL, $edit, 'Change size');
-    $this->assertFieldByName('size');
-    $this->assertFieldByName('size_value');
-
-    // Submit the form with the regular 'Save' button and check that the entity
-    // values are correct.
-    $edit += ['size_value' => 'medium'];
-    $this->drupalPostForm(NULL, $edit, 'Save');
-
-    $entity = entity_load('config_test', $id);
-    $this->assertEqual($entity->get('size'), 'custom');
-    $this->assertEqual($entity->get('size_value'), 'medium');
   }
 
 }
diff --git a/core/modules/config/src/Tests/ConfigImportRecreateTest.php b/core/modules/config/src/Tests/ConfigImportRecreateTest.php
index 83ea2ee..74aea5f 100644
--- a/core/modules/config/src/Tests/ConfigImportRecreateTest.php
+++ b/core/modules/config/src/Tests/ConfigImportRecreateTest.php
@@ -38,7 +38,7 @@ protected function setUp() {
     parent::setUp();
 
     $this->installEntitySchema('node');
-    $this->installConfig(array('field', 'node'));
+    $this->installConfig(array('field'));
 
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
 
@@ -94,8 +94,8 @@ public function testRecreateEntity() {
     // will be recreated.
     $creates = $this->configImporter->getUnprocessedConfiguration('create');
     $deletes = $this->configImporter->getUnprocessedConfiguration('delete');
-    $this->assertEqual(5, count($creates), 'There are 5 configuration items to create.');
-    $this->assertEqual(5, count($deletes), 'There are 5 configuration items to delete.');
+    $this->assertEqual(4, count($creates), 'There are 4 configuration items to create.');
+    $this->assertEqual(4, count($deletes), 'There are 4 configuration items to delete.');
     $this->assertEqual(0, count($this->configImporter->getUnprocessedConfiguration('update')), 'There are no configuration items to update.');
     $this->assertIdentical($creates, array_reverse($deletes), 'Deletes and creates contain the same configuration names in opposite orders due to dependencies.');
 
diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/src/Tests/ConfigImportUITest.php
index 4f3aea5..9bc30e3 100644
--- a/core/modules/config/src/Tests/ConfigImportUITest.php
+++ b/core/modules/config/src/Tests/ConfigImportUITest.php
@@ -68,8 +68,6 @@ function testImport() {
       'label' => 'New',
       'weight' => 0,
       'style' => '',
-      'size' => '',
-      'size_value' => '',
       'protected_property' => '',
     );
     $staging->write($dynamic_name, $original_dynamic_data);
@@ -375,9 +373,7 @@ function testImportErrorLog() {
       'label' => 'Primary',
       'weight' => 0,
       'style' => NULL,
-      'size' => NULL,
-      'size_value' => NULL,
-      'protected_property' => NULL,
+      'protected_property' => null,
     );
     $staging->write($name_primary, $values_primary);
     $values_secondary = array(
@@ -392,9 +388,7 @@ function testImportErrorLog() {
       'label' => 'Secondary Sync',
       'weight' => 0,
       'style' => NULL,
-      'size' => NULL,
-      'size_value' => NULL,
-      'protected_property' => NULL,
+      'protected_property' => null,
     );
     $staging->write($name_secondary, $values_secondary);
     // Verify that there are configuration differences to import.
diff --git a/core/modules/config/src/Tests/ConfigImporterTest.php b/core/modules/config/src/Tests/ConfigImporterTest.php
index a6b2312..00c5a1f 100644
--- a/core/modules/config/src/Tests/ConfigImporterTest.php
+++ b/core/modules/config/src/Tests/ConfigImporterTest.php
@@ -32,7 +32,7 @@ class ConfigImporterTest extends KernelTestBase {
    *
    * @var array
    */
-  public static $modules = array('config_test', 'system', 'config_import_test');
+  public static $modules = array('config_test', 'system', 'config_import_test', 'config_test_language');
 
   protected function setUp() {
     parent::setUp();
@@ -173,8 +173,6 @@ function testNew() {
       'label' => 'New',
       'weight' => 0,
       'style' => '',
-      'size' => '',
-      'size_value' => '',
       'protected_property' => '',
     );
     $staging->write($dynamic_name, $original_dynamic_data);
@@ -541,4 +539,24 @@ function testIsInstallable() {
     $this->assertTrue($this->container->get('config.storage')->exists($config_name));
   }
 
+  /**
+   * Tests imported configuration entities with and without language information.
+   */
+  function testLanguage() {
+    // Test imported configuration with implicit language code.
+    $data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.english');
+    $this->assertTrue(!isset($data['langcode']));
+    $this->assertEqual(
+      $this->config('config_test.dynamic.dotted.english')->get('langcode'),
+      'en'
+    );
+
+    // Test imported configuration with explicit language code.
+    $data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.french');
+    $this->assertEqual($data['langcode'], 'fr');
+    $this->assertEqual(
+      $this->config('config_test.dynamic.dotted.french')->get('langcode'),
+      'fr'
+    );
+  }
 }
diff --git a/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php b/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php
deleted file mode 100644
index 3e2c7bf..0000000
--- a/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\config\Tests\ConfigInstallProfileOverrideTest.
- */
-
-namespace Drupal\config\Tests;
-
-use Drupal\Core\Config\InstallStorage;
-use Drupal\simpletest\WebTestBase;
-use Drupal\Core\Config\FileStorage;
-use Drupal\system\Entity\Action;
-use Drupal\tour\Entity\Tour;
-
-/**
- * Tests installation and removal of configuration objects in install, disable
- * and uninstall functionality.
- *
- * @group config
- */
-class ConfigInstallProfileOverrideTest extends WebTestBase {
-
-  /**
-   * The profile to install as a basis for testing.
-   *
-   * @var string
-   */
-  protected $profile = 'testing_config_overrides';
-
-
-  /**
-   * Tests install profile config changes.
-   */
-  function testInstallProfileConfigOverwrite() {
-    $config_name = 'system.cron';
-    // The expected configuration from the system module.
-    $expected_original_data = array(
-      'threshold' => array(
-        'autorun' => 0,
-        'requirements_warning' => 172800,
-        'requirements_error' => 1209600,
-      ),
-    );
-    // The expected active configuration altered by the install profile.
-    $expected_profile_data = array(
-      'threshold' => array(
-        'autorun' => 0,
-        'requirements_warning' => 259200,
-        'requirements_error' => 1209600,
-      ),
-    );
-
-    // Verify that the original data matches. We have to read the module config
-    // file directly, because the install profile default system.cron.yml
-    // configuration file was used to create the active configuration.
-    $config_dir = drupal_get_path('module', 'system') . '/'. InstallStorage::CONFIG_INSTALL_DIRECTORY;
-    $this->assertTrue(is_dir($config_dir));
-    $source_storage = new FileStorage($config_dir);
-    $data = $source_storage->read($config_name);
-    $this->assertIdentical($data, $expected_original_data);
-
-    // Verify that active configuration matches the expected data, which was
-    // created from the testing install profile's system.cron.yml file.
-    $config = $this->config($config_name);
-    $this->assertIdentical($config->get(), $expected_profile_data);
-
-    // Ensure that the configuration entity has the expected dependencies and
-    // overrides.
-    $action = Action::load('user_block_user_action');
-    $this->assertEqual($action->label(), 'Overridden block the selected user(s)');
-    $action = Action::load('user_cancel_user_action');
-    $this->assertEqual($action->label(), 'Cancel the selected user account(s)', 'Default configuration that is not overridden is not affected.');
-
-    // Ensure that optional configuration can be overridden.
-    $tour = Tour::load('language');
-    $this->assertEqual(count($tour->getTips()), 1, 'Optional configuration can be overridden. The language tour only has one tip');
-    $tour = Tour::load('language-add');
-    $this->assertEqual(count($tour->getTips()), 3, 'Optional configuration that is not overridden is not affected.');
-
-    // Ensure that optional configuration from a profile is created if
-    // dependencies are met.
-    $this->assertEqual(Tour::load('testing_config_overrides')->label(), 'Config override test');
-
-    // Ensure that optional configuration from a profile is not created if
-    // dependencies are not met. Cannot use the entity system since the entity
-    // type does not exist.
-    $optional_dir = drupal_get_path('module', 'testing_config_overrides') . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
-    $optional_storage = new FileStorage($optional_dir);
-    foreach (['config_test.dynamic.dotted.default', 'config_test.dynamic.override','config_test.dynamic.override_unmet'] as $id) {
-      $this->assertTrue(\Drupal::config($id)->isNew(), "The config_test entity $id contained in the profile's optional directory does not exist.");
-      // Make that we don't get false positives from the assertion above.
-      $this->assertTrue($optional_storage->exists($id), "The config_test entity $id does exist in the profile's optional directory.");
-    }
-
-    // Install the config_test module and ensure that the override from the
-    // install profile is not used. Optional configuration can not override
-    // configuration in a modules config/install directory.
-    $this->container->get('module_installer')->install(['config_test']);
-    $this->rebuildContainer();
-    $config_test_storage = \Drupal::entityManager()->getStorage('config_test');
-    $this->assertEqual($config_test_storage->load('dotted.default')->label(), 'Default', 'The config_test entity is not overridden by the profile optional configuration.');
-    // Test that override of optional configuration does work.
-    $this->assertEqual($config_test_storage->load('override')->label(), 'Override', 'The optional config_test entity is overridden by the profile optional configuration.');
-    // Test that override of optional configuration which introduces an unmet
-    // dependency does not get created.
-    $this->assertNull($config_test_storage->load('override_unmet'), 'The optional config_test entity with unmet dependencies is not created.');
-
-    $this->container->get('module_installer')->install(['dblog']);
-    $this->rebuildContainer();
-    // Just installing db_log does not create the optional configuration.
-    $this->assertNull($config_test_storage->load('override_unmet'), 'The optional config_test entity with unmet dependencies is not created.');
-    // Install all available optional configuration.
-    $this->container->get('config.installer')->installOptionalConfig();
-    $this->assertEqual($config_test_storage->load('override_unmet')->label(), 'Override', 'The optional config_test entity is overridden by the profile optional configuration.');
-
-
-  }
-
-}
diff --git a/core/modules/config/src/Tests/ConfigInstallProfileUnmetDependenciesTest.php b/core/modules/config/src/Tests/ConfigInstallProfileUnmetDependenciesTest.php
deleted file mode 100644
index e7e8f6c..0000000
--- a/core/modules/config/src/Tests/ConfigInstallProfileUnmetDependenciesTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\config\Tests\ConfigInstallProfileUnmetDependenciesTest.
- */
-
-namespace Drupal\config\Tests;
-
-use Drupal\Component\Serialization\Yaml;
-use Drupal\Core\Config\InstallStorage;
-use Drupal\simpletest\InstallerTestBase;
-
-/**
- * Tests install profile config overrides can not add unmet dependencies.
- *
- * @group Config
- */
-class ConfigInstallProfileUnmetDependenciesTest extends InstallerTestBase {
-
-  /**
-   * The installation profile to install.
-   *
-   * @var string
-   */
-  protected $profile = 'testing_config_overrides';
-
-  /**
-   * Set to TRUE if the expected exception is thrown.
-   *
-   * @var bool
-   */
-  protected $expectedException = FALSE;
-
-  protected function setUp() {
-    // Copy the testing_config_overrides install profile so we can change the
-    // configuration to include a dependency that can not be met. File API
-    // functions are not available yet.
-    $dest = $this->siteDirectory . '/profiles/testing_config_overrides';
-    mkdir($dest, 0777, TRUE);
-    $source = DRUPAL_ROOT . '/core/profiles/testing_config_overrides';
-    $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
-    foreach ($iterator as $item) {
-      if ($item->isDir()) {
-        mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
-      }
-      else {
-        copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
-      }
-    }
-
-    // Add a dependency that can not be met because User is installed before
-    // Action.
-    $config_file = $dest . DIRECTORY_SEPARATOR . InstallStorage::CONFIG_INSTALL_DIRECTORY . DIRECTORY_SEPARATOR . 'system.action.user_block_user_action.yml';
-    $action = Yaml::decode(file_get_contents($config_file));
-    $action['dependencies']['module'][] = 'action';
-    file_put_contents($config_file, Yaml::encode($action));
-
-    parent::setUp();
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * Override the error method so we can test for the expected exception.
-   */
-  protected function error($message = '', $group = 'Other', array $caller = NULL) {
-    if ($group == 'User notice') {
-      // Since 'User notice' is set by trigger_error() which is used for debug
-      // set the message to a status of 'debug'.
-      return $this->assert('debug', $message, 'Debug', $caller);
-    }
-    if ($group == 'Drupal\Core\Config\UnmetDependenciesException') {
-      $this->expectedException = TRUE;
-      return FALSE;
-    }
-    return $this->assert('exception', $message, $group, $caller);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUpSite() {
-    // This step is not reached due to the exception.
-  }
-
-
-  /**
-   * Confirms that the installation succeeded.
-   */
-  public function testInstalled() {
-    if ($this->expectedException) {
-      $this->pass('Expected Drupal\Core\Config\UnmetDependenciesException exception thrown');
-    }
-    else {
-      $this->fail('Expected Drupal\Core\Config\UnmetDependenciesException exception thrown');
-    }
-  }
-
-}
diff --git a/core/modules/config/src/Tests/ConfigInstallTest.php b/core/modules/config/src/Tests/ConfigInstallTest.php
index 9a903a1..2da9e53 100644
--- a/core/modules/config/src/Tests/ConfigInstallTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallTest.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Config\StorageInterface;
-use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\simpletest\KernelTestBase;
 
 /**
@@ -23,14 +22,8 @@ class ConfigInstallTest extends KernelTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['system'];
-
-  /**
-   * {@inheritdoc}
-   */
   protected function setUp() {
     parent::setUp();
-    $this->installSchema('system', ['router']);
 
     // Ensure the global variable being asserted by this test does not exist;
     // a previous test executed in this request/process might have set it.
@@ -55,7 +48,11 @@ function testModuleInstallation() {
     $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install does not exist.');
 
     // Install the test module.
-    $this->installModules(array('config_test'));
+    $this->enableModules(array('config_test', 'config_schema_test'));
+    $this->installConfig(array('config_test', 'config_schema_test'));
+
+    // After module installation the new schema should exist.
+    $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install exists.');
 
     // Verify that default module config exists.
     \Drupal::configFactory()->reset($default_config);
@@ -74,13 +71,6 @@ function testModuleInstallation() {
     $this->assertFalse(isset($GLOBALS['hook_config_test']['predelete']));
     $this->assertFalse(isset($GLOBALS['hook_config_test']['delete']));
 
-    // Install the schema test module.
-    $this->enableModules(array('config_schema_test'));
-    $this->installConfig(array('config_schema_test'));
-
-    // After module installation the new schema should exist.
-    $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install exists.');
-
     // Ensure that data type casting is applied during config installation.
     $config = $this->config('config_schema_test.schema_in_install');
     $this->assertIdentical($config->get('integer'), 1);
@@ -180,7 +170,8 @@ public function testCollectionInstallationCollectionConfigEntity() {
     );
     \Drupal::state()->set('config_collection_install_test.collection_names', $collections);
     // Install the test module.
-    $this->installModules(array('config_test', 'config_collection_install_test'));
+    $this->enableModules(array('config_test', 'config_collection_install_test'));
+    $this->installConfig(array('config_test'));
     /** @var \Drupal\Core\Config\StorageInterface $active_storage */
     $active_storage = \Drupal::service('config.storage');
     $this->assertEqual($collections, $active_storage->getAllCollectionNames());
@@ -198,56 +189,4 @@ public function testCollectionInstallationCollectionConfigEntity() {
     $this->assertIdentical(array('label' => 'entity'), $data);
   }
 
-  /**
-   * Tests the configuration with unmet dependencies is not installed.
-   */
-  public function testDependencyChecking() {
-    $this->installModules(['config_test']);
-    try {
-      $this->installModules(['config_install_dependency_test']);
-      $this->fail('Expected UnmetDependenciesException not thrown.');
-    }
-    catch (UnmetDependenciesException $e) {
-      $this->assertEqual($e->getExtension(), 'config_install_dependency_test');
-      $this->assertEqual($e->getConfigObjects(), ['config_test.dynamic.other_module_test_with_dependency']);
-      $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.other_module_test_with_dependency) provided by config_install_dependency_test have unmet dependencies');
-    }
-    $this->installModules(['config_other_module_config_test']);
-    $this->installModules(['config_install_dependency_test']);
-    $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
-  }
-
-  /**
-   * Tests imported configuration entities with and without language information.
-   */
-  function testLanguage() {
-    $this->installModules(['config_test_language']);
-    // Test imported configuration with implicit language code.
-    $data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.english');
-    $this->assertTrue(!isset($data['langcode']));
-    $this->assertEqual(
-      $this->config('config_test.dynamic.dotted.english')->get('langcode'),
-      'en'
-    );
-
-    // Test imported configuration with explicit language code.
-    $data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.french');
-    $this->assertEqual($data['langcode'], 'fr');
-    $this->assertEqual(
-      $this->config('config_test.dynamic.dotted.french')->get('langcode'),
-      'fr'
-    );
-  }
-
-  /**
-   * Installs a module.
-   *
-   * @param array $modules
-   *   The module names.
-   */
-  protected function installModules(array $modules) {
-    $this->container->get('module_installer')->install($modules);
-    $this->container = \Drupal::getContainer();
-  }
-
 }
diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/src/Tests/ConfigInstallWebTest.php
index cff60a4..b04ce39 100644
--- a/core/modules/config/src/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallWebTest.php
@@ -7,10 +7,12 @@
 
 namespace Drupal\config\Tests;
 
+use Drupal\Core\Config\InstallStorage;
 use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\simpletest\WebTestBase;
+use Drupal\Core\Config\FileStorage;
 
 /**
  * Tests installation and removal of configuration objects in install, disable
@@ -118,6 +120,43 @@ function testIntegrationModuleReinstallation() {
   }
 
   /**
+   * Tests install profile config changes.
+   */
+  function testInstallProfileConfigOverwrite() {
+    $config_name = 'system.cron';
+    // The expected configuration from the system module.
+    $expected_original_data = array(
+      'threshold' => array(
+        'autorun' => 0,
+        'requirements_warning' => 172800,
+        'requirements_error' => 1209600,
+      ),
+    );
+    // The expected active configuration altered by the install profile.
+    $expected_profile_data = array(
+      'threshold' => array(
+        'autorun' => 0,
+        'requirements_warning' => 259200,
+        'requirements_error' => 1209600,
+      ),
+    );
+
+    // Verify that the original data matches. We have to read the module config
+    // file directly, because the install profile default system.cron.yml
+    // configuration file was used to create the active configuration.
+    $config_dir = drupal_get_path('module', 'system') . '/'. InstallStorage::CONFIG_INSTALL_DIRECTORY;
+    $this->assertTrue(is_dir($config_dir));
+    $source_storage = new FileStorage($config_dir);
+    $data = $source_storage->read($config_name);
+    $this->assertIdentical($data, $expected_original_data);
+
+    // Verify that active configuration matches the expected data, which was
+    // created from the testing install profile's system.cron.yml file.
+    $config = $this->config($config_name);
+    $this->assertIdentical($config->get(), $expected_profile_data);
+  }
+
+  /**
    * Tests pre-existing configuration detection.
    */
   public function testPreExistingConfigInstall() {
@@ -175,21 +214,4 @@ public function testPreExistingConfigInstall() {
       $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default) provided by config_clash_test_theme already exist in active configuration');
     }
   }
-
-  /**
-   * Tests unmet dependencies detection.
-   */
-  public function testUnmetDependenciesInstall() {
-    $this->drupalLogin($this->adminUser);
-    // We need to install separately since config_install_dependency_test does
-    // not depend on config_test and order is important.
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE), t('Save configuration'));
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration'));
-    $this->assertRaw('Unable to install Config install dependency test, <em class="placeholder">config_test.dynamic.other_module_test_with_dependency</em> has unmet dependencies.');
-
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_other_module_config_test][enable]' => TRUE), t('Save configuration'));
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration'));
-    $this->rebuildContainer();
-    $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
-  }
 }
diff --git a/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php b/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php
index f21c30c..9ecf5ae 100644
--- a/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php
+++ b/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php
@@ -75,7 +75,7 @@ function testSiteNameTranslation() {
     // overrides still work.
     $language_manager = \Drupal::languageManager()->reset();
     $this->assertTrue($language_manager->isMultilingual(), 'The test site is multilingual.');
-    $this->config('system.site')->set('default_langcode', 'xx')->save();
+    $this->config('system.site')->set('langcode', 'xx')->save();
 
     ConfigurableLanguage::load('en')->delete();
     $this->assertFalse($language_manager->isMultilingual(), 'The test site is monolingual.');
diff --git a/core/modules/config/src/Tests/ConfigOtherModuleTest.php b/core/modules/config/src/Tests/ConfigOtherModuleTest.php
index ee03317..082e485 100644
--- a/core/modules/config/src/Tests/ConfigOtherModuleTest.php
+++ b/core/modules/config/src/Tests/ConfigOtherModuleTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\config\Tests;
 
+use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\StorageInterface;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -57,10 +59,18 @@ public function testInstallOtherModuleFirst() {
     // Default configuration provided by config_test should still exist.
     $this->assertTrue(entity_load('config_test', 'dotted.default', TRUE), 'The configuration is not deleted.');
 
-    // Re-enable module to test that pre-existing optional configuration does
-    // not throw an error.
-    $this->installModule('config_other_module_config_test');
-    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('config_other_module_config_test'), 'The config_other_module_config_test module is installed.');
+    // Re-enable module to test that pre-existing default configuration throws
+    // an error.
+    $msg = "The expected PreExistingConfigException is thrown by reinstalling config_other_module_config_test.";
+    try {
+      $this->installModule('config_other_module_config_test');
+      $this->fail($msg);
+    }
+    catch (PreExistingConfigException $e) {
+      $this->pass($msg);
+      $this->assertEqual($e->getExtension(), 'config_other_module_config_test');
+      $this->assertEqual($e->getConfigObjects(), [StorageInterface::DEFAULT_COLLECTION => ['config_test.dynamic.other_module_test']]);
+    }
   }
 
   /**
diff --git a/core/modules/config/src/Tests/ConfigSchemaTest.php b/core/modules/config/src/Tests/ConfigSchemaTest.php
index 676401e..ca53a53 100644
--- a/core/modules/config/src/Tests/ConfigSchemaTest.php
+++ b/core/modules/config/src/Tests/ConfigSchemaTest.php
@@ -248,7 +248,7 @@ function testSchemaMappingWithParents() {
     $expected = array(
       'type' => 'config_schema_test.someschema.with_parents.key_1',
       'label' => 'Test item nested one level',
-      'class' => '\Drupal\Core\TypedData\Plugin\DataType\StringData',
+      'class' => '\Drupal\Core\TypedData\Plugin\DataType\String',
       'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
     );
     $this->assertEqual($definition, $expected);
@@ -259,7 +259,7 @@ function testSchemaMappingWithParents() {
     $expected = array(
       'type' => 'config_schema_test.someschema.with_parents.key_2',
       'label' => 'Test item nested two levels',
-      'class' => '\Drupal\Core\TypedData\Plugin\DataType\StringData',
+      'class' => '\Drupal\Core\TypedData\Plugin\DataType\String',
       'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
     );
     $this->assertEqual($definition, $expected);
@@ -270,7 +270,7 @@ function testSchemaMappingWithParents() {
     $expected = array(
       'type' => 'config_schema_test.someschema.with_parents.key_3',
       'label' => 'Test item nested three levels',
-      'class' => '\Drupal\Core\TypedData\Plugin\DataType\StringData',
+      'class' => '\Drupal\Core\TypedData\Plugin\DataType\String',
       'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
     );
     $this->assertEqual($definition, $expected);
diff --git a/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml b/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml
deleted file mode 100644
index 69470f8..0000000
--- a/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-id: other_module_test_with_dependency
-label: 'Other module test with dependency'
-weight: 0
-style: ''
-status: true
-langcode: en
-protected_property: Default
-dependencies:
-  enforced:
-    module:
-      - config_other_module_config_test
diff --git a/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml b/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml
deleted file mode 100644
index e9b3c72..0000000
--- a/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-name: 'Config install dependency test'
-type: module
-package: Testing
-version: VERSION
-core: 8.x
diff --git a/core/modules/config/tests/config_other_module_config_test/config/optional/config_test.dynamic.other_module_test.yml b/core/modules/config/tests/config_other_module_config_test/config/install/config_test.dynamic.other_module_test.yml
similarity index 100%
rename from core/modules/config/tests/config_other_module_config_test/config/optional/config_test.dynamic.other_module_test.yml
rename to core/modules/config/tests/config_other_module_config_test/config/install/config_test.dynamic.other_module_test.yml
diff --git a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override.yml b/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override.yml
deleted file mode 100644
index 9721190..0000000
--- a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# See \Drupal\config\Tests\ConfigInstallProfileOverrideTest
-id: override
-label: Default
-weight: 0
-protected_property: Default
-status: 1
diff --git a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml b/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml
deleted file mode 100644
index 7fa7ae4..0000000
--- a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-# See \Drupal\config\Tests\ConfigInstallProfileOverrideTest
-# This configuration entity has dependencies which would be met.
-id: override_unmet
-label: Default
-weight: 0
-protected_property: Default
-status: 1
-dependencies:
-  module:
-    - tour
diff --git a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
index e964db3..1657750 100644
--- a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
+++ b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
@@ -15,12 +15,6 @@ config_test_dynamic:
     style:
       type: string
       label: 'style'
-    size:
-      type: string
-      label: 'Size'
-    size_value:
-      type: string
-      label: 'Size value'
     protected_property:
       type: string
       label: 'Protected property'
diff --git a/core/modules/config/tests/config_test/src/ConfigTestForm.php b/core/modules/config/tests/config_test/src/ConfigTestForm.php
index 56195e2..e77ddb0 100644
--- a/core/modules/config/tests/config_test/src/ConfigTestForm.php
+++ b/core/modules/config/tests/config_test/src/ConfigTestForm.php
@@ -54,50 +54,6 @@ public function form(array $form, FormStateInterface $form_state) {
       $form['style']['#options'] = image_style_options();
     }
 
-    // The main premise of entity forms is that we get to work with an entity
-    // object at all times instead of checking submitted values from the form
-    // state.
-    $size = $entity->get('size');
-
-    $form['size_wrapper'] = array(
-      '#type' => 'container',
-      '#attributes' => array(
-        'id' => 'size-wrapper',
-      ),
-    );
-    $form['size_wrapper']['size'] = array(
-      '#type' => 'select',
-      '#title' => 'Size',
-      '#options' => array(
-        'custom' => 'Custom',
-      ),
-      '#empty_option' => '- None -',
-      '#default_value' => $size,
-      '#ajax' => array(
-        'callback' => '::updateSize',
-        'wrapper' => 'size-wrapper',
-      ),
-    );
-    $form['size_wrapper']['size_submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Change size'),
-      '#attributes' => array(
-        'class' => array('js-hide'),
-      ),
-      '#submit' => array(array(get_class($this), 'changeSize')),
-    );
-    $form['size_wrapper']['size_value'] = array(
-      '#type' => 'select',
-      '#title' => 'Custom size value',
-      '#options' => array(
-        'small' => 'Small',
-        'medium' => 'Medium',
-        'large' => 'Large',
-      ),
-      '#default_value' => $entity->get('size_value'),
-      '#access' => !empty($size),
-    );
-
     $form['actions'] = array('#type' => 'actions');
     $form['actions']['submit'] = array(
       '#type' => 'submit',
@@ -112,20 +68,6 @@ public function form(array $form, FormStateInterface $form_state) {
   }
 
   /**
-   * Ajax callback for the size selection element.
-   */
-  public static function updateSize(array $form, FormStateInterface $form_state) {
-    return $form['size_wrapper'];
-  }
-
-  /**
-   * Element submit handler for non-JS testing.
-   */
-  public static function changeSize(array $form, FormStateInterface $form_state) {
-    $form_state->setRebuild();
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function save(array $form, FormStateInterface $form_state) {
diff --git a/core/modules/config/tests/config_test_language/config_test_language.info.yml b/core/modules/config/tests/config_test_language/config_test_language.info.yml
index 527270f..28d720b 100644
--- a/core/modules/config/tests/config_test_language/config_test_language.info.yml
+++ b/core/modules/config/tests/config_test_language/config_test_language.info.yml
@@ -3,5 +3,3 @@ type: module
 package: Testing
 version: VERSION
 core: 8.x
-dependencies:
-  - config_test
\ No newline at end of file
diff --git a/core/modules/contact/src/Tests/MessageEntityTest.php b/core/modules/contact/src/Tests/MessageEntityTest.php
index 7d9b9b2..52c78a2 100644
--- a/core/modules/contact/src/Tests/MessageEntityTest.php
+++ b/core/modules/contact/src/Tests/MessageEntityTest.php
@@ -32,7 +32,7 @@ class MessageEntityTest extends EntityUnitTestBase {
 
   protected function setUp() {
     parent::setUp();
-    $this->installConfig(array('contact', 'contact_test'));
+    $this->installConfig(array('contact'));
   }
 
   /**
diff --git a/core/modules/content_translation/content_translation.admin.js b/core/modules/content_translation/content_translation.admin.js
index 1f4224b..c10efa1 100644
--- a/core/modules/content_translation/content_translation.admin.js
+++ b/core/modules/content_translation/content_translation.admin.js
@@ -70,7 +70,7 @@
     attach: function (context) {
       // Initially hide all field rows for non translatable bundles and all column
       // rows for non translatable fields.
-      $(context).find('table .bundle-settings .translatable :input').once('translation-entity-admin-hide').each(function () {
+      $(context).find('table .bundle-settings .translatable :input').once('translation-entity-admin-hide', function () {
         var $input = $(this);
         var $bundleSettings = $input.closest('.bundle-settings');
         if (!$input.is(':checked')) {
diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module
index 647b91f..928c4da 100644
--- a/core/modules/editor/editor.module
+++ b/core/modules/editor/editor.module
@@ -92,8 +92,7 @@ function editor_form_filter_admin_overview_alter(&$form, FormStateInterface $for
 function editor_form_filter_format_form_alter(&$form, FormStateInterface $form_state) {
   $editor = $form_state->get('editor');
   if ($editor === NULL) {
-    $format = $form_state->getFormObject()->getEntity();
-    $format_id = $format->isNew() ? NULL : $format->id();
+    $format_id = $form_state->getFormObject()->getEntity()->id();
     $editor = editor_load($format_id);
     $form_state->set('editor', $editor);
   }
@@ -176,9 +175,8 @@ function editor_form_filter_admin_format_editor_configure($form, FormStateInterf
       $form_state->set('editor', FALSE);
     }
     elseif (empty($editor) || $editor_value !== $editor->getEditor()) {
-      $format = $form_state->getFormObject()->getEntity();
       $editor = entity_create('editor', array(
-        'format' => $format->isNew() ? NULL : $format->id(),
+        'format' => $form_state->getFormObject()->getEntity()->id(),
         'editor' => $editor_value,
       ));
       $form_state->set('editor', $editor);
@@ -217,8 +215,7 @@ function editor_form_filter_admin_format_validate($form, FormStateInterface $for
  */
 function editor_form_filter_admin_format_submit($form, FormStateInterface $form_state) {
   // Delete the existing editor if disabling or switching between editors.
-  $format = $form_state->getFormObject()->getEntity();
-  $format_id = $format->isNew() ? NULL : $format->id();
+  $format_id = $form_state->getFormObject()->getEntity()->id();
   $original_editor = editor_load($format_id);
   if ($original_editor && $original_editor->getEditor() != $form_state->getValue(array('editor', 'editor'))) {
     $original_editor->delete();
diff --git a/core/modules/editor/js/editor.admin.js b/core/modules/editor/js/editor.admin.js
index cbd1510..74a38b2 100644
--- a/core/modules/editor/js/editor.admin.js
+++ b/core/modules/editor/js/editor.admin.js
@@ -714,7 +714,7 @@
     attach: function (context, settings) {
       var $context = $(context);
 
-      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-editor-status').each(function () {
+      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-editor-status', function () {
         var $checkbox = $(this);
         var nameAttribute = $checkbox.attr('name');
 
diff --git a/core/modules/editor/js/editor.js b/core/modules/editor/js/editor.js
index c6bbfd6..022bc9f 100644
--- a/core/modules/editor/js/editor.js
+++ b/core/modules/editor/js/editor.js
@@ -140,7 +140,7 @@
         return;
       }
 
-      $(context).find('.editor').once('editor').each(function () {
+      $(context).find('.editor').once('editor', function () {
         var $this = $(this);
         var activeFormatID = $this.val();
         $this.attr('data-editor-active-text-format', activeFormatID);
@@ -188,7 +188,7 @@
       if (trigger === 'serialize') {
         // Removing the editor-processed class guarantees that the editor will
         // be reattached. Only do this if we're planning to destroy the editor.
-        editors = $(context).find('.editor').findOnce('editor');
+        editors = $(context).find('.editor-processed');
       }
       else {
         editors = $(context).find('.editor').removeOnce('editor');
diff --git a/core/modules/editor/src/Tests/EditorFileUsageTest.php b/core/modules/editor/src/Tests/EditorFileUsageTest.php
index 7b5210e..3e66cef 100644
--- a/core/modules/editor/src/Tests/EditorFileUsageTest.php
+++ b/core/modules/editor/src/Tests/EditorFileUsageTest.php
@@ -28,7 +28,6 @@ protected function setUp() {
     $this->installEntitySchema('file');
     $this->installSchema('node', array('node_access'));
     $this->installSchema('file', array('file_usage'));
-    $this->installConfig(['node']);
 
     // Add text formats.
     $filtered_html_format = entity_create('filter_format', array(
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.info.yml b/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.info.yml
index e465519..67a5f48 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.info.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.info.yml
@@ -6,6 +6,3 @@ package: Testing
 version: VERSION
 dependencies:
   - entity_reference
-  - node
-  - user
-  - views
diff --git a/core/modules/field/src/Tests/FieldImportChangeTest.php b/core/modules/field/src/Tests/FieldImportChangeTest.php
index c34ff31..8541664 100644
--- a/core/modules/field/src/Tests/FieldImportChangeTest.php
+++ b/core/modules/field/src/Tests/FieldImportChangeTest.php
@@ -31,7 +31,6 @@ class FieldImportChangeTest extends FieldUnitTestBase {
    * Tests importing an updated field.
    */
   function testImportChange() {
-    $this->installConfig(['field_test_config']);
     $field_storage_id = 'field_test_import';
     $field_id = "entity_test.entity_test.$field_storage_id";
     $field_config_name = "field.field.$field_id";
diff --git a/core/modules/field/src/Tests/FieldImportDeleteTest.php b/core/modules/field/src/Tests/FieldImportDeleteTest.php
index 04eaecc..030adfb 100644
--- a/core/modules/field/src/Tests/FieldImportDeleteTest.php
+++ b/core/modules/field/src/Tests/FieldImportDeleteTest.php
@@ -33,7 +33,6 @@ class FieldImportDeleteTest extends FieldUnitTestBase {
    * Tests deleting field storages and fields as part of config import.
    */
   public function testImportDelete() {
-    $this->installConfig(['field_test_config']);
     // At this point there are 5 field configuration objects in the active
     // storage.
     // - field.storage.entity_test.field_test_import
diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js
index 3ee0dab..1167fcc 100644
--- a/core/modules/field_ui/field_ui.js
+++ b/core/modules/field_ui/field_ui.js
@@ -54,7 +54,7 @@
 
   Drupal.behaviors.fieldUIDisplayOverview = {
     attach: function (context, settings) {
-      $(context).find('table#field-display-overview').once('field-display-overview').each(function () {
+      $(context).find('table#field-display-overview').once('field-display-overview', function () {
         Drupal.fieldUIOverview.attach(this, settings.fieldUIRowsData, Drupal.fieldUIDisplayOverview);
       });
     }
diff --git a/core/modules/field_ui/src/Tests/EntityDisplayTest.php b/core/modules/field_ui/src/Tests/EntityDisplayTest.php
index af63002..9cedc2d 100644
--- a/core/modules/field_ui/src/Tests/EntityDisplayTest.php
+++ b/core/modules/field_ui/src/Tests/EntityDisplayTest.php
@@ -28,7 +28,7 @@ protected function setUp() {
     parent::setUp();
     $this->installSchema('system', array('router'));
     $this->installEntitySchema('node');
-    $this->installConfig(array('field', 'node'));
+    $this->installConfig(array('field'));
   }
 
   /**
diff --git a/core/modules/file/config/optional/views.view.files.yml b/core/modules/file/config/install/views.view.files.yml
similarity index 100%
rename from core/modules/file/config/optional/views.view.files.yml
rename to core/modules/file/config/install/views.view.files.yml
diff --git a/core/modules/file/file.js b/core/modules/file/file.js
index b704542..fcefad1 100644
--- a/core/modules/file/file.js
+++ b/core/modules/file/file.js
@@ -134,10 +134,10 @@
      * Prevent file uploads when using buttons not intended to upload.
      */
     disableFields: function (event) {
-      var $clickedButton = $(this).findOnce('ajax');
+      var $clickedButton = $(this);
 
       // Only disable upload fields for Ajax buttons.
-      if (!$clickedButton.length) {
+      if (!$clickedButton.hasClass('ajax-processed')) {
         return;
       }
 
diff --git a/core/modules/file/src/Plugin/views/argument/Fid.php b/core/modules/file/src/Plugin/views/argument/Fid.php
index 7548901..bca81f7 100644
--- a/core/modules/file/src/Plugin/views/argument/Fid.php
+++ b/core/modules/file/src/Plugin/views/argument/Fid.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -21,7 +21,7 @@
  *
  * @ViewsArgument("file_fid")
  */
-class Fid extends NumericArgument implements ContainerFactoryPluginInterface {
+class Fid extends Numeric implements ContainerFactoryPluginInterface {
 
   /**
    * The entity manager service
diff --git a/core/modules/file/src/Tests/FileFieldPathTest.php b/core/modules/file/src/Tests/FileFieldPathTest.php
index 6de342a..bf166ed 100644
--- a/core/modules/file/src/Tests/FileFieldPathTest.php
+++ b/core/modules/file/src/Tests/FileFieldPathTest.php
@@ -57,7 +57,7 @@ function testUploadPath() {
     $node_file = file_load($node->{$field_name}->target_id);
     // Do token replacement using the same user which uploaded the file, not
     // the user running the test case.
-    $data = array('user' => $this->adminUser);
+    $data = array('user' => $this->admin_user);
     $subdirectory = \Drupal::token()->replace('[user:uid]/[user:name]', $data);
     $this->assertPathMatch('public://' . $subdirectory . '/' . $test_file->getFilename(), $node_file->getFileUri(), format_string('The file %file was uploaded to the correct path with token replacements.', array('%file' => $node_file->getFileUri())));
   }
diff --git a/core/modules/file/src/Tests/FileFieldTestBase.php b/core/modules/file/src/Tests/FileFieldTestBase.php
index 25ef7f2..0cf36c3 100644
--- a/core/modules/file/src/Tests/FileFieldTestBase.php
+++ b/core/modules/file/src/Tests/FileFieldTestBase.php
@@ -24,17 +24,12 @@
   */
   public static $modules = array('node', 'file', 'file_module_test', 'field_ui');
 
-  /**
-   * An user with administration permissions.
-   *
-   * @var \Drupal\user\UserInterface
-   */
-  protected $adminUser;
+  protected $admin_user;
 
   protected function setUp() {
     parent::setUp();
-    $this->adminUser = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access'));
-    $this->drupalLogin($this->adminUser);
+    $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access'));
+    $this->drupalLogin($this->admin_user);
     $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
   }
 
diff --git a/core/modules/file/src/Tests/FileFieldValidateTest.php b/core/modules/file/src/Tests/FileFieldValidateTest.php
index 51d7402..21d93af 100644
--- a/core/modules/file/src/Tests/FileFieldValidateTest.php
+++ b/core/modules/file/src/Tests/FileFieldValidateTest.php
@@ -17,6 +17,8 @@
  * @group file
  */
 class FileFieldValidateTest extends FileFieldTestBase {
+  protected $field;
+  protected $node_type;
 
   /**
    * Tests the required property on file fields.
diff --git a/core/modules/file/src/Tests/FileFieldWidgetTest.php b/core/modules/file/src/Tests/FileFieldWidgetTest.php
index 8ebb696..b26bfaf 100644
--- a/core/modules/file/src/Tests/FileFieldWidgetTest.php
+++ b/core/modules/file/src/Tests/FileFieldWidgetTest.php
@@ -222,7 +222,7 @@ function testMultiValuedWidget() {
   function testPrivateFileSetting() {
     $node_storage = $this->container->get('entity.manager')->getStorage('node');
     // Grant the admin user required permissions.
-    user_role_grant_permissions($this->adminUser->roles[0]->target_id, array('administer node fields'));
+    user_role_grant_permissions($this->admin_user->roles[0]->target_id, array('administer node fields'));
 
     $type_name = 'article';
     $field_name = strtolower($this->randomMachineName());
@@ -262,7 +262,7 @@ function testPrivateFileComment() {
     $user = $this->drupalCreateUser(array('access comments'));
 
     // Grant the admin user required comment permissions.
-    $roles = $this->adminUser->getRoles();
+    $roles = $this->admin_user->getRoles();
     user_role_grant_permissions($roles[1], array('administer comment fields', 'administer comments'));
 
     // Revoke access comments permission from anon user, grant post to
@@ -318,7 +318,7 @@ function testPrivateFileComment() {
     $this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
 
     // Unpublishes node.
-    $this->drupalLogin($this->adminUser);
+    $this->drupalLogin($this->admin_user);
     $this->drupalPostForm('node/' . $node->id() . '/edit', array(), t('Save and unpublish'));
 
     // Ensures normal user can no longer download the file.
diff --git a/core/modules/file/src/Tests/FileListingTest.php b/core/modules/file/src/Tests/FileListingTest.php
index b752c3f..38293ec 100644
--- a/core/modules/file/src/Tests/FileListingTest.php
+++ b/core/modules/file/src/Tests/FileListingTest.php
@@ -23,18 +23,11 @@ class FileListingTest extends FileFieldTestBase {
    */
   public static $modules = array('views', 'file', 'image');
 
-  /**
-   * An authenticated user.
-   *
-   * @var \Drupal\user\UserInterface
-   */
-  protected $baseUser;
-
   protected function setUp() {
     parent::setUp();
 
-    $this->adminUser = $this->drupalCreateUser(array('access files overview', 'bypass node access'));
-    $this->baseUser = $this->drupalCreateUser();
+    $this->admin_user = $this->drupalCreateUser(array('access files overview', 'bypass node access'));
+    $this->base_user = $this->drupalCreateUser();
     $this->createFileField('file', 'node', 'article', array(), array('file_extensions' => 'txt png'));
   }
 
@@ -65,12 +58,12 @@ protected function sumUsages($usage) {
   function testFileListingPages() {
     $file_usage = $this->container->get('file.usage');
     // Users without sufficient permissions should not see file listing.
-    $this->drupalLogin($this->baseUser);
+    $this->drupalLogin($this->base_user);
     $this->drupalGet('admin/content/files');
     $this->assertResponse(403);
 
     // Login with user with right permissions and test listing.
-    $this->drupalLogin($this->adminUser);
+    $this->drupalLogin($this->admin_user);
 
     for ($i = 0; $i < 5; $i++) {
       $nodes[] = $this->drupalCreateNode(array('type' => 'article'));
diff --git a/core/modules/file/src/Tests/FilePrivateTest.php b/core/modules/file/src/Tests/FilePrivateTest.php
index 9c7762b..4ff4ea7 100644
--- a/core/modules/file/src/Tests/FilePrivateTest.php
+++ b/core/modules/file/src/Tests/FilePrivateTest.php
@@ -62,7 +62,7 @@ function testPrivateFile() {
     $no_access_field_name = 'field_no_view_access';
     $this->createFileField($no_access_field_name, 'node', $type_name, array('uri_scheme' => 'private'));
     // Test with the field that should deny access through field access.
-    $this->drupalLogin($this->adminUser);
+    $this->drupalLogin($this->admin_user);
     $nid = $this->uploadNodeFile($test_file, $no_access_field_name, $type_name, TRUE, array('private' => TRUE));
     \Drupal::entityManager()->getStorage('node')->resetCache(array($nid));
     $node = $node_storage->load($nid);
diff --git a/core/modules/file/src/Tests/FileTokenReplaceTest.php b/core/modules/file/src/Tests/FileTokenReplaceTest.php
index bc53e68..84d599f 100644
--- a/core/modules/file/src/Tests/FileTokenReplaceTest.php
+++ b/core/modules/file/src/Tests/FileTokenReplaceTest.php
@@ -54,7 +54,7 @@ function testFileTokenReplacement() {
     $tests['[file:created:short]'] = format_date($file->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
     $tests['[file:changed]'] = format_date($file->getChangedTime(), 'medium', '', NULL, $language_interface->getId());
     $tests['[file:changed:short]'] = format_date($file->getChangedTime(), 'short', '', NULL, $language_interface->getId());
-    $tests['[file:owner]'] = String::checkPlain(user_format_name($this->adminUser));
+    $tests['[file:owner]'] = String::checkPlain(user_format_name($this->admin_user));
     $tests['[file:owner:uid]'] = $file->getOwnerId();
 
     // Test to make sure that we generated something for each token.
diff --git a/core/modules/file/src/Tests/SaveUploadTest.php b/core/modules/file/src/Tests/SaveUploadTest.php
index 5b0dbc1..032a3d4 100644
--- a/core/modules/file/src/Tests/SaveUploadTest.php
+++ b/core/modules/file/src/Tests/SaveUploadTest.php
@@ -22,8 +22,6 @@ class SaveUploadTest extends FileManagedTestBase {
 
   /**
    * An image file path for uploading.
-   *
-   * @var \Drupal\file\FileInterface
    */
   protected $image;
 
@@ -37,13 +35,6 @@ class SaveUploadTest extends FileManagedTestBase {
    */
   protected $maxFidBefore;
 
-  /**
-   * Extension of the image filename.
-   *
-   * @var string
-   */
-  protected $imageExtension;
-
   protected function setUp() {
     parent::setUp();
     $account = $this->drupalCreateUser(array('access site reports'));
@@ -52,7 +43,7 @@ protected function setUp() {
     $image_files = $this->drupalGetTestFiles('image');
     $this->image = entity_create('file', (array) current($image_files));
 
-    list(, $this->imageExtension) = explode('.', $this->image->getFilename());
+    list(, $this->image_extension) = explode('.', $this->image->getFilename());
     $this->assertTrue(is_file($this->image->getFileUri()), "The image file we're going to upload exists.");
 
     $this->phpfile = current($this->drupalGetTestFiles('php'));
@@ -151,7 +142,7 @@ function testHandleExtension() {
     // Reset the hook counters.
     file_test_reset();
 
-    $extensions = 'foo ' . $this->imageExtension;
+    $extensions = 'foo ' . $this->image_extension;
     // Now tell file_save_upload() to allow the extension of our test image.
     $edit = array(
       'file_test_replace' => FILE_EXISTS_REPLACE,
@@ -234,12 +225,12 @@ function testHandleDangerousFile() {
   function testHandleFileMunge() {
     // Ensure insecure uploads are disabled for this test.
     $this->config('system.file')->set('allow_insecure_uploads', 0)->save();
-    $this->image = file_move($this->image, $this->image->getFileUri() . '.foo.' . $this->imageExtension);
+    $this->image = file_move($this->image, $this->image->getFileUri() . '.foo.' . $this->image_extension);
 
     // Reset the hook counters to get rid of the 'move' we just called.
     file_test_reset();
 
-    $extensions = $this->imageExtension;
+    $extensions = $this->image_extension;
     $edit = array(
       'files[file_test_upload]' => drupal_realpath($this->image->getFileUri()),
       'extensions' => $extensions,
@@ -247,7 +238,7 @@ function testHandleFileMunge() {
 
     $munged_filename = $this->image->getFilename();
     $munged_filename = substr($munged_filename, 0, strrpos($munged_filename, '.'));
-    $munged_filename .= '_.' . $this->imageExtension;
+    $munged_filename .= '_.' . $this->image_extension;
 
     $this->drupalPostForm('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, 'Received a 200 response for posted test file.');
diff --git a/core/modules/file/src/Tests/ValidatorTest.php b/core/modules/file/src/Tests/ValidatorTest.php
index a17fa8f..304a84c 100644
--- a/core/modules/file/src/Tests/ValidatorTest.php
+++ b/core/modules/file/src/Tests/ValidatorTest.php
@@ -15,18 +15,14 @@
 class ValidatorTest extends FileManagedUnitTestBase {
 
   /**
-   * An image file.
-   *
-   * @var \Drupal\file\FileInterface
+   * @var \Drupal\file\Entity\File
    */
   protected $image;
 
   /**
-   * A file which is not an image.
-   *
    * @var \Drupal\file\Entity\File
    */
-  protected $nonImage;
+  protected $non_image;
 
   protected function setUp() {
     parent::setUp();
@@ -35,9 +31,9 @@ protected function setUp() {
     $this->image->setFileUri('core/misc/druplicon.png');
     $this->image->setFilename(drupal_basename($this->image->getFileUri()));
 
-    $this->nonImage = entity_create('file');
-    $this->nonImage->setFileUri('core/assets/vendor/jquery/jquery.min.js');
-    $this->nonImage->setFilename(drupal_basename($this->nonImage->getFileUri()));
+    $this->non_image = entity_create('file');
+    $this->non_image->setFileUri('core/assets/vendor/jquery/jquery.min.js');
+    $this->non_image->setFilename(drupal_basename($this->non_image->getFileUri()));
   }
 
   /**
@@ -61,8 +57,8 @@ function testFileValidateIsImage() {
     $errors = file_validate_is_image($this->image);
     $this->assertEqual(count($errors), 0, 'No error reported for our image file.', 'File');
 
-    $this->assertTrue(file_exists($this->nonImage->getFileUri()), 'The non-image being tested exists.', 'File');
-    $errors = file_validate_is_image($this->nonImage);
+    $this->assertTrue(file_exists($this->non_image->getFileUri()), 'The non-image being tested exists.', 'File');
+    $errors = file_validate_is_image($this->non_image);
     $this->assertEqual(count($errors), 1, 'An error reported for our non-image file.', 'File');
   }
 
@@ -72,9 +68,9 @@ function testFileValidateIsImage() {
    */
   function testFileValidateImageResolution() {
     // Non-images.
-    $errors = file_validate_image_resolution($this->nonImage);
+    $errors = file_validate_image_resolution($this->non_image);
     $this->assertEqual(count($errors), 0, 'Should not get any errors for a non-image file.', 'File');
-    $errors = file_validate_image_resolution($this->nonImage, '50x50', '100x100');
+    $errors = file_validate_image_resolution($this->non_image, '50x50', '100x100');
     $this->assertEqual(count($errors), 0, 'Do not check the resolution on non files.', 'File');
 
     // Minimum size.
diff --git a/core/modules/filter/filter.admin.js b/core/modules/filter/filter.admin.js
index ba650c8..959442a 100644
--- a/core/modules/filter/filter.admin.js
+++ b/core/modules/filter/filter.admin.js
@@ -10,7 +10,7 @@
   Drupal.behaviors.filterStatus = {
     attach: function (context, settings) {
       var $context = $(context);
-      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-status').each(function () {
+      $context.find('#filters-status-wrapper input.form-checkbox').once('filter-status', function () {
         var $checkbox = $(this);
         // Retrieve the tabledrag row belonging to this filter.
         var $row = $context.find('#' + $checkbox.attr('id').replace(/-status$/, '-weight')).closest('tr');
diff --git a/core/modules/filter/filter.filter_html.admin.js b/core/modules/filter/filter.filter_html.admin.js
index a74b938..a11fca5 100644
--- a/core/modules/filter/filter.filter_html.admin.js
+++ b/core/modules/filter/filter.filter_html.admin.js
@@ -55,7 +55,7 @@
 
     attach: function (context, settings) {
       var that = this;
-      $(context).find('[name="filters[filter_html][settings][allowed_html]"]').once('filter-filter_html-updating').each(function () {
+      $(context).find('[name="filters[filter_html][settings][allowed_html]"]').once('filter-filter_html-updating', function () {
         that.$allowedHTMLFormItem = $(this);
         that.$allowedHTMLDescription = that.$allowedHTMLFormItem.closest('.form-item').find('.description');
         that.userTags = that._parseSetting(this.value);
diff --git a/core/modules/filter/src/Plugin/DataType/FilterFormat.php b/core/modules/filter/src/Plugin/DataType/FilterFormat.php
index 74279f0..31ab7f7 100644
--- a/core/modules/filter/src/Plugin/DataType/FilterFormat.php
+++ b/core/modules/filter/src/Plugin/DataType/FilterFormat.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TypedData\OptionsProviderInterface;
-use Drupal\Core\TypedData\Plugin\DataType\StringData;
+use Drupal\Core\TypedData\Plugin\DataType\String;
 
 /**
  * The filter format data type.
@@ -19,7 +19,7 @@
  *   label = @Translation("Filter format")
  * )
  */
-class FilterFormat extends StringData implements OptionsProviderInterface {
+class FilterFormat extends String implements OptionsProviderInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php
index fe54ccd..3ceb5eb 100644
--- a/core/modules/filter/src/Tests/FilterAPITest.php
+++ b/core/modules/filter/src/Tests/FilterAPITest.php
@@ -8,7 +8,6 @@
 namespace Drupal\filter\Tests;
 
 use Drupal\Component\Utility\String;
-use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Session\AnonymousUserSession;
 use Drupal\Core\TypedData\OptionsProviderInterface;
 use Drupal\Core\TypedData\DataDefinition;
@@ -30,7 +29,7 @@ protected function setUp() {
     parent::setUp();
 
     $this->installSchema('system', array('router'));
-    $this->installConfig(array('system', 'filter', 'filter_test'));
+    $this->installConfig(array('system', 'filter'));
   }
 
   /**
@@ -261,7 +260,7 @@ function testProcessedTextElement() {
     $this->assertEqual($expected_cache_tags, $build['#cache']['tags'], 'Expected cache tags present.');
     $expected_cache_contexts = [
       // The cache context set by the filter_test_cache_contexts filter.
-      'languages:' . LanguageInterface::TYPE_CONTENT,
+      'language',
     ];
     $this->assertEqual($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.');
     $expected_markup = '<p>Hello, world!</p><p>This is a dynamic llama.</p>';
diff --git a/core/modules/filter/tests/filter_test/filter_test.info.yml b/core/modules/filter/tests/filter_test/filter_test.info.yml
index 6e377bc..dcefe8e 100644
--- a/core/modules/filter/tests/filter_test/filter_test.info.yml
+++ b/core/modules/filter/tests/filter_test/filter_test.info.yml
@@ -4,5 +4,3 @@ description: 'Tests filter hooks and functions.'
 package: Testing
 version: VERSION
 core: 8.x
-dependencies:
-  - filter
diff --git a/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestCacheContexts.php b/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestCacheContexts.php
index 3cb6de2..6a98956 100644
--- a/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestCacheContexts.php
+++ b/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestCacheContexts.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\filter_test\Plugin\Filter;
 
-use Drupal\Core\Language\LanguageInterface;
 use Drupal\filter\FilterProcessResult;
 use Drupal\filter\Plugin\FilterBase;
 
@@ -29,7 +28,7 @@ class FilterTestCacheContexts extends FilterBase {
   public function process($text, $langcode) {
     $result = new FilterProcessResult($text);
     // The changes made by this filter are language-specific.
-    $result->addCacheContexts(['languages:' . LanguageInterface::TYPE_CONTENT]);
+    $result->addCacheContexts(['language']);
     return $result;
   }
 
diff --git a/core/modules/forum/config/optional/rdf.mapping.node.forum.yml b/core/modules/forum/config/install/rdf.mapping.node.forum.yml
similarity index 100%
rename from core/modules/forum/config/optional/rdf.mapping.node.forum.yml
rename to core/modules/forum/config/install/rdf.mapping.node.forum.yml
diff --git a/core/modules/forum/config/optional/rdf.mapping.taxonomy_term.forums.yml b/core/modules/forum/config/install/rdf.mapping.taxonomy_term.forums.yml
similarity index 100%
rename from core/modules/forum/config/optional/rdf.mapping.taxonomy_term.forums.yml
rename to core/modules/forum/config/install/rdf.mapping.taxonomy_term.forums.yml
diff --git a/core/modules/forum/src/Plugin/Block/ForumBlockBase.php b/core/modules/forum/src/Plugin/Block/ForumBlockBase.php
index ec5431a..e5937ce 100644
--- a/core/modules/forum/src/Plugin/Block/ForumBlockBase.php
+++ b/core/modules/forum/src/Plugin/Block/ForumBlockBase.php
@@ -87,16 +87,7 @@ public function blockSubmit($form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function getCacheKeys() {
-    $keys = parent::getCacheKeys();
-    $keys[] = Cache::keyFromQuery($this->buildForumQuery());
-    return $keys;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheTags() {
-    return ['node_list'];
+    return array_merge(parent::getCacheKeys(), Cache::keyFromQuery($this->buildForumQuery()));
   }
 
 }
diff --git a/core/modules/hal/hal.services.yml b/core/modules/hal/hal.services.yml
index 7e40df0..4e89841 100644
--- a/core/modules/hal/hal.services.yml
+++ b/core/modules/hal/hal.services.yml
@@ -26,3 +26,7 @@ services:
     class: Drupal\hal\Encoder\JsonEncoder
     tags:
       - { name: encoder, priority: 10, format: hal_json }
+  hal.subscriber:
+    class: Drupal\hal\HalSubscriber
+    tags:
+      - { name: event_subscriber }
diff --git a/core/modules/hal/src/HalServiceProvider.php b/core/modules/hal/src/HalServiceProvider.php
deleted file mode 100644
index d8ac47f..0000000
--- a/core/modules/hal/src/HalServiceProvider.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\hal\HalServiceProvider.
- */
-
-namespace Drupal\hal;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceModifierInterface;
-
-/**
- * Adds hal+json as known format.
- */
-class HalServiceProvider implements ServiceModifierInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    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/HalSubscriber.php b/core/modules/hal/src/HalSubscriber.php
new file mode 100644
index 0000000..93a70bb
--- /dev/null
+++ b/core/modules/hal/src/HalSubscriber.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\hal\HalSubscriber.
+ */
+
+namespace Drupal\hal;
+
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Subscribes to the kernel request event to add HAL media types.
+ */
+class HalSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Registers HAL formats with the Request class.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   *   The event to process.
+   */
+  public function onKernelRequest(GetResponseEvent $event) {
+    $request = $event->getRequest();
+    $request->setFormat('hal_json', 'application/hal+json');
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::REQUEST][] = array('onKernelRequest', 40);
+    return $events;
+  }
+
+}
diff --git a/core/modules/hal/src/Tests/EntityTest.php b/core/modules/hal/src/Tests/EntityTest.php
index 9fb1014..a1b221d 100644
--- a/core/modules/hal/src/Tests/EntityTest.php
+++ b/core/modules/hal/src/Tests/EntityTest.php
@@ -35,7 +35,6 @@ protected function setUp() {
     $this->installSchema('system', array('sequences'));
     $this->installSchema('comment', array('comment_entity_statistics'));
     $this->installEntitySchema('taxonomy_term');
-    $this->installConfig(['node', 'comment']);
   }
 
   /**
diff --git a/core/modules/help/src/Plugin/Block/HelpBlock.php b/core/modules/help/src/Plugin/Block/HelpBlock.php
index 968fca6..7038c9d 100644
--- a/core/modules/help/src/Plugin/Block/HelpBlock.php
+++ b/core/modules/help/src/Plugin/Block/HelpBlock.php
@@ -127,7 +127,18 @@ public function build() {
   /**
    * {@inheritdoc}
    */
-  public function getCacheContexts() {
+  public function defaultConfiguration() {
+    // Modify the default max age for the Help block: help text is
+    // static for a given URL, except when a module is updated, in which case
+    // update.php must be run, which clears all caches. Thus it's safe to cache
+    // the output for this block forever on a per-URL basis.
+    return array('cache' => array('max_age' => \Drupal\Core\Cache\Cache::PERMANENT));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getRequiredCacheContexts() {
     // The "Help" block must be cached per URL: help is defined for a
     // given path, and does not come with any access restrictions.
     return array('url');
diff --git a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
index ced9679..7358f10 100644
--- a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
@@ -76,8 +76,8 @@ public static function defaultStorageSettings() {
   public static function defaultFieldSettings() {
     $settings = array(
       'file_extensions' => 'png gif jpg jpeg',
-      'alt_field' => 1,
-      'alt_field_required' => 1,
+      'alt_field' => 0,
+      'alt_field_required' => 0,
       'title_field' => 0,
       'title_field_required' => 0,
       'max_resolution' => '',
@@ -263,7 +263,7 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#type' => 'checkbox',
       '#title' => t('Enable <em>Alt</em> field'),
       '#default_value' => $settings['alt_field'],
-      '#description' => t('The alt attribute may be used by search engines, screen readers, and when the image cannot be loaded. Enabling this field is recommended.'),
+      '#description' => t('The alt attribute may be used by search engines, screen readers, and when the image cannot be loaded. Enabling this field is recommended'),
       '#weight' => 9,
     );
     $element['alt_field_required'] = array(
diff --git a/core/modules/image/src/Tests/ImageAdminStylesTest.php b/core/modules/image/src/Tests/ImageAdminStylesTest.php
index 3486e49..df068ee 100644
--- a/core/modules/image/src/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
@@ -296,7 +296,7 @@ function testStyleReplacement() {
 
     // Create a new node with an image attached.
     $test_image = current($this->drupalGetTestFiles('image'));
-    $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName());
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
     $node = Node::load($nid);
 
     // Get node field original image URI.
@@ -430,7 +430,7 @@ function testConfigImport() {
 
     // Create a new node with an image attached.
     $test_image = current($this->drupalGetTestFiles('image'));
-    $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName());
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
     $node = Node::load($nid);
 
     // Get node field original image URI.
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index 29fbce3..368f7f6 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -49,8 +49,7 @@ function testImageFieldFormattersPrivate() {
   function _testImageFieldFormatters($scheme) {
     $node_storage = $this->container->get('entity.manager')->getStorage('node');
     $field_name = strtolower($this->randomMachineName());
-    $field_settings = array('alt_field_required' => 0);
-    $instance = $this->createImageField($field_name, 'article', array('uri_scheme' => $scheme), $field_settings);
+    $this->createImageField($field_name, 'article', array('uri_scheme' => $scheme));
 
     // Go to manage display page.
     $this->drupalGet("admin/structure/types/manage/article/display");
@@ -79,16 +78,8 @@ function _testImageFieldFormatters($scheme) {
     // Ensure that preview works.
     $this->previewNodeImage($test_image, $field_name, 'article');
 
-    // After previewing, make the alt field required. It cannot be required
-    // during preview because the form validation will fail.
-    $instance->settings['alt_field_required'] = 1;
-    $instance->save();
-
-    // Create alt text for the image.
-    $alt = $this->randomMachineName();
-
     // Save node.
-    $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt);
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
     $node_storage->resetCache(array($nid));
     $node = $node_storage->load($nid);
 
@@ -99,7 +90,6 @@ function _testImageFieldFormatters($scheme) {
       '#uri' => $image_uri,
       '#width' => 40,
       '#height' => 20,
-      '#alt' => $alt,
     );
     $default_output = str_replace("\n", NULL, drupal_render($image));
     $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.');
@@ -118,7 +108,6 @@ function _testImageFieldFormatters($scheme) {
       '#uri' => $image_uri,
       '#width' => 40,
       '#height' => 20,
-      '#alt' => $alt,
     );
     $default_output = '<a href="' . file_create_url($image_uri) . '">' . drupal_render($image) . '</a>';
     $this->drupalGet('node/' . $nid);
@@ -156,13 +145,12 @@ function _testImageFieldFormatters($scheme) {
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $elements = $this->xpath(
-      '//a[@href=:path]/img[@src=:url and @alt=:alt and @width=:width and @height=:height]',
+      '//a[@href=:path]/img[@src=:url and @alt="" and @width=:width and @height=:height]',
       array(
         ':path' => $node->url(),
         ':url' => file_create_url($image['#uri']),
         ':width' => $image['#width'],
         ':height' => $image['#height'],
-        ':alt' => $alt,
       )
     );
     $this->assertEqual(count($elements), 1, 'Image linked to content formatter displaying correctly on full node view.');
@@ -182,7 +170,6 @@ function _testImageFieldFormatters($scheme) {
       '#width' => 40,
       '#height' => 20,
       '#style_name' => 'thumbnail',
-      '#alt' => $alt,
     );
     $default_output = drupal_render($image_style);
     $this->drupalGet('node/' . $nid);
@@ -234,11 +221,7 @@ function testImageFieldSettings() {
 
     // We have to create the article first and then edit it because the alt
     // and title fields do not display until the image has been attached.
-
-    // Create alt text for the image.
-    $alt = $this->randomMachineName();
-
-    $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt);
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
     $this->drupalGet('node/' . $nid . '/edit');
     $this->assertFieldByName($field_name . '[0][alt]', '', 'Alt field displayed on article form.');
     $this->assertFieldByName($field_name . '[0][title]', '', 'Title field displayed on article form.');
@@ -260,7 +243,7 @@ function testImageFieldSettings() {
     $image = array(
       '#theme' => 'image',
       '#uri' => file_load($node->{$field_name}->target_id)->getFileUri(),
-      '#alt' => $alt,
+      '#alt' => $this->randomMachineName(),
       '#title' => $this->randomMachineName(),
       '#width' => 40,
       '#height' => 20,
@@ -298,19 +281,15 @@ function testImageFieldSettings() {
     // providing all settings, even if they are not used.
     // @see FileWidget::formMultipleElements().
     $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $field_name . '/storage', array('field_storage[cardinality]' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED), t('Save field settings'));
-    $edit = array(
-      'files[' . $field_name . '_1][]' => drupal_realpath($test_image->uri),
-    );
+    $edit = array();
+    $edit['files[' . $field_name . '_1][]'] = drupal_realpath($test_image->uri);
     $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
-    // Add the required alt text.
-    $this->drupalPostForm(NULL, [$field_name . '[1][alt]' => $alt], t('Save and keep published'));
     $this->assertText(format_string('Article @title has been updated.', array('@title' => $node->getTitle())));
 
     // Assert ImageWidget::process() calls FieldWidget::process().
     $this->drupalGet('node/' . $node->id() . '/edit');
-    $edit = array(
-      'files[' . $field_name . '_2][]' => drupal_realpath($test_image->uri),
-    );
+    $edit = array();
+    $edit['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="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">');
@@ -367,11 +346,7 @@ function testImageFieldDefaultImage() {
 
     // Create a node with an image attached and ensure that the default image
     // is not displayed.
-
-    // Create alt text for the image.
-    $alt = $this->randomMachineName();
-
-    $nid = $this->uploadNodeImage($images[1], $field_name, 'article', $alt);
+    $nid = $this->uploadNodeImage($images[1], $field_name, 'article');
     $node_storage->resetCache(array($nid));
     $node = $node_storage->load($nid);
     $image = array(
@@ -379,7 +354,6 @@ function testImageFieldDefaultImage() {
       '#uri' => file_load($node->{$field_name}->target_id)->getFileUri(),
       '#width' => 40,
       '#height' => 20,
-      '#alt' => $alt,
     );
     $image_output = str_replace("\n", NULL, drupal_render($image));
     $this->drupalGet('node/' . $nid);
diff --git a/core/modules/image/src/Tests/ImageFieldTestBase.php b/core/modules/image/src/Tests/ImageFieldTestBase.php
index ae3f10a..d8bee12 100644
--- a/core/modules/image/src/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/src/Tests/ImageFieldTestBase.php
@@ -129,19 +129,13 @@ function previewNodeImage($image, $field_name, $type) {
    *   Name of the image field the image should be attached to.
    * @param $type
    *   The type of node to create.
-   * @param $alt
-   *  The alt text for the image. Use if the field settings require alt text.
    */
-  function uploadNodeImage($image, $field_name, $type, $alt = '') {
+  function uploadNodeImage($image, $field_name, $type) {
     $edit = array(
       'title[0][value]' => $this->randomMachineName(),
     );
     $edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri);
     $this->drupalPostForm('node/add/' . $type, $edit, t('Save and publish'));
-    if ($alt) {
-      // Add alt text.
-      $this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save and publish'));
-    }
 
     // Retrieve ID of the newly created node from the current URL.
     $matches = array();
diff --git a/core/modules/image/src/Tests/ImageFieldValidateTest.php b/core/modules/image/src/Tests/ImageFieldValidateTest.php
index fa52d06..e6afc32 100644
--- a/core/modules/image/src/Tests/ImageFieldValidateTest.php
+++ b/core/modules/image/src/Tests/ImageFieldValidateTest.php
@@ -23,7 +23,6 @@ function testResolution() {
     $field_settings = array(
       'max_resolution' => $max_resolution . 'x' . $max_resolution,
       'min_resolution' => $min_resolution . 'x' . $min_resolution,
-      'alt_field' => 0,
     );
     $this->createImageField($field_name, 'article', array(), $field_settings);
 
diff --git a/core/modules/language/config/optional/tour.tour.language-add.yml b/core/modules/language/config/install/tour.tour.language-add.yml
similarity index 100%
rename from core/modules/language/config/optional/tour.tour.language-add.yml
rename to core/modules/language/config/install/tour.tour.language-add.yml
diff --git a/core/modules/language/config/optional/tour.tour.language-edit.yml b/core/modules/language/config/install/tour.tour.language-edit.yml
similarity index 100%
rename from core/modules/language/config/optional/tour.tour.language-edit.yml
rename to core/modules/language/config/install/tour.tour.language-edit.yml
diff --git a/core/modules/language/config/optional/tour.tour.language.yml b/core/modules/language/config/install/tour.tour.language.yml
similarity index 100%
rename from core/modules/language/config/optional/tour.tour.language.yml
rename to core/modules/language/config/install/tour.tour.language.yml
diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml
index b9de79a..77c0328 100644
--- a/core/modules/language/language.services.yml
+++ b/core/modules/language/language.services.yml
@@ -4,7 +4,7 @@ services:
     arguments: ['@container.namespaces', '@cache.discovery', '@module_handler']
   language_negotiator:
     class: Drupal\language\LanguageNegotiator
-    arguments: ['@language_manager', '@plugin.manager.language_negotiation_method', '@config.factory', '@settings', '@request_stack']
+    arguments: ['@language_manager', '@plugin.manager.language_negotiation_method', '@config.factory', '@request_stack']
     calls:
       - [initLanguageManager]
   language.config_subscriber:
diff --git a/core/modules/language/src/EventSubscriber/ConfigSubscriber.php b/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
index ef3f65d..2b1c73c 100644
--- a/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
+++ b/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
@@ -54,8 +54,8 @@ public function __construct(LanguageManagerInterface $language_manager, Language
    */
   public function onConfigSave(ConfigCrudEvent $event) {
     $saved_config = $event->getConfig();
-    if ($saved_config->getName() == 'system.site' && $event->isChanged('default_langcode')) {
-      $language = $this->languageManager->getLanguage($saved_config->get('default_langcode'));
+    if ($saved_config->getName() == 'system.site' && $event->isChanged('langcode')) {
+      $language = $this->languageManager->getLanguage($saved_config->get('langcode'));
       // During an import the language might not exist yet.
       if ($language) {
         $this->languageDefault->set($language);
diff --git a/core/modules/language/src/LanguageListBuilder.php b/core/modules/language/src/LanguageListBuilder.php
index aa018dc..b8f6454 100644
--- a/core/modules/language/src/LanguageListBuilder.php
+++ b/core/modules/language/src/LanguageListBuilder.php
@@ -152,7 +152,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     // Save the default language if changed.
     $new_id = $form_state->getValue('site_default_language');
     if ($new_id != $this->languageManager->getDefaultLanguage()->getId()) {
-      $this->configFactory->getEditable('system.site')->set('default_langcode', $new_id)->save();
+      $this->configFactory->getEditable('system.site')->set('langcode', $new_id)->save();
       $this->languageManager->reset();
     }
 
diff --git a/core/modules/language/src/LanguageNegotiator.php b/core/modules/language/src/LanguageNegotiator.php
index bc924fb..6afdf38 100644
--- a/core/modules/language/src/LanguageNegotiator.php
+++ b/core/modules/language/src/LanguageNegotiator.php
@@ -41,13 +41,6 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
   protected $configFactory;
 
   /**
-   * The settings instance.
-   *
-   * @return \Drupal\Core\Site\Settings
-   */
-  protected $settings;
-
-  /**
    * The request stack object.
    *
    * @var \Symfony\Component\HttpFoundation\RequestStack
@@ -84,14 +77,11 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
    *   The language negotiation methods plugin manager
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The configuration factory.
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The settings instance.
    */
-  public function __construct(ConfigurableLanguageManagerInterface $language_manager, PluginManagerInterface $negotiator_manager, ConfigFactoryInterface $config_factory, Settings $settings, RequestStack $requestStack) {
+  public function __construct(ConfigurableLanguageManagerInterface $language_manager, PluginManagerInterface $negotiator_manager, ConfigFactoryInterface $config_factory, RequestStack $requestStack) {
     $this->languageManager = $language_manager;
     $this->negotiatorManager = $negotiator_manager;
     $this->configFactory = $config_factory;
-    $this->settings = $settings;
     $this->requestStack = $requestStack;
   }
 
@@ -190,7 +180,7 @@ protected function negotiateLanguage($type, $method_id) {
     if (!isset($method['types']) || in_array($type, $method['types'])) {
 
       // Check for a cache mode force from settings.php.
-      if ($this->settings->get('page_cache_without_database')) {
+      if (Settings::get('page_cache_without_database')) {
         $cache_enabled = TRUE;
       }
       else {
diff --git a/core/modules/language/src/LanguageServiceProvider.php b/core/modules/language/src/LanguageServiceProvider.php
index de2fa6f..d7c4ddd 100644
--- a/core/modules/language/src/LanguageServiceProvider.php
+++ b/core/modules/language/src/LanguageServiceProvider.php
@@ -97,7 +97,7 @@ protected function isMultilingual() {
   protected function getDefaultLanguageValues() {
     $config_storage = BootstrapConfigStorageFactory::get();
     $system = $config_storage->read('system.site');
-    $default_language = $config_storage->read(static::CONFIG_PREFIX . $system['default_langcode']);
+    $default_language = $config_storage->read(static::CONFIG_PREFIX . $system['langcode']);
     if (is_array($default_language)) {
       return $default_language;
     }
diff --git a/core/modules/language/src/Plugin/Block/LanguageBlock.php b/core/modules/language/src/Plugin/Block/LanguageBlock.php
index 7aa9bb8..e86f263 100644
--- a/core/modules/language/src/Plugin/Block/LanguageBlock.php
+++ b/core/modules/language/src/Plugin/Block/LanguageBlock.php
@@ -107,13 +107,4 @@ public function build() {
     return $build;
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Make cacheable in https://drupal.org/node/2232375.
-   */
-  public function getCacheMaxAge() {
-    return 0;
-  }
-
 }
diff --git a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
index 1d4ee27..f4e1378 100644
--- a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
+++ b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
@@ -116,7 +116,7 @@ public function testDefaultLangcode() {
     $configurable_language = entity_load('configurable_language', $old_default->getId());
     $this->assertTrue($configurable_language->isDefault(), 'The en language entity is flagged as the default language.');
 
-    $this->config('system.site')->set('default_langcode', 'cc')->save();
+    $this->config('system.site')->set('langcode', 'cc')->save();
     ContentLanguageSettings::loadByEntityTypeBundle('entity_test','custom_bundle')
       ->setLanguageAlterable(TRUE)
       ->setDefaultLangcode(LanguageInterface::LANGCODE_SITE_DEFAULT)
diff --git a/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php b/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php
index 46b3041..1a7a815 100644
--- a/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php
+++ b/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php
@@ -43,7 +43,7 @@ function testDependencyInjectedNewDefaultLanguage() {
     $default_language = ConfigurableLanguage::load(\Drupal::languageManager()->getDefaultLanguage()->getId());
     // Change the language default object to different values.
     ConfigurableLanguage::createFromLangcode('fr')->save();
-    $this->config('system.site')->set('default_langcode', 'fr')->save();
+    $this->config('system.site')->set('langcode', 'fr')->save();
 
     // The language system creates a Language object which contains the
     // same properties as the new default language object.
@@ -60,7 +60,7 @@ function testDependencyInjectedNewDefaultLanguage() {
     }
 
     // Re-save the previous default language and the delete should work.
-    $this->config('system.site')->set('default_langcode', $default_language->getId())->save();
+    $this->config('system.site')->set('langcode', $default_language->getId())->save();
 
     entity_delete_multiple('configurable_language', array('fr'));
     $result = \Drupal::languageManager()->getCurrentLanguage();
diff --git a/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php
index 99d4778..f801b6a 100644
--- a/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php
+++ b/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php
@@ -93,7 +93,7 @@ function testUILanguageNegotiation() {
     // be some bug.
     $default_language = \Drupal::languageManager()->getDefaultLanguage();
     ConfigurableLanguage::createFromLangcode($langcode_browser_fallback)->save();
-    $this->config('system.site')->set('default_langcode', $langcode_browser_fallback)->save();
+    $this->config('system.site')->set('langcode', $langcode_browser_fallback)->save();
     ConfigurableLanguage::createFromLangcode($langcode)->save();
 
     // We will look for this string in the admin/config screen to see if the
@@ -106,7 +106,7 @@ function testUILanguageNegotiation() {
     // Now the t()'ed string is in db so switch the language back to default.
     // This will rebuild the container so we need to rebuild the container in
     // the test environment.
-    $this->config('system.site')->set('default_langcode', $default_language->getId())->save();
+    $this->config('system.site')->set('langcode', $default_language->getId())->save();
     $this->config('language.negotiation')->set('url.prefixes.en', '')->save();
     $this->rebuildContainer();
 
diff --git a/core/modules/locale/config/optional/tour.tour.locale.yml b/core/modules/locale/config/install/tour.tour.locale.yml
similarity index 100%
rename from core/modules/locale/config/optional/tour.tour.locale.yml
rename to core/modules/locale/config/install/tour.tour.locale.yml
diff --git a/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php b/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
index ef53b8c..0522010 100644
--- a/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
+++ b/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
@@ -32,7 +32,7 @@ public function setUp() {
 
     // Change the language default object to different values.
     ConfigurableLanguage::createFromLangcode('fr')->save();
-    $this->config('system.site')->set('default_langcode', 'fr')->save();
+    $this->config('system.site')->set('langcode', 'fr')->save();
 
     $this->drupalLogin($this->rootUser);
   }
diff --git a/core/modules/locale/src/Tests/LocalePluralFormatTest.php b/core/modules/locale/src/Tests/LocalePluralFormatTest.php
index bb8674a..e6b51f1 100644
--- a/core/modules/locale/src/Tests/LocalePluralFormatTest.php
+++ b/core/modules/locale/src/Tests/LocalePluralFormatTest.php
@@ -131,11 +131,6 @@ public function testGetPluralFormat() {
         $expected_plural_index = ($count == 1) ? 0 : $expected_plural_index;
         $expected_plural_string = str_replace('@count', $count, $plural_strings[$langcode][$expected_plural_index]);
         $this->assertIdentical(\Drupal::translation()->formatPlural($count, '1 hour', '@count hours', array(), array('langcode' => $langcode)), $expected_plural_string, 'Plural translation of 1 hours / @count hours for count ' . $count . ' in ' . $langcode . ' is ' . $expected_plural_string);
-        // DO NOT use translation to pass into formatPluralTranslated() this
-        // way. It is designed to be used with *already* translated text like
-        // settings from configuration. We use PHP translation here just because
-        // we have the expected result data in that format.
-        $this->assertIdentical(\Drupal::translation()->formatPluralTranslated($count, \Drupal::translation()->translate('1 hour' . LOCALE_PLURAL_DELIMITER . '@count hours', array(), array('langcode' => $langcode)), array(), array('langcode' => $langcode)), $expected_plural_string, 'Translated plural lookup of 1 hours / @count hours for count ' . $count . ' in ' . $langcode . ' is ' . $expected_plural_string);
       }
     }
   }
diff --git a/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php b/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php
index a5786b1..f94db02 100644
--- a/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php
+++ b/core/modules/locale/src/Tests/LocaleTranslatedSchemaDefinitionTest.php
@@ -30,7 +30,7 @@ class LocaleTranslatedSchemaDefinitionTest extends WebTestBase {
   protected function setUp() {
     parent::setUp();
     ConfigurableLanguage::createFromLangcode('fr')->save();
-    $this->config('system.site')->set('default_langcode', 'fr')->save();
+    $this->config('system.site')->set('langcode', 'fr')->save();
     // Make sure new entity type definitions are processed.
     \Drupal::service('entity.definition_update_manager')->applyUpdates();
     // Clear all caches so that the base field definition, its cache in the
diff --git a/core/modules/menu_ui/menu_ui.admin.js b/core/modules/menu_ui/menu_ui.admin.js
index 06a9f34..4a04ab0 100644
--- a/core/modules/menu_ui/menu_ui.admin.js
+++ b/core/modules/menu_ui/menu_ui.admin.js
@@ -4,15 +4,15 @@
 
   Drupal.behaviors.menuUiChangeParentItems = {
     attach: function (context, settings) {
-      var $menu = $('#edit-menu').once('menu-parent');
-      if ($menu.length) {
+      var $menu = $('#edit-menu');
+      $menu.once('menu-parent', function () {
         // Update the list of available parent menu items to match the initial
         // available menus.
         Drupal.menuUiUpdateParentList();
 
         // Update list of available parent menu items.
         $menu.on('change', 'input', Drupal.menuUiUpdateParentList);
-      }
+      });
     }
   };
 
diff --git a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php b/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
index 085722f..59b0458 100644
--- a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
@@ -155,7 +155,7 @@ function testMenuLanguageRemovedEnglish() {
 
     // Remove English language. To do that another language has to be set as
     // default.
-    $this->config('system.site')->set('default_langcode', 'cs')->save();
+    $this->config('system.site')->set('langcode', 'cs')->save();
     entity_delete_multiple('configurable_language', array('en'));
 
     // Save the menu again and check if the language is still the same.
diff --git a/core/modules/menu_ui/src/Tests/MenuTest.php b/core/modules/menu_ui/src/Tests/MenuTest.php
index 9834792..5cb6563 100644
--- a/core/modules/menu_ui/src/Tests/MenuTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuTest.php
@@ -578,6 +578,12 @@ public function testBlockContextualLinks() {
     $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="entitymenuedit-form"><a href="' . base_path() . 'admin/structure/menu/manage/' . $custom_menu->id() . '">Edit menu</a></li></ul>');
+
+    // Test the contextual links are available when block caching is enabled.
+    $this->drupalPostForm('admin/structure/block/manage/' . $block->id(), ['settings[cache][max_age]' => Cache::PERMANENT], t('Save block'));
+    $this->drupalGet('test-page');
+    $id = 'block:block=' . $block->id() . ':|menu:menu=' . $custom_menu->id() . ':';
+    $this->assertRaw('<div data-contextual-id="'. $id . '"></div>', format_string('Contextual link placeholder with id @id exists.', array('@id' => $id)));
   }
 
   /**
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_user.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_user.yml
index 99302ec..7864f09 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_user.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_user.yml
@@ -22,6 +22,22 @@ process:
     plugin: migration
     migration: d6_user_role
     source: roles
+  signature: signature
+  signature_format:
+    -
+# Drupal 6 stores 0 as the signature format when signatures are disabled.
+# Drupal 8 stores a NULL.
+      plugin: static_map
+      bypass: true
+      source: signature_format
+      map:
+        0: NULL
+    -
+# Do not try to migrate the NULL format.
+      plugin: skip_process_on_empty
+    -
+      plugin: migration
+      migration: d6_filter_format
   user_picture:
     plugin: d6_user_picture
     source: uid
@@ -30,6 +46,7 @@ destination:
   md5_passwords: true
 migration_dependencies:
   required:
+    - d6_filter_format
     - d6_user_role
   optional:
     - d6_user_picture_file
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_user_settings.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_user_settings.yml
index 274288b..557dc8c 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_user_settings.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_user_settings.yml
@@ -7,12 +7,14 @@ source:
   variables:
     - user_mail_status_blocked_notify
     - user_mail_status_activated_notify
+    - user_signatures
     - user_email_verification
     - user_register
     - anonymous
 process:
   'notify/status_blocked': user_mail_status_blocked_notify
   'notify/status_activated': user_mail_status_activated_notify
+  signatures: user_signatures
   verify_mail: user_email_verification
   register:
     plugin: static_map
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php b/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php
index 22fec2f..f04672d 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php
@@ -134,9 +134,8 @@ protected function processTextField($field_name, $field_data, MigrationInterface
 
     $migration->setProcessOfProperty("$field_name/value", $value_key);
 
-    // See \Drupal\migrate_drupal\Plugin\migrate\source\d6\User::baseFields(),
-    // signature_format for an example of the YAML that represents this
-    // process array.
+    // See d6_user, signature_format for an example of the YAML that
+    // represents this process array.
     $process = [
       [
         'plugin' => 'static_map',
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateUserConfigsTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateUserConfigsTest.php
index 0c9636a..21396c6 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateUserConfigsTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateUserConfigsTest.php
@@ -67,6 +67,7 @@ public function testUserSettings() {
     $config = $this->config('user.settings');
     $this->assertIdentical(TRUE, $config->get('notify.status_blocked'));
     $this->assertIdentical(FALSE, $config->get('notify.status_activated'));
+    $this->assertIdentical(TRUE, $config->get('signatures'));
     $this->assertIdentical(FALSE, $config->get('verify_mail'));
     $this->assertIdentical('admin_only', $config->get('register'));
     $this->assertIdentical('Guest', $config->get('anonymous'));
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateUserTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateUserTest.php
index 5ed9a9b..24ac4f9 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateUserTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateUserTest.php
@@ -100,6 +100,11 @@ protected function setUp() {
     $this->loadDumps($dumps);
 
     $id_mappings = array(
+      'd6_filter_format' => array(
+        array(array(1), array('filtered_html')),
+        array(array(2), array('full_html')),
+        array(array(3), array('escape_html_filter')),
+      ),
       'd6_user_role' => array(
         array(array(1), array('anonymous user')),
         array(array(2), array('authenticated user')),
@@ -151,11 +156,16 @@ public function testUser() {
         $role = $migration_role->getIdMap()->lookupDestinationId(array($rid));
         $roles[] = reset($role);
       }
+      // Get the user signature format.
+      $migration_format = entity_load('migration', 'd6_filter_format');
+      $signature_format = $source->signature_format === '0' ? [NULL] : $migration_format->getIdMap()->lookupDestinationId(array($source->signature_format));
 
       $user = User::load($source->uid);
       $this->assertIdentical($source->uid, $user->id());
       $this->assertIdentical($source->name, $user->label());
       $this->assertIdentical($source->mail, $user->getEmail());
+      $this->assertIdentical($source->signature, $user->getSignature());
+      $this->assertIdentical(reset($signature_format), $user->getSignatureFormat());
       $this->assertIdentical($source->created, $user->getCreatedTime());
       $this->assertIdentical($source->access, $user->getLastAccessedTime());
       $this->assertIdentical($source->login, $user->getLastLoginTime());
diff --git a/core/modules/node/config/optional/search.page.node_search.yml b/core/modules/node/config/install/search.page.node_search.yml
similarity index 100%
rename from core/modules/node/config/optional/search.page.node_search.yml
rename to core/modules/node/config/install/search.page.node_search.yml
diff --git a/core/modules/node/config/optional/views.view.archive.yml b/core/modules/node/config/install/views.view.archive.yml
similarity index 100%
rename from core/modules/node/config/optional/views.view.archive.yml
rename to core/modules/node/config/install/views.view.archive.yml
diff --git a/core/modules/node/config/optional/views.view.content.yml b/core/modules/node/config/install/views.view.content.yml
similarity index 100%
rename from core/modules/node/config/optional/views.view.content.yml
rename to core/modules/node/config/install/views.view.content.yml
diff --git a/core/modules/node/config/optional/views.view.content_recent.yml b/core/modules/node/config/install/views.view.content_recent.yml
similarity index 99%
rename from core/modules/node/config/optional/views.view.content_recent.yml
rename to core/modules/node/config/install/views.view.content_recent.yml
index 7cd39e1..c769ff4 100644
--- a/core/modules/node/config/optional/views.view.content_recent.yml
+++ b/core/modules/node/config/install/views.view.content_recent.yml
@@ -427,5 +427,3 @@ display:
     id: block_1
     display_title: Block
     position: 1
-    display_options:
-      display_extenders: {  }
diff --git a/core/modules/node/config/optional/views.view.frontpage.yml b/core/modules/node/config/install/views.view.frontpage.yml
similarity index 100%
rename from core/modules/node/config/optional/views.view.frontpage.yml
rename to core/modules/node/config/install/views.view.frontpage.yml
diff --git a/core/modules/node/config/optional/views.view.glossary.yml b/core/modules/node/config/install/views.view.glossary.yml
similarity index 100%
rename from core/modules/node/config/optional/views.view.glossary.yml
rename to core/modules/node/config/install/views.view.glossary.yml
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index fa0d245..034da3b 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -26,13 +26,14 @@ function node_requirements($phase) {
     else {
       $value = t('Disabled');
     }
+    $description = t('If the site is experiencing problems with permissions to content, you may have to rebuild the permissions cache. Rebuilding will remove all privileges to content and replace them with permissions based on the current modules and settings. Rebuilding may take some time if there is a lot of content or complex permission settings. After rebuilding has completed, content will automatically use the new permissions.');
 
     $requirements['node_access'] = array(
       'title' => t('Node Access Permissions'),
       'value' => $value,
-      'description' => t('If the site is experiencing problems with permissions to content, you may have to rebuild the permissions cache. Rebuilding will remove all privileges to content and replace them with permissions based on the current modules and settings. Rebuilding may take some time if there is a lot of content or complex permission settings. After rebuilding has completed, content will automatically use the new permissions. <a href="@rebuild">Rebuild permissions</a>', array(
-        '@rebuild' => \Drupal::url('node.configure_rebuild_confirm'),
-      )),
+      // The result of t() is safe and so is the result of l(). Preserving
+      // safe object.
+      'description' => SafeMarkup::set($description . ' ' . \Drupal::l(t('Rebuild permissions'), new Url('node.configure_rebuild_confirm'))),
     );
   }
   return $requirements;
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index eb222b4..f181df1 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -11,7 +11,6 @@
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Cache\Cache;
 use Drupal\Core\Database\Query\AlterableInterface;
 use Drupal\Core\Database\Query\SelectInterface;
 use Drupal\Core\Database\StatementInterface;
@@ -189,17 +188,15 @@ function node_entity_view_display_alter(EntityViewDisplayInterface $display, $co
 function node_title_list(StatementInterface $result, $title = NULL) {
   $items = array();
   $num_rows = FALSE;
-  $nids = [];
   foreach ($result as $row) {
     // Do not use $node->label() or $node->urlInfo() here, because we only have
     // database rows, not actual nodes.
-    $nids[] = $row->nid;
     $options = !empty($row->comment_count) ? array('attributes' => array('title' => \Drupal::translation()->formatPlural($row->comment_count, '1 comment', '@count comments'))) : array();
     $items[] = \Drupal::l($row->title, new Url('entity.node.canonical', ['node' => $row->nid], $options));
     $num_rows = TRUE;
   }
 
-  return $num_rows ? array('#theme' => 'item_list__node', '#items' => $items, '#title' => $title, '#cache' => ['tags' => Cache::mergeTags(['node_list'], Cache::buildTags('node', $nids))]) : FALSE;
+  return $num_rows ? array('#theme' => 'item_list__node', '#items' => $items, '#title' => $title) : FALSE;
 }
 
 /**
diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml
index f3e54fb..b2585d9 100644
--- a/core/modules/node/node.services.yml
+++ b/core/modules/node/node.services.yml
@@ -39,8 +39,8 @@ services:
     arguments: ['@current_route_match']
     tags:
       - { name: page_cache_response_policy }
-  cache_context.user.node_grants:
-    class: Drupal\node\Cache\NodeAccessGrantsCacheContext
+  cache_context.node_view_grants:
+    class: Drupal\node\Cache\NodeAccessViewGrantsCacheContext
     arguments: ['@current_user']
     tags:
       - { name: cache.context }
diff --git a/core/modules/node/src/Cache/NodeAccessGrantsCacheContext.php b/core/modules/node/src/Cache/NodeAccessGrantsCacheContext.php
deleted file mode 100644
index e213c40..0000000
--- a/core/modules/node/src/Cache/NodeAccessGrantsCacheContext.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Cache\NodeAccessGrantsCacheContext.
- */
-
-namespace Drupal\node\Cache;
-
-use Drupal\Core\Cache\CalculatedCacheContextInterface;
-use Drupal\Core\Cache\UserCacheContext;
-
-/**
- * Defines the node access view cache context service.
- *
- * This allows for node access grants-sensitive caching when listing nodes.
- *
- * @see node_query_node_access_alter()
- */
-class NodeAccessGrantsCacheContext extends UserCacheContext implements CalculatedCacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t("Content access view grants");
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($operation = NULL) {
-    // If the current user either can bypass node access then we don't need to
-    // determine the exact node grants for the current user.
-    if ($this->user->hasPermission('bypass node access')) {
-      return 'all';
-    }
-
-    // When no specific operation is specified, check the grants for all three
-    // possible operations.
-    if ($operation === NULL) {
-      $result = [];
-      foreach (['view', 'update', 'delete'] as $op) {
-        $result[] = $this->checkNodeGrants($op);
-      }
-      return implode('-', $result);
-    }
-    else {
-      return $this->checkNodeGrants($operation);
-    }
-  }
-
-  /**
-   * Checks the node grants for the given operation.
-   *
-   * @param string $operation
-   *   The operation to check the node grants for.
-   *
-   * @return string
-   *   The string representation of the cache context.
-   */
-  protected function checkNodeGrants($operation) {
-    // When checking the grants for the 'view' operation and the current user
-    // has a global view grant (i.e. a view grant for node ID 0) — note that
-    // this is automatically the case if no node access modules exist (no
-    // hook_node_grants() implementations) then we don't need to determine the
-    // exact node view grants for the current user.
-    if ($operation === 'view' && node_access_view_all_nodes($this->user)) {
-      return 'view.all';
-    }
-
-    $grants = node_access_grants($operation, $this->user);
-    $grants_context_parts = [];
-    foreach ($grants as $realm => $gids) {
-      $grants_context_parts[] = $realm . ':' . implode(',', $gids);
-    }
-    return $operation . '.' . implode(';', $grants_context_parts);
-  }
-
-}
diff --git a/core/modules/node/src/Cache/NodeAccessViewGrantsCacheContext.php b/core/modules/node/src/Cache/NodeAccessViewGrantsCacheContext.php
new file mode 100644
index 0000000..24323b9
--- /dev/null
+++ b/core/modules/node/src/Cache/NodeAccessViewGrantsCacheContext.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\NodeAccessViewGrantsCacheContext.
+ */
+
+namespace Drupal\node\Cache;
+
+use Drupal\Core\Cache\CacheContextInterface;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Defines the node access view grants cache context service.
+ *
+ * This allows for node access grants-sensitive caching when viewing nodes.
+ *
+ * @see node_query_node_access_alter()
+ */
+class NodeAccessViewGrantsCacheContext implements CacheContextInterface {
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $user;
+
+  /**
+   * Constructs a new NodeAccessViewGrantsCacheContext service.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $user
+   *   The current user.
+   */
+  public function __construct(AccountInterface $user) {
+    $this->user = $user;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getLabel() {
+    return t("Content access view grants");
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext() {
+    // If the current user either:
+    // - can bypass node access
+    // - has a global view grant (such as a view grant for node ID 0) — note
+    //   that this is automatically the case if no node access modules exist (no
+    //   hook_node_grants() implementations)
+    // then we don't need to determine the exact node view grants for the
+    // current user.
+    if ($this->user->hasPermission('bypass node access') || node_access_view_all_nodes($this->user)) {
+      return 'all';
+    }
+
+    $grants = node_access_grants('view', $this->user);
+    $grants_context_parts = [];
+    foreach ($grants as $realm => $gids) {
+      $grants_context_parts[] = $realm . ':' . implode(',', $gids);
+    }
+    return implode(';', $grants_context_parts);
+  }
+
+}
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index 2621d82..eb99636 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -45,7 +45,7 @@
  *   revision_table = "node_revision",
  *   revision_data_table = "node_field_revision",
  *   translatable = TRUE,
- *   list_cache_contexts = { "user.node_grants:view" },
+ *   list_cache_contexts = { "node_view_grants" },
  *   entity_keys = {
  *     "id" = "nid",
  *     "revision" = "vid",
diff --git a/core/modules/node/src/NodeGrantDatabaseStorage.php b/core/modules/node/src/NodeGrantDatabaseStorage.php
index 5c66190..da6522d 100644
--- a/core/modules/node/src/NodeGrantDatabaseStorage.php
+++ b/core/modules/node/src/NodeGrantDatabaseStorage.php
@@ -106,11 +106,12 @@ public function access(NodeInterface $node, $operation, $langcode, AccountInterf
     // theoretically cacheable, because we don't have the necessary metadata to
     // know it for a fact.
     $set_cacheability = function (AccessResult $access_result) use ($operation) {
-      $access_result->addCacheContexts(['user.node_grants:' . $operation]);
-      if ($operation !== 'view') {
-        $access_result->setCacheable(FALSE);
+      if ($operation === 'view') {
+        return $access_result->addCacheContexts(['node_view_grants']);
+      }
+      else {
+        return $access_result->setCacheable(FALSE);
       }
-      return $access_result;
     };
 
     if ($query->execute()->fetchField()) {
diff --git a/core/modules/node/src/Plugin/views/argument/Nid.php b/core/modules/node/src/Plugin/views/argument/Nid.php
index 7ef1d93..07f93ec 100644
--- a/core/modules/node/src/Plugin/views/argument/Nid.php
+++ b/core/modules/node/src/Plugin/views/argument/Nid.php
@@ -9,7 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\node\NodeStorageInterface;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -17,7 +17,7 @@
  *
  * @ViewsArgument("node_nid")
  */
-class Nid extends NumericArgument {
+class Nid extends Numeric {
 
   /**
    * The node storage.
diff --git a/core/modules/node/src/Plugin/views/argument/Type.php b/core/modules/node/src/Plugin/views/argument/Type.php
index ec03b48..eb1e107 100644
--- a/core/modules/node/src/Plugin/views/argument/Type.php
+++ b/core/modules/node/src/Plugin/views/argument/Type.php
@@ -9,7 +9,7 @@
 
 use Drupal\Component\Utility\String as UtilityString;
 use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\views\Plugin\views\argument\StringArgument;
+use Drupal\views\Plugin\views\argument\String;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -17,7 +17,7 @@
  *
  * @ViewsArgument("node_type")
  */
-class Type extends StringArgument {
+class Type extends String {
 
   /**
    * NodeType storage controller.
diff --git a/core/modules/node/src/Plugin/views/argument/Vid.php b/core/modules/node/src/Plugin/views/argument/Vid.php
index 2c93d9d..43246d8 100644
--- a/core/modules/node/src/Plugin/views/argument/Vid.php
+++ b/core/modules/node/src/Plugin/views/argument/Vid.php
@@ -9,7 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Database\Connection;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\node\NodeStorageInterface;
 
@@ -18,7 +18,7 @@
  *
  * @ViewsArgument("node_vid")
  */
-class Vid extends NumericArgument {
+class Vid extends Numeric {
 
   /**
    * Database Service Object.
diff --git a/core/modules/node/src/Plugin/views/argument_default/Node.php b/core/modules/node/src/Plugin/views/argument_default/Node.php
index e6d8343..4a61f03 100644
--- a/core/modules/node/src/Plugin/views/argument_default/Node.php
+++ b/core/modules/node/src/Plugin/views/argument_default/Node.php
@@ -83,7 +83,7 @@ public function isCacheable() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return ['url'];
+    return ['cache.context.url'];
   }
 
 }
diff --git a/core/modules/node/src/Tests/NodeAccessGrantsCacheContextTest.php b/core/modules/node/src/Tests/NodeAccessViewGrantsCacheContextTest.php
similarity index 76%
rename from core/modules/node/src/Tests/NodeAccessGrantsCacheContextTest.php
rename to core/modules/node/src/Tests/NodeAccessViewGrantsCacheContextTest.php
index d66e776..1cd8062 100644
--- a/core/modules/node/src/Tests/NodeAccessGrantsCacheContextTest.php
+++ b/core/modules/node/src/Tests/NodeAccessViewGrantsCacheContextTest.php
@@ -2,18 +2,18 @@
 
 /**
  * @file
- * Contains \Drupal\node\Tests\NodeAccessGrantsCacheContextTest.
+ * Contains \Drupal\node\Tests\NodeAccessViewGrantsCacheContextTest.
  */
 
 namespace Drupal\node\Tests;
 
 /**
- * Tests the node access grants cache context service.
+ * Tests the node access view grants cache context service.
  *
  * @group node
  * @group Cache
  */
-class NodeAccessGrantsCacheContextTest extends NodeTestBase {
+class NodeAccessViewGrantsCacheContextTest extends NodeTestBase {
 
   /**
    * Modules to enable.
@@ -71,20 +71,20 @@ protected function assertCacheContext(array $expected) {
         $this->drupalLogin($this->userMapping[$uid]);
       }
       $this->pass('Asserting cache context for user ' . $uid . '.');
-      $this->assertIdentical($context, $this->container->get('cache_context.user.node_grants')->getContext('view'));
+      $this->assertIdentical($context, $this->container->get('cache_context.node_view_grants')->getContext());
     }
     $this->drupalLogout();
   }
 
   /**
-   * Tests NodeAccessGrantsCacheContext::getContext().
+   * Tests NodeAccessViewGrantsCacheContext::getContext().
    */
   public function testCacheContext() {
     $this->assertCacheContext([
-      0 => 'view.all:0;node_access_test_author:0;node_access_all:0',
+      0 => 'all:0;node_access_test_author:0;node_access_all:0',
       1 => 'all',
-      2 => 'view.all:0;node_access_test_author:2;node_access_test:8888,8889',
-      3 => 'view.all:0;node_access_test_author:3',
+      2 => 'all:0;node_access_test_author:2;node_access_test:8888,8889',
+      3 => 'all:0;node_access_test_author:3',
     ]);
 
     // Grant view to all nodes (because nid = 0) for users in the
@@ -103,40 +103,40 @@ public function testCacheContext() {
     \Drupal::state()->set('node_access_test.no_access_uid', 0);
     drupal_static_reset('node_access_view_all_nodes');
     $this->assertCacheContext([
-      0 => 'view.all',
+      0 => 'all',
       1 => 'all',
-      2 => 'view.all:0;node_access_test_author:2;node_access_test:8888,8889',
-      3 => 'view.all:0;node_access_test_author:3',
+      2 => 'all:0;node_access_test_author:2;node_access_test:8888,8889',
+      3 => 'all:0;node_access_test_author:3',
     ]);
 
     // Put user accessUser (uid 2) in the realm.
     \Drupal::state()->set('node_access_test.no_access_uid', $this->accessUser->id());
     drupal_static_reset('node_access_view_all_nodes');
     $this->assertCacheContext([
-      0 => 'view.all:0;node_access_test_author:0',
+      0 => 'all:0;node_access_test_author:0',
       1 => 'all',
-      2 => 'view.all',
-      3 => 'view.all:0;node_access_test_author:3',
+      2 => 'all',
+      3 => 'all:0;node_access_test_author:3',
     ]);
 
     // Put user noAccessUser (uid 3) in the realm.
     \Drupal::state()->set('node_access_test.no_access_uid', $this->noAccessUser->id());
     drupal_static_reset('node_access_view_all_nodes');
     $this->assertCacheContext([
-      0 => 'view.all:0;node_access_test_author:0',
+      0 => 'all:0;node_access_test_author:0',
       1 => 'all',
-      2 => 'view.all:0;node_access_test_author:2;node_access_test:8888,8889',
-      3 => 'view.all',
+      2 => 'all:0;node_access_test_author:2;node_access_test:8888,8889',
+      3 => 'all',
     ]);
 
     // Uninstall the node_access_test module
     $this->container->get('module_installer')->uninstall(['node_access_test']);
     drupal_static_reset('node_access_view_all_nodes');
     $this->assertCacheContext([
-      0 => 'view.all',
+      0 => 'all',
       1 => 'all',
-      2 => 'view.all',
-      3 => 'view.all',
+      2 => 'all',
+      3 => 'all',
     ]);
   }
 
diff --git a/core/modules/node/src/Tests/NodeBodyFieldStorageTest.php b/core/modules/node/src/Tests/NodeBodyFieldStorageTest.php
index 2153c7f..6e606f5 100644
--- a/core/modules/node/src/Tests/NodeBodyFieldStorageTest.php
+++ b/core/modules/node/src/Tests/NodeBodyFieldStorageTest.php
@@ -37,7 +37,7 @@ protected function setUp() {
     $this->installSchema('user', 'users_data');
     $this->installEntitySchema('user');
     $this->installEntitySchema('node');
-    $this->installConfig(array('field', 'node'));
+    $this->installConfig(array('field'));
   }
 
   /**
diff --git a/core/modules/node/src/Tests/NodeCacheTagsTest.php b/core/modules/node/src/Tests/NodeCacheTagsTest.php
index 8144ba2..c18f15b 100644
--- a/core/modules/node/src/Tests/NodeCacheTagsTest.php
+++ b/core/modules/node/src/Tests/NodeCacheTagsTest.php
@@ -62,7 +62,7 @@ protected function getAdditionalCacheTagsForEntity(EntityInterface $node) {
    * {@inheritdoc}
    */
   protected function getAdditionalCacheContextsForEntityListing() {
-    return ['user.node_grants:view'];
+    return ['node_view_grants'];
   }
 
 }
diff --git a/core/modules/node/src/Tests/NodeListBuilderTest.php b/core/modules/node/src/Tests/NodeListBuilderTest.php
index ec4b1ea..a594f1f 100644
--- a/core/modules/node/src/Tests/NodeListBuilderTest.php
+++ b/core/modules/node/src/Tests/NodeListBuilderTest.php
@@ -38,7 +38,7 @@ public function testCacheContexts() {
     $build = $list_builder->render();
     $this->container->get('renderer')->render($build);
 
-    $this->assertEqual(['url.query_args.pagers:0', 'user.node_grants:view'], $build['#cache']['contexts']);
+    $this->assertEqual(['node_view_grants', 'pager:0'], $build['#cache']['contexts']);
   }
 
 }
diff --git a/core/modules/node/src/Tests/NodeTokenReplaceTest.php b/core/modules/node/src/Tests/NodeTokenReplaceTest.php
index 7431f06..7c0dfe7 100644
--- a/core/modules/node/src/Tests/NodeTokenReplaceTest.php
+++ b/core/modules/node/src/Tests/NodeTokenReplaceTest.php
@@ -30,7 +30,7 @@ class NodeTokenReplaceTest extends TokenReplaceUnitTestBase {
    */
   protected function setUp() {
     parent::setUp();
-    $this->installConfig(array('filter', 'node'));
+    $this->installConfig(array('filter'));
 
     $node_type = entity_create('node_type', array('type' => 'article', 'name' => 'Article'));
     $node_type->save();
diff --git a/core/modules/node/src/Tests/Views/FrontPageTest.php b/core/modules/node/src/Tests/Views/FrontPageTest.php
index ed6fd3d..61fe5eb 100644
--- a/core/modules/node/src/Tests/Views/FrontPageTest.php
+++ b/core/modules/node/src/Tests/Views/FrontPageTest.php
@@ -241,7 +241,7 @@ protected function assertFrontPageViewCacheTags($do_assert_views_caches) {
     $view = Views::getView('frontpage');
     $view->setDisplay('page_1');
 
-    $cache_contexts = ['user.node_grants:view', 'languages'];
+    $cache_contexts = ['node_view_grants', 'language'];
 
     // Test before there are any nodes.
     $empty_node_listing_cache_tags = [
diff --git a/core/modules/options/src/Plugin/views/argument/NumberListField.php b/core/modules/options/src/Plugin/views/argument/NumberListField.php
index 007bcdd..792381c 100644
--- a/core/modules/options/src/Plugin/views/argument/NumberListField.php
+++ b/core/modules/options/src/Plugin/views/argument/NumberListField.php
@@ -13,7 +13,7 @@
 use Drupal\views\FieldAPIHandlerTrait;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 
 /**
  * Argument handler for list field to show the human readable name in the
@@ -23,7 +23,7 @@
  *
  * @ViewsArgument("number_list_field")
  */
-class NumberListField extends NumericArgument {
+class NumberListField extends Numeric {
 
   use AllowedTagsXssTrait;
   use FieldAPIHandlerTrait;
diff --git a/core/modules/options/src/Plugin/views/argument/StringListField.php b/core/modules/options/src/Plugin/views/argument/StringListField.php
index 0825bb1..da715c4 100644
--- a/core/modules/options/src/Plugin/views/argument/StringListField.php
+++ b/core/modules/options/src/Plugin/views/argument/StringListField.php
@@ -12,7 +12,7 @@
 use Drupal\views\FieldAPIHandlerTrait;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Plugin\views\argument\StringArgument;
+use Drupal\views\Plugin\views\argument\String;
 use Drupal\Component\Utility\String as StringUtility;
 
 /**
@@ -22,7 +22,7 @@
  *
  * @ViewsArgument("string_list_field")
  */
-class StringListField extends StringArgument {
+class StringListField extends String {
 
   use AllowedTagsXssTrait;
   use FieldAPIHandlerTrait;
diff --git a/core/modules/quickedit/js/quickedit.js b/core/modules/quickedit/js/quickedit.js
index 238ba0d..539fc3e 100644
--- a/core/modules/quickedit/js/quickedit.js
+++ b/core/modules/quickedit/js/quickedit.js
@@ -66,7 +66,7 @@
   Drupal.behaviors.quickedit = {
     attach: function (context) {
       // Initialize the Quick Edit app once per page load.
-      $('body').once('quickedit-init').each(initQuickEdit);
+      $('body').once('quickedit-init', initQuickEdit);
 
       // Find all in-place editable fields, if any.
       var $fields = $(context).find('[data-quickedit-field-id]').once('quickedit');
diff --git a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
index af73169..7c365ac 100644
--- a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
+++ b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
@@ -98,7 +98,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->drupalPost('quickedit/metadata', 'application/json', $post);
-    $this->assertIdentical('{"message":""}', $response);
+    $this->assertIdentical('{}', $response);
     $this->assertResponse(403);
 
     // Quick Edit's JavaScript would SearchRankingTestnever hit these endpoints if the metadata
@@ -125,7 +125,7 @@ public function testUserWithoutPermission() {
     $this->assertResponse(403);
     $post = array('nocssjs' => 'true');
     $response = $this->drupalPost('quickedit/entity/' . 'node/1', 'application/json', $post);
-    $this->assertIdentical('{"message":""}', $response);
+    $this->assertIdentical('{}', $response);
     $this->assertResponse(403);
   }
 
diff --git a/core/modules/rdf/src/Tests/ImageFieldAttributesTest.php b/core/modules/rdf/src/Tests/ImageFieldAttributesTest.php
index c58b3bb..ec41a77 100644
--- a/core/modules/rdf/src/Tests/ImageFieldAttributesTest.php
+++ b/core/modules/rdf/src/Tests/ImageFieldAttributesTest.php
@@ -66,7 +66,7 @@ protected function setUp() {
     $image = current($this->drupalGetTestFiles('image'));
 
     // Save a node with the image.
-    $nid = $this->uploadNodeImage($image, $this->fieldName, 'article', $this->randomMachineName());
+    $nid = $this->uploadNodeImage($image, $this->fieldName, 'article');
     $this->node = Node::load($nid);
     $this->file = file_load($this->node->{$this->fieldName}->target_id);
   }
diff --git a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
index dcd9c32..be905cd 100644
--- a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
+++ b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
@@ -168,11 +168,7 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
     // Create a new node with an image attached. Make sure we use a large image
     // so the scale effects of the image styles always have an effect.
     $test_image = current($this->drupalGetTestFiles('image', 39325));
-
-    // Create alt text for the image.
-    $alt = $this->randomMachineName();
-
-    $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt);
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
     $node_storage->resetCache(array($nid));
     $node = $node_storage->load($nid);
 
@@ -183,7 +179,6 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
       '#uri' => $image_uri,
       '#width' => 360,
       '#height' => 240,
-      '#alt' => $alt,
     );
     $default_output = str_replace("\n", NULL, drupal_render($image));
     $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.');
@@ -204,7 +199,6 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
       '#uri' => $image_uri,
       '#width' => 360,
       '#height' => 240,
-      '#alt' => $alt,
     );
     $default_output = '<a href="' . file_create_url($image_uri) . '">' . drupal_render($image) . '</a>';
     $this->drupalGet('node/' . $nid);
@@ -279,7 +273,6 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
     $image = \Drupal::service('image.factory')->get($image_uri);
     $fallback_image = array(
       '#theme' => 'image',
-      '#alt' => $alt,
       '#srcset' => array(
         array(
           'uri' => $large_style->buildUrl($image->getSource()),
@@ -336,7 +329,7 @@ public function testResponsiveImageFieldFormattersEmptyMediaQuery() {
     $this->createImageField($field_name, 'article', array('uri_scheme' => 'public'));
     // Create a new node with an image attached.
     $test_image = current($this->drupalGetTestFiles('image'));
-    $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName());
+    $nid = $this->uploadNodeImage($test_image, $field_name, 'article');
     $node_storage->resetCache(array($nid));
 
     // Use the responsive image formatter linked to file formatter.
@@ -373,8 +366,7 @@ public function testResponsiveImageFieldFormattersEmptyMediaQuery() {
    */
   private function assertResponsiveImageFieldFormattersLink($link_type) {
     $field_name = Unicode::strtolower($this->randomMachineName());
-    $field_settings = array('alt_field_required' => 0);
-    $this->createImageField($field_name, 'article', array('uri_scheme' => 'public'), $field_settings);
+    $this->createImageField($field_name, 'article', array('uri_scheme' => 'public'));
     // Create a new node with an image attached.
     $test_image = current($this->drupalGetTestFiles('image'));
 
diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php
index 240c9de..076eb1c 100644
--- a/core/modules/rest/src/Plugin/views/display/RestExport.php
+++ b/core/modules/rest/src/Plugin/views/display/RestExport.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\String;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
+use Drupal\Core\ContentNegotiation;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\PathPluginBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -72,6 +73,13 @@ class RestExport extends PathPluginBase {
   protected $mimeType;
 
   /**
+   * The content negotiation library.
+   *
+   * @var \Drupal\Core\ContentNegotiation
+   */
+  protected $contentNegotiation;
+
+  /**
    * Constructs a Drupal\rest\Plugin\ResourceBase object.
    *
    * @param array $configuration
@@ -84,9 +92,12 @@ class RestExport extends PathPluginBase {
    *   The route provider
    * @param \Drupal\Core\State\StateInterface $state
    *   The state key value store.
+   * @param \Drupal\Core\ContentNegotiation $content_negotiation
+   *   The content negotiation library.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, ContentNegotiation $content_negotiation) {
     parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider, $state);
+    $this->contentNegotiation = $content_negotiation;
   }
 
   /**
@@ -98,7 +109,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $plugin_id,
       $plugin_definition,
       $container->get('router.route_provider'),
-      $container->get('state')
+      $container->get('state'),
+      $container->get('content_negotiation')
     );
   }
 
@@ -108,7 +120,7 @@ public static function create(ContainerInterface $container, array $configuratio
   public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
     parent::initDisplay($view, $display, $options);
 
-    $request_content_type = $this->view->getRequest()->getRequestFormat();
+    $request_content_type = $this->contentNegotiation->getContentType($this->view->getRequest());
     // Only use the requested content type if it's not 'html'. If it is then
     // default to 'json' to aid debugging.
     // @todo Remove the need for this when we have better content negotiation.
diff --git a/core/modules/rest/tests/src/Unit/CollectRoutesTest.php b/core/modules/rest/tests/src/Unit/CollectRoutesTest.php
index 7a2cbae..7a91831 100644
--- a/core/modules/rest/tests/src/Unit/CollectRoutesTest.php
+++ b/core/modules/rest/tests/src/Unit/CollectRoutesTest.php
@@ -40,10 +40,16 @@ protected function setUp() {
 
     $container = new ContainerBuilder();
 
+    $content_negotiation = $this->getMockBuilder('\Drupal\Core\ContentNegotiation')
+      ->disableOriginalConstructor()
+      ->getMock();
+
     $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request')
       ->disableOriginalConstructor()
       ->getMock();
 
+    $container->set('content_negotiation', $content_negotiation);
+
     $this->view = $this->getMock('\Drupal\views\Entity\View', array('initHandlers'), array(
       array('id' => 'test_view'),
       'view',
diff --git a/core/modules/search/src/Plugin/Block/SearchBlock.php b/core/modules/search/src/Plugin/Block/SearchBlock.php
index 48a2b54..369aad6 100644
--- a/core/modules/search/src/Plugin/Block/SearchBlock.php
+++ b/core/modules/search/src/Plugin/Block/SearchBlock.php
@@ -37,13 +37,4 @@ public function build() {
     return \Drupal::formBuilder()->getForm('Drupal\search\Form\SearchBlockForm');
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Make cacheable once https://www.drupal.org/node/2351015 lands.
-   */
-  public function getCacheMaxAge() {
-    return 0;
-  }
-
 }
diff --git a/core/modules/search/src/Plugin/views/field/Score.php b/core/modules/search/src/Plugin/views/field/Score.php
index 7d093b7..bb5c3fe 100644
--- a/core/modules/search/src/Plugin/views/field/Score.php
+++ b/core/modules/search/src/Plugin/views/field/Score.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\search\Plugin\views\field;
 
-use Drupal\views\Plugin\views\field\NumericField;
+use Drupal\views\Plugin\views\field\Numeric;
 use Drupal\views\ResultRow;
 
 /**
@@ -17,7 +17,7 @@
  *
  * @ViewsField("search_score")
  */
-class Score extends NumericField {
+class Score extends Numeric {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/simpletest/simpletest.js b/core/modules/simpletest/simpletest.js
index b1c63de..7e365bd 100644
--- a/core/modules/simpletest/simpletest.js
+++ b/core/modules/simpletest/simpletest.js
@@ -7,7 +7,7 @@
    */
   Drupal.behaviors.simpleTestGroupCollapse = {
     attach: function (context) {
-      $(context).find('.simpletest-group').once('simpletest-group-collapse').each(function () {
+      $(context).find('.simpletest-group').once('simpletest-group-collapse', function () {
         var $group = $(this);
         var $image = $group.find('.simpletest-image');
         $image
@@ -28,7 +28,7 @@
    */
   Drupal.behaviors.simpleTestSelectAll = {
     attach: function (context) {
-      $(context).find('.simpletest-group').once('simpletest-group-select-all').each(function () {
+      $(context).find('.simpletest-group').once('simpletest-group-select-all', function () {
         var $group = $(this);
         var $cell = $group.find('.simpletest-group-select-all');
         var $groupCheckbox = $('<input type="checkbox" id="' + $cell.attr('id') + '-group-select-all" class="form-checkbox" />');
diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php
index c340c92..11e9076 100644
--- a/core/modules/simpletest/src/InstallerTestBase.php
+++ b/core/modules/simpletest/src/InstallerTestBase.php
@@ -140,7 +140,7 @@ protected function setUp() {
 
     // Import new settings.php written by the installer.
     $request = Request::createFromGlobals();
-    $class_loader = require $this->container->get('app.root') . '/autoload.php';
+    $class_loader = require $this->container->get('app.root') . '/core/vendor/autoload.php';
     Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader);
     foreach ($GLOBALS['config_directories'] as $type => $path) {
       $this->configDirectories[$type] = $path;
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index abc1f20..14b839b 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -178,7 +178,7 @@ protected function setUp() {
     $GLOBALS['conf']['container_service_providers']['TestServiceProvider'] = 'Drupal\simpletest\TestServiceProvider';
 
     // Bootstrap a new kernel.
-    $class_loader = require DRUPAL_ROOT . '/autoload.php';
+    $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
     $this->kernel = new DrupalKernel('testing', $class_loader, FALSE);
     $request = Request::create('/');
     $site_path = DrupalKernel::findSitePath($request);
diff --git a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
index 3024e43..e808cd2 100644
--- a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
+++ b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
@@ -211,8 +211,6 @@ function testInstallEntitySchema() {
    * Tests expected behavior of installConfig().
    */
   function testInstallConfig() {
-    // The user module has configuration that depends on system.
-    $this->enableModules(array('system'));
     $module = 'user';
 
     // Verify that default config can only be installed for enabled modules.
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 220ee09..63cf76a 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -375,7 +375,7 @@ protected function drupalBuildEntityView(EntityInterface $entity, $view_mode = '
    *   - region: 'sidebar_first'.
    *   - theme: The default theme.
    *   - visibility: Empty array.
-   *   - cache: array('max_age' => Cache::PERMANENT).
+   *   - cache: array('max_age' => 0).
    *
    * @return \Drupal\block\Entity\Block
    *   The block entity.
@@ -393,7 +393,7 @@ protected function drupalPlaceBlock($plugin_id, array $settings = array()) {
       'visibility' => array(),
       'weight' => 0,
       'cache' => array(
-        'max_age' => Cache::PERMANENT,
+        'max_age' => 0,
       ),
     );
     $values = [];
@@ -862,7 +862,7 @@ protected function setUp() {
     // Since Drupal is bootstrapped already, install_begin_request() will not
     // bootstrap again. Hence, we have to reload the newly written custom
     // settings.php manually.
-    $class_loader = require DRUPAL_ROOT . '/autoload.php';
+    $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
     Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $class_loader);
 
     // Execute the non-interactive installer.
diff --git a/core/modules/system/config/install/system.site.yml b/core/modules/system/config/install/system.site.yml
index 403e464..10e2be2 100644
--- a/core/modules/system/config/install/system.site.yml
+++ b/core/modules/system/config/install/system.site.yml
@@ -9,4 +9,3 @@ page:
 admin_compact_mode: false
 weight_select_max: 100
 langcode: en
-default_langcode: en
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index ba8fa15..6888a56 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -37,10 +37,7 @@ system.site:
       label: 'Weight element maximum value'
     langcode:
       type: string
-      label: 'Language code'
-    default_langcode:
-      type: string
-      label: 'Site default language code'
+      label: 'Default language'
     mail_notification:
       type: string
       label: 'Notification email address'
diff --git a/core/modules/system/src/Controller/ThemeController.php b/core/modules/system/src/Controller/ThemeController.php
index 5f56052..dd5f749 100644
--- a/core/modules/system/src/Controller/ThemeController.php
+++ b/core/modules/system/src/Controller/ThemeController.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\PreExistingConfigException;
-use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Routing\RouteBuilderInterface;
@@ -145,9 +144,6 @@ public function install(Request $request) {
           'error'
         );
       }
-      catch (UnmetDependenciesException $e) {
-        drupal_set_message($e->getTranslatedMessage($this->getStringTranslation(), $theme), 'error');
-      }
 
       return $this->redirect('system.themes_page');
     }
diff --git a/core/modules/system/src/Form/ModulesListConfirmForm.php b/core/modules/system/src/Form/ModulesListConfirmForm.php
index 5449b41..b3c7977 100644
--- a/core/modules/system/src/Form/ModulesListConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesListConfirmForm.php
@@ -8,7 +8,6 @@
 namespace Drupal\system\Form;
 
 use Drupal\Core\Config\PreExistingConfigException;
-use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
@@ -177,13 +176,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         );
         return;
       }
-      catch (UnmetDependenciesException $e) {
-        drupal_set_message(
-          $e->getTranslatedMessage($this->getStringTranslation(), $this->modules['install'][$e->getExtension()]),
-          'error'
-        );
-        return;
-      }
     }
 
     // Gets module list after install process, flushes caches and displays a
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 90a6e9f..2e80482 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -10,7 +10,6 @@
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\PreExistingConfigException;
-use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\Core\Controller\TitleResolverInterface;
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
@@ -537,13 +536,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         );
         return;
       }
-      catch (UnmetDependenciesException $e) {
-        drupal_set_message(
-          $e->getTranslatedMessage($this->getStringTranslation(), $modules['install'][$e->getExtension()]),
-          'error'
-        );
-        return;
-      }
     }
 
     // Gets module list after install process, flushes caches and displays a
diff --git a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php
index c5ebaa5..44650dd 100644
--- a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php
+++ b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php
@@ -71,6 +71,12 @@ public function defaultConfiguration() {
       'use_site_name' => TRUE,
       'use_site_slogan' => TRUE,
       'label_display' => FALSE,
+      // Modify the default max age for the 'Site branding' block: the site
+      // logo, name and slogan are static for a given language, except when the
+      // theme settings are updated (global theme settings or theme-specific
+      // settings). Cache tags for those cases ensure that a cached version of
+      // this block is invalidated automatically.
+      'cache' => array('max_age' => \Drupal\Core\Cache\Cache::PERMANENT),
     );
   }
 
diff --git a/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php b/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php
index b0cfe9a..e822a72 100644
--- a/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php
+++ b/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php
@@ -84,13 +84,4 @@ public function build() {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Make cacheable as part of https://drupal.org/node/1805054
-   */
-  public function getCacheMaxAge() {
-    return 0;
-  }
-
 }
diff --git a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
index 4a6a2ea..c07fba2 100644
--- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
+++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Plugin\Block;
 
 use Drupal\Core\Block\BlockBase;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Menu\MenuActiveTrailInterface;
 use Drupal\Core\Menu\MenuLinkTreeInterface;
@@ -164,7 +165,16 @@ public function build() {
    * {@inheritdoc}
    */
   public function defaultConfiguration() {
+    // Modify the default max age for menu blocks: modifications made to menus,
+    // menu links and menu blocks will automatically invalidate corresponding
+    // cache tags, therefore allowing us to cache menu blocks forever. This is
+    // only not the case if there are user-specific or dynamic alterations (e.g.
+    // hook_node_access()), but in that:
+    // 1) it is possible to set a different max age for individual blocks, since
+    //    this is just the default value.
+    // 2) modules can modify caching by implementing hook_block_view_alter()
     return [
+      'cache' => array('max_age' => Cache::PERMANENT),
       'level' => 1,
       'depth' => 0,
     ];
@@ -186,12 +196,12 @@ public function getCacheTags() {
   /**
    * {@inheritdoc}
    */
-  public function getCacheContexts() {
+  protected function getRequiredCacheContexts() {
     // Menu blocks must be cached per role and per active trail.
     $menu_name = $this->getDerivativeId();
     return [
       'user.roles',
-      'route.menu_active_trails:' . $menu_name,
+      'menu.active_trail:' . $menu_name,
     ];
   }
 
diff --git a/core/modules/system/src/Plugin/Block/SystemMessagesBlock.php b/core/modules/system/src/Plugin/Block/SystemMessagesBlock.php
index 59dde2a..b724780 100644
--- a/core/modules/system/src/Plugin/Block/SystemMessagesBlock.php
+++ b/core/modules/system/src/Plugin/Block/SystemMessagesBlock.php
@@ -50,6 +50,9 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
     $form['cache']['#description'] = $this->t('This block is cacheable forever, it is not configurable.');
     $form['cache']['max_age']['#value'] = Cache::PERMANENT;
     $form['cache']['max_age']['#disabled'] = TRUE;
+    // Don't allow cache contexts to be configured, this block is globally
+    // cacheable.
+    $form['cache']['contexts']['#access'] = FALSE;
 
     return $form;
   }
diff --git a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php
index c389a2a..0f7bc6d 100644
--- a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php
+++ b/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php
@@ -11,7 +11,6 @@
 use Drupal\Core\Routing\RequestContext;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Core\Cache\Cache;
-use Drupal\user\Entity\Role;
 
 /**
  * Enables the page cache and tests it with various HTTP requests.
@@ -99,50 +98,6 @@ function testAcceptHeaderRequests() {
     $this->drupalGet($accept_header_cache_uri, 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.');
-
-    // Enable REST support for nodes and hal+json.
-    \Drupal::service('module_installer')->install(['node', 'rest', 'hal']);
-    $this->drupalCreateContentType(['type' => 'article']);
-    $node = $this->drupalCreateNode(['type' => 'article']);
-    $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');
-    $role->save();
-
-    $this->drupalGet($node_uri);
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
-    $this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
-    $this->drupalGet($node_uri);
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
-    $this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
-
-    // Now request a HAL page, we expect that the first request is a cache miss
-    // and it serves HTML.
-    $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_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_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_uri, [], $hal_json_accept_header);
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
-    $this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
-
-    $this->drupalGet($node_uri);
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
-    $this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
-    $this->drupalGet($node_uri);
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
-    $this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
index 8078913..f4d30ec 100644
--- a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
+++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
@@ -68,11 +68,11 @@ function testPageCacheTags() {
     ));
 
     $cache_contexts = [
-      'languages',
-      'route.menu_active_trails:account',
-      'route.menu_active_trails:footer',
-      'route.menu_active_trails:main',
-      'route.menu_active_trails:tools',
+      'language',
+      'menu.active_trail:account',
+      'menu.active_trail:footer',
+      'menu.active_trail:main',
+      'menu.active_trail:tools',
       'theme',
       'timezone',
       'user.roles',
diff --git a/core/modules/system/src/Tests/Common/FormatDateTest.php b/core/modules/system/src/Tests/Common/FormatDateTest.php
index 9d9a265..63576fe 100644
--- a/core/modules/system/src/Tests/Common/FormatDateTest.php
+++ b/core/modules/system/src/Tests/Common/FormatDateTest.php
@@ -96,7 +96,7 @@ function testFormatDate() {
     $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'Europe/London', 'en'), 'Monday, 26-Mar-07 01:00:00 BST', 'Test a different time zone.');
 
     // Change the default language and timezone.
-    $this->config('system.site')->set('default_langcode', static::LANGCODE)->save();
+    $this->config('system.site')->set('langcode', static::LANGCODE)->save();
     date_default_timezone_set('America/Los_Angeles');
 
     $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'America/Los_Angeles', 'en'), 'Sunday, 25-Mar-07 17:00:00 PDT', 'Test a different language.');
diff --git a/core/modules/system/src/Tests/Database/DatabaseExceptionWrapperTest.php b/core/modules/system/src/Tests/Database/DatabaseExceptionWrapperTest.php
index 8237e36..fbe0247 100644
--- a/core/modules/system/src/Tests/Database/DatabaseExceptionWrapperTest.php
+++ b/core/modules/system/src/Tests/Database/DatabaseExceptionWrapperTest.php
@@ -18,47 +18,15 @@
  */
 class DatabaseExceptionWrapperTest extends KernelTestBase {
 
-  /**
-   * Tests the expected database exception thrown for prepared statements.
-   */
-  public function testPreparedStatement() {
+  function testDatabaseExceptionWrapper() {
     $connection = Database::getConnection();
+    $query = $connection->prepare('bananas');
     try {
-      // SQLite validates the syntax upon preparing a statement already.
-      // @throws \PDOException
-      $query = $connection->prepare('bananas');
-
-      // MySQL only validates the syntax upon trying to execute a query.
-      // @throws \Drupal\Core\Database\DatabaseExceptionWrapper
       $connection->query($query);
-
-      $this->fail('Expected PDOException or DatabaseExceptionWrapper, none was thrown.');
-    }
-    catch (\PDOException $e) {
-      $this->pass('Expected PDOException was thrown.');
-    }
-    catch (DatabaseExceptionWrapper $e) {
-      $this->pass('Expected DatabaseExceptionWrapper was thrown.');
-    }
-    catch (\Exception $e) {
-      $this->fail("Thrown exception is not a PDOException:\n" . (string) $e);
-    }
-  }
-
-  /**
-   * Tests the expected database exception thrown for inexistent tables.
-   */
-  public function testQueryThrowsDatabaseExceptionWrapperException() {
-    $connection = Database::getConnection();
-    try {
-      $connection->query('SELECT * FROM {does_not_exist}');
-      $this->fail('Expected PDOException, none was thrown.');
+      $this->fail('The expected exception is not thrown.');
     }
     catch (DatabaseExceptionWrapper $e) {
-      $this->pass('Expected DatabaseExceptionWrapper was thrown.');
-    }
-    catch (\Exception $e) {
-      $this->fail("Thrown exception is not a DatabaseExceptionWrapper:\n" . (string) $e);
+      $this->pass('The expected exception has been thrown.');
     }
   }
 
diff --git a/core/modules/system/src/Tests/Database/QueryTest.php b/core/modules/system/src/Tests/Database/QueryTest.php
index 82454a6..64e7b42 100644
--- a/core/modules/system/src/Tests/Database/QueryTest.php
+++ b/core/modules/system/src/Tests/Database/QueryTest.php
@@ -66,20 +66,4 @@ public function testArrayArgumentsSQLInjection() {
     $this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
   }
 
-  /**
-   * Tests numeric query parameter expansion in expressions.
-   *
-   * @see \Drupal\Core\Database\Driver\sqlite\Connection::expandArguments()
-   * @see http://bugs.php.net/bug.php?id=45259
-   */
-  public function testNumericExpressionSubstitution() {
-    $count = db_query('SELECT COUNT(*) >= 3 FROM {test}')->fetchField();
-    $this->assertEqual((bool) $count, TRUE);
-
-    $count = db_query('SELECT COUNT(*) >= :count FROM {test}', array(
-      ':count' => 3,
-    ))->fetchField();
-    $this->assertEqual((bool) $count, TRUE);
-  }
-
 }
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
index 03e56fc..ebd8307 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
@@ -61,7 +61,7 @@ protected function prepareConfigDirectories() {
    */
   protected function getTestKernel(Request $request, array $modules_enabled = NULL, $read_only = FALSE) {
     // Manually create kernel to avoid replacing settings.
-    $class_loader = require DRUPAL_ROOT . '/autoload.php';
+    $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
     $kernel = DrupalKernel::createFromRequest($request, $class_loader, 'testing');
     $this->settingsSet('container_yamls', []);
     $this->settingsSet('hash_salt', $this->databasePrefix);
@@ -168,7 +168,7 @@ public function testCompileDIC() {
    */
   public function testRepeatedBootWithDifferentEnvironment() {
     $request = Request::createFromGlobals();
-    $class_loader = require DRUPAL_ROOT . '/autoload.php';
+    $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
 
     $environments = [
       'testing1',
diff --git a/core/modules/system/src/Tests/Entity/EntityCrudHookTest.php b/core/modules/system/src/Tests/Entity/EntityCrudHookTest.php
index deff706..9386983 100644
--- a/core/modules/system/src/Tests/Entity/EntityCrudHookTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityCrudHookTest.php
@@ -52,7 +52,6 @@ protected function setUp() {
     $this->installSchema('file', array('file_usage'));
     $this->installSchema('node', array('node_access'));
     $this->installSchema('comment', array('comment_entity_statistics'));
-    $this->installConfig(['node', 'comment']);
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php b/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php
index fa5097a..9d8b36b 100644
--- a/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php
@@ -66,7 +66,7 @@ public function testCacheContexts() {
     $build = $list_builder->render();
     $this->container->get('renderer')->render($build);
 
-    $this->assertEqual(['entity_test_view_grants', 'url.query_args.pagers:0'], $build['#cache']['contexts']);
+    $this->assertEqual(['entity_test_view_grants', 'pager:0'], $build['#cache']['contexts']);
   }
 
 }
diff --git a/core/modules/system/src/Tests/File/DirectoryTest.php b/core/modules/system/src/Tests/File/DirectoryTest.php
index 0822063..5594b7c 100644
--- a/core/modules/system/src/Tests/File/DirectoryTest.php
+++ b/core/modules/system/src/Tests/File/DirectoryTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\File;
 
 use Drupal\Component\PhpStorage\FileStorage;
+use Drupal\Core\File\FileSystem;
 
 /**
  * Tests operations dealing with directories.
@@ -81,7 +82,8 @@ function testFileCheckDirectoryHandling() {
       $this->assertFalse(file_prepare_directory($directory, 0), 'Error reported for a non-writeable directory.', 'File');
 
       // Test directory permission modification.
-      $this->settingsSet('file_chmod_directory', 0777);
+      $this->container->set('file_system', new FileSystem($this->container->get('stream_wrapper_manager'), ['directory' => 0777], $this->container->get('logger.channel.file')));
+
       $this->assertTrue(file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS), 'No error reported when making directory writeable.', 'File');
     }
 
diff --git a/core/modules/system/src/Tests/File/UnmanagedSaveDataTest.php b/core/modules/system/src/Tests/File/UnmanagedSaveDataTest.php
index fc715c6..2e1e507 100644
--- a/core/modules/system/src/Tests/File/UnmanagedSaveDataTest.php
+++ b/core/modules/system/src/Tests/File/UnmanagedSaveDataTest.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\system\Tests\File;
+use Drupal\Core\File\FileSystem;
 
 /**
  * Tests the file_unmanaged_save_data() function.
@@ -18,7 +19,8 @@ class UnmanagedSaveDataTest extends FileTestBase {
    */
   function testFileSaveData() {
     $contents = $this->randomMachineName(8);
-    $this->settingsSet('file_chmod_file', 0777);
+    $this->container->set('file_system', new FileSystem($this->container->get('stream_wrapper_manager'), ['file' => 0777], $this->container->get('logger.channel.file')));
+
 
     // No filename.
     $filepath = file_unmanaged_save_data($contents);
diff --git a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php b/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php
index 1951f57..4645668 100644
--- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php
@@ -31,15 +31,6 @@ protected function setUp() {
       'required' => TRUE,
     );
 
-    // Actually the install profile should be skipped to because it is written
-    // to settings.php.
-    // @todo https://www.drupal.org/node/2451369 Fix install_profile so that it
-    //   is written to an existing settings.php if possible or if set used.
-    $this->settings['settings']['install_profile'] = (object) array(
-      'value' => 'testing',
-      'required' => TRUE,
-    );
-
     // Pre-configure database credentials.
     $connection_info = Database::getConnectionInfo();
     unset($connection_info['default']['pdo']);
diff --git a/core/modules/system/src/Tests/Installer/StandardInstallerTest.php b/core/modules/system/src/Tests/Installer/StandardInstallerTest.php
deleted file mode 100644
index a19ab6c..0000000
--- a/core/modules/system/src/Tests/Installer/StandardInstallerTest.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\system\Tests\Installer\StandardInstallerTest.
- */
-
-namespace Drupal\system\Tests\Installer;
-
-use Drupal\simpletest\InstallerTestBase;
-
-/**
- * Tests the interactive installer installing the standard profile.
- *
- * @group Installer
- */
-class StandardInstallerTest extends InstallerTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected $profile = 'standard';
-
-  /**
-   * Ensures that the user page is available after installation.
-   */
-  public function testInstaller() {
-    // Verify that the confirmation message appears.
-    require_once \Drupal::root() . '/core/includes/install.inc';
-    $this->assertRaw(t('Congratulations, you installed @drupal!', array(
-      '@drupal' => drupal_install_profile_distribution_name(),
-    )));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUpSite() {
-    // Test that the correct theme is being used.
-    $this->assertNoRaw('bartik');
-    $this->assertRaw('themes/seven/css/theme/install-page.css');
-    parent::setUpSite();
-  }
-
-
-}
diff --git a/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php b/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php
index b8ea7ed..052033f 100644
--- a/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php
+++ b/core/modules/system/src/Tests/Routing/ExceptionHandlingTest.php
@@ -48,7 +48,7 @@ public function testJson403() {
 
     $this->assertEqual($response->getStatusCode(), Response::HTTP_FORBIDDEN);
     $this->assertEqual($response->headers->get('Content-type'), 'application/json');
-    $this->assertEqual('{"message":""}', $response->getContent());
+    $this->assertEqual('{}', $response->getContent());
   }
 
   /**
@@ -65,7 +65,7 @@ public function testJson404() {
 
     $this->assertEqual($response->getStatusCode(), Response::HTTP_NOT_FOUND);
     $this->assertEqual($response->headers->get('Content-type'), 'application/json');
-    $this->assertEqual('{"message":"No route found for \\u0022GET \\/not-found\\u0022"}', $response->getContent());
+    $this->assertEqual('{}', $response->getContent());
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Session/SessionTest.php b/core/modules/system/src/Tests/Session/SessionTest.php
index 0921f66..f4a0dbc 100644
--- a/core/modules/system/src/Tests/Session/SessionTest.php
+++ b/core/modules/system/src/Tests/Session/SessionTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\system\Tests\Session;
 
+use Drupal\Component\Serialization\Yaml;
+use Drupal\Core\DependencyInjection\YamlFileLoader;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -228,13 +230,13 @@ function testSessionWrite() {
     $this->assertEqual($times4->timestamp, $times3->timestamp, 'Sessions table was not updated.');
 
     // Force updating of users and sessions table once per second.
-    $this->settingsSet('session_write_interval', 0);
-    // Write that value also into the test settings.php file.
-    $settings['settings']['session_write_interval'] = (object) array(
-      'value' => 0,
-      'required' => TRUE,
-    );
-    $this->writeSettings($settings);
+    $filename = $this->siteDirectory . '/services.yml';
+    $data = Yaml::decode(file_get_contents($filename));
+    $data['parameters']['session_write_interval'] = 0;
+    file_put_contents($filename, Yaml::encode($data));
+    YamlFileLoader::reset();
+    $this->rebuildContainer();
+
     $this->drupalGet('');
     $times5 = db_query($sql, array(':uid' => $user->id()))->fetchObject();
     $this->assertNotEqual($times5->access, $times4->access, 'Users table was updated.');
diff --git a/core/modules/system/src/Tests/System/CronRunTest.php b/core/modules/system/src/Tests/System/CronRunTest.php
index e17bbf3..de8cdcc 100644
--- a/core/modules/system/src/Tests/System/CronRunTest.php
+++ b/core/modules/system/src/Tests/System/CronRunTest.php
@@ -49,12 +49,6 @@ function testCronRun() {
    * need the exact time when cron is triggered.
    */
   function testAutomaticCron() {
-    // Test with a logged in user; anonymous users likely don't cause Drupal to
-    // fully bootstrap, because of the internal page cache or an external
-    // reverse proxy. Reuse this user for disabling cron later in the test.
-    $admin_user = $this->drupalCreateUser(array('administer site configuration'));
-    $this->drupalLogin($admin_user);
-
     // Ensure cron does not run when the cron threshold is enabled and was
     // not passed.
     $cron_last = time();
@@ -74,6 +68,8 @@ function testAutomaticCron() {
     $this->assertTrue($cron_last < \Drupal::state()->get('system.cron_last'), 'Cron runs when the cron threshold is passed.');
 
     // Disable the cron threshold through the interface.
+    $admin_user = $this->drupalCreateUser(array('administer site configuration'));
+    $this->drupalLogin($admin_user);
     $this->drupalPostForm('admin/config/system/cron', array('cron_safe_threshold' => 0), t('Save configuration'));
     $this->assertText(t('The configuration options have been saved.'));
     $this->drupalLogout();
diff --git a/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php b/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php
index 18298f9..3615c43 100644
--- a/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php
+++ b/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php
@@ -32,7 +32,7 @@ function testSystemInitIgnoresSecondaries() {
     Database::addConnectionInfo('default', 'replica', $connection_info['default']);
 
     db_ignore_replica();
-    $class_loader = require \Drupal::root() . '/autoload.php';
+    $class_loader = require \Drupal::root() . '/core/vendor/autoload.php';
     $kernel = new DrupalKernel('testing', $class_loader, FALSE);
     $event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST);
     $subscriber = new ReplicaDatabaseIgnoreSubscriber();
diff --git a/core/modules/system/src/Tests/Theme/TwigTransTest.php b/core/modules/system/src/Tests/Theme/TwigTransTest.php
index 85ba19a..7f21b2d 100644
--- a/core/modules/system/src/Tests/Theme/TwigTransTest.php
+++ b/core/modules/system/src/Tests/Theme/TwigTransTest.php
@@ -70,7 +70,7 @@ protected function setUp() {
     $this->installLanguages();
 
     // Assign Lolspeak (xx) to be the default language.
-    $this->config('system.site')->set('default_langcode', 'xx')->save();
+    $this->config('system.site')->set('langcode', 'xx')->save();
     $this->rebuildContainer();
 
     // Check that lolspeak is the default language for the site.
diff --git a/core/modules/system/tests/modules/form_test/src/Plugin/Block/RedirectFormBlock.php b/core/modules/system/tests/modules/form_test/src/Plugin/Block/RedirectFormBlock.php
index f02b523..4a04599 100644
--- a/core/modules/system/tests/modules/form_test/src/Plugin/Block/RedirectFormBlock.php
+++ b/core/modules/system/tests/modules/form_test/src/Plugin/Block/RedirectFormBlock.php
@@ -76,14 +76,4 @@ protected function blockAccess(AccountInterface $account) {
   public function build() {
     return $this->formBuilder->getForm('Drupal\form_test\Form\RedirectBlockForm');
   }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Make cacheable once https://www.drupal.org/node/2351015 lands.
-   */
-  public function getCacheMaxAge() {
-    return 0;
-  }
-
 }
diff --git a/core/modules/system/tests/modules/pager_test/src/Controller/PagerTestController.php b/core/modules/system/tests/modules/pager_test/src/Controller/PagerTestController.php
index 2448cce..b277c75 100644
--- a/core/modules/system/tests/modules/pager_test/src/Controller/PagerTestController.php
+++ b/core/modules/system/tests/modules/pager_test/src/Controller/PagerTestController.php
@@ -69,7 +69,7 @@ public function queryParameters() {
    * #pre_render callback for #type => pager that shows the pager cache context.
    */
   public static function showPagerCacheContext(array $pager) {
-    drupal_set_message(\Drupal::service('cache_contexts')->convertTokensToKeys(['url.query_args.pagers:' . $pager['#element']])[0]);
+    drupal_set_message(\Drupal::service('cache_contexts')->convertTokensToKeys(['pager:' . $pager['#element']])[0]);
     return $pager;
   }
 
diff --git a/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml b/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml
index 05d5e27..37a0bf8 100644
--- a/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml
+++ b/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml
@@ -7,7 +7,3 @@ status: true
 langcode: en
 locked: false
 pattern: 'U'
-dependencies:
-  enforced:
-    theme:
-      - test_basetheme
diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php
index 79334e0..b88f740 100644
--- a/core/modules/system/theme.api.php
+++ b/core/modules/system/theme.api.php
@@ -162,6 +162,7 @@
  * removing them).
  *
  * @section assets Assets
+ *
  * We can distinguish between three types of assets:
  * 1. unconditional page-level assets (loaded on all pages where the theme is in
  *    use): these are defined in the theme's *.info.yml file.
@@ -209,7 +210,6 @@
  *
  * For further information on the Theme and Render APIs, see:
  * - https://drupal.org/documentation/theme
- * - https://www.drupal.org/developing/api/8/render
  * - https://drupal.org/node/722174
  * - https://drupal.org/node/933976
  * - https://drupal.org/node/930760
@@ -287,56 +287,9 @@
  * properties. Look through implementations of hook_element_info() to discover
  * elements defined this way.
  *
- * @section sec_caching Caching
- * The Drupal rendering process has the ability to cache rendered output at any
- * level in a render array hierarchy. This allows expensive calculations to be
- * done infrequently, and speeds up page loading. See the
- * @link cache Cache API topic @endlink for general information about the cache
- * system.
- *
- * In order to make caching possible, the following information needs to be
- * present:
- * - Cache keys: Identifiers for cacheable portions of render arrays. These
- *   should be created and added for portions of a render array that
- *   involve expensive calculations in the rendering process.
- * - Cache contexts: Contexts that may affect rendering, such as user role and
- *   language. When no context is specified, it means that the render array
- *   does not vary by any context.
- * - Cache tags: Tags for data that rendering depends on, such as for
- *   individual nodes or user accounts, so that when these change the cache
- *   can be automatically invalidated. If the data consists of entities, you
- *   can use \Drupal\Core\Entity\EntityInterface::getCacheTags() to generate
- *   appropriate tags; configuration objects have a similar method.
- * - Cache max-age: The maximum duration for which a render array may be cached.
- *   Defaults to \Drupal\Core\Cache\Cache::PERMANENT (permanently cacheable).
- *
- * Cache information is provided in the #cache property in a render array. In
- * this property, always supply the cache contexts, tags, and max-age if a
- * render array varies by context, depends on some modifiable data, or depends
- * on information that's only valid for a limited time, respectively. Cache keys
- * should only be set on the portions of a render array that should be cached.
- * Contexts are automatically replaced with the value for the current request
- * (e.g. the current language) and combined with the keys to form a cache ID.
- * The cache contexts, tags, and max-age will be propagated up the render array
- * hierarchy to determine cacheability for containing render array sections.
- *
- * Here's an example of what a #cache property might contain:
- * @code
- *   '#cache' => [
- *     'keys' => ['entity_view', 'node', $node->id()],
- *     'contexts' => ['language'],
- *     'tags' => ['node:' . $node->id()],
- *     'max-age' => Cache::PERMANENT,
- *   ],
- * @endcode
- *
- * At the response level, you'll see X-Drupal-Cache-Contexts and
- * X-Drupal-Cache-Tags headers.
+ * @section sec_attached Attaching libraries in render arrays
  *
- * See https://www.drupal.org/developing/api/8/render/arrays/cacheability for
- * details.
  *
- * @section sec_attached Attaching libraries in render arrays
  * Libraries, JavaScript settings, feeds, HTML <head> tags and HTML <head> links
  * are attached to elements using the #attached property. The #attached property
  * is an associative array, where the keys are the attachment types and the
@@ -350,53 +303,87 @@
  * values. Example:
  * @code
  * $build['#attached']['library'][] = 'core/jquery';
- * $build['#attached']['drupalSettings']['foo'] = 'bar';
+ * $build['#attached']['drupalSettings']['foo] = 'bar';
  * $build['#attached']['feed'][] = ['aggregator/rss', $this->t('Feed title')];
  * @endcode
  *
  * See drupal_process_attached() for additional information.
  *
- * @section render_pipeline The Render Pipeline
- * The term "render pipeline" refers to the process Drupal uses to take
- * information provided by modules and render it into a response. For more
- * details on this process, see https://www.drupal.org/developing/api/8/render;
- * for background on routing concepts, see @ref sec_controller.
- *
- * There are in fact multiple render pipelines:
- * - Drupal always uses the Symfony render pipeline. See
- *   http://symfony.com/doc/2.7/components/http_kernel/introduction.html
- * - Within the Symfony render pipeline, there is a Drupal render pipeline,
- *   which handles controllers that return render arrays. (Symfony's render
- *   pipeline only knows how to deal with Response objects; this pipeline
- *   converts render arrays into Response objects.) These render arrays are
- *   considered the main content, and can be rendered into multiple formats:
- *   HTML, Ajax, dialog, and modal. Modules can add support for more formats, by
- *   implementing a main content renderer, which is a service tagged with
- *   'render.main_content_renderer'.
- * - Finally, within the HTML main content renderer, there is another pipeline,
- *   to allow for rendering the page containing the main content in multiple
- *   ways: no decoration at all (just a page showing the main content) or blocks
- *   (a page with regions, with blocks positioned in regions around the main
- *   content). Modules can provide additional options, by implementing a page
- *   variant, which is a plugin annotated with
- *   \Drupal\Core\Display\Annotation\PageDisplayVariant.
- *
- * Routes whose controllers return a \Symfony\Component\HttpFoundation\Response
- * object are fully handled by the Symfony render pipeline.
- *
- * Routes whose controllers return the "main content" as a render array can be
- * requested in multiple formats (HTML, JSON, etc.) and/or in a "decorated"
- * manner, as described above.
+ * @section render_pipeline The Render Pipeline (or: how Drupal renders pages)
+ *
+ * First, you need to know the general routing concepts: please read
+ * @ref sec_controller first.
+ *
+ * Any route that returns the "main content" as a render array automatically has
+ * the ability to be requested in multiple ways: it can be rendered in a certain
+ * format (HTML, JSON …) and/or in a certain decorated manner (e.g. with blocks
+ * around the main content).
+ *
+ * After the controller returned a render array, the @code VIEW @endcode event
+ * (\Symfony\Component\HttpKernel\KernelEvents::VIEW) will be triggered, because
+ * the controller result is not a Response, but a render array.
+ *
+ * \Drupal\Core\EventSubscriber\MainContentViewSubscriber is subscribed to the
+ * @code VIEW @endcode event. It checks whether the controller result is an
+ * array, and if so, guarantees to generate a Response.
+ *
+ * Next, it checks whether the negotiated request format is supported. Any
+ * format for which a main content renderer service exists (an implementation of
+ * \Drupal\Core\Render\MainContent\MainContentRendererInterface) is supported.
+ *
+ * If the negotiated request format is not supported, a 406 JSON response is
+ * generated, which lists the supported formats in a machine-readable way(as per
+ * RFC 2616, section 10.4.7).
+ *
+ * Otherwise, when the negotiated request format is supported, the corresponding
+ * main content renderer service is initialized. A response is generated by
+ * calling \Drupal\Core\Render\MainContent\MainContentRendererInterface::renderResponse()
+ * on the service. That's it!
+ *
+ * Each main content renderer service can choose how to implement its
+ * renderResponse() method. It may of course choose to add protected helper
+ * methods to provide more structure, if it's a complex main content renderer.
+ *
+ * The above is the general flow. But let's take a look at the HTML main content
+ * renderer (\Drupal\Core\Render\MainContent\HtmlRenderer), because that will be
+ * used most often.
+ *
+ * \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse() first calls a
+ * helper method, @code prepare() @endcode, which takes the main content render
+ * array and returns a #type 'page' render array. A #type 'page' render array
+ * represents the final <body> for the HTML document (page.html.twig). The
+ * remaining task for @code renderResponse() @endcode is to wrap the #type
+ * 'page' render array in a #type 'html' render array, which then represents the
+ * entire HTML document (html.html.twig).
+ * Hence the steps are:
+ * 1. \Drupal\Core\Render\MainContent\HtmlRenderer::prepare() takes the main
+ *    content render array; if it already is #type 'page', then most of the work
+ *    it must do is already done. In the other case, we need to build that #type
+ *    'page' render array still. The RenderEvents::SELECT_PAGE_DISPLAY_VARIANT
+ *    event is dispatched, to select a page display variant. By default,
+ *    \Drupal\Core\Render\Plugin\DisplayVariant\SimplePageVariant is used, which
+ *    doesn't apply any decorations. But, when Block module is enabled,
+ *    \Drupal\block\Plugin\DisplayVariant\BlockPageVariant is used, which allows
+ *    the site builder to place blocks in any of the page regions, and hence
+ *    "decorate" the main content.
+ * 2. \Drupal\Core\Render\MainContent\HtmlRenderer::prepare() now is guaranteed
+ *    to be working on a #type 'page' render array. hook_page_attachments() and
+ *    hook_page_attachments_alter() are invoked.
+ * 3. \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse() uses the
+ *    #type 'page' render array returned by the previous step and wraps it in
+ *    #type 'html'. hook_page_top() and hook_page_bottom() are invoked.
+ * 4. drupal_render() is called on the #type 'html' render array, which uses
+ *    the html.html.twig template and the return value is a HTML document as a
+ *    string.
+ * 5. This string of HTML is returned as the Response.
+ *
+ * For HTML pages to be rendered in limited environments, such as when you are
+ * installing or updating Drupal, or when you put it in maintenance mode, or
+ * when an error occurs, a simpler HTML page renderer is used for rendering
+ * these bare pages: \Drupal\Core\Render\BareHtmlPageRenderer
+ *
  *
  * @see themeable
- * @see \Symfony\Component\HttpKernel\KernelEvents::VIEW
- * @see \Drupal\Core\EventSubscriber\MainContentViewSubscriber
- * @see \Drupal\Core\Render\MainContent\MainContentRendererInterface
- * @see \Drupal\Core\Render\MainContent\HtmlRenderer
- * @see \Drupal\Core\Render\RenderEvents::SELECT_PAGE_DISPLAY_VARIANT
- * @see \Drupal\Core\Render\Plugin\DisplayVariant\SimplePageVariant
- * @see \Drupal\block\Plugin\DisplayVariant\BlockPageVariant
- * @see \Drupal\Core\Render\BareHtmlPageRenderer
  *
  * @}
  */
diff --git a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/install/views.view.taxonomy_term.yml
similarity index 100%
rename from core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml
rename to core/modules/taxonomy/config/install/views.view.taxonomy_term.yml
diff --git a/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
index 2a3c4ad..61281fb 100644
--- a/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
+++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
@@ -46,11 +46,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       '#title' => $this->t("Create referenced entities if they don't already exist"),
       '#default_value' => isset($this->configuration['handler_settings']['auto_create']) ? $this->configuration['handler_settings']['auto_create'] : FALSE,
     );
-
-    // Sorting is not possible for taxonomy terms because we use
-    // \Drupal\taxonomy\TermStorageInterface::loadTree() to retrieve matches.
-    $form['sort']['#access'] = FALSE;
-
     return $form;
 
   }
diff --git a/core/modules/taxonomy/src/Plugin/views/argument/Taxonomy.php b/core/modules/taxonomy/src/Plugin/views/argument/Taxonomy.php
index 87704ed..41a7f5d 100644
--- a/core/modules/taxonomy/src/Plugin/views/argument/Taxonomy.php
+++ b/core/modules/taxonomy/src/Plugin/views/argument/Taxonomy.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Drupal\Component\Utility\String;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -20,7 +20,7 @@
  *
  * @ViewsArgument("taxonomy")
  */
-class Taxonomy extends NumericArgument implements ContainerFactoryPluginInterface {
+class Taxonomy extends Numeric implements ContainerFactoryPluginInterface {
 
   /**
    * @var EntityStorageInterface
diff --git a/core/modules/taxonomy/src/Plugin/views/argument/VocabularyVid.php b/core/modules/taxonomy/src/Plugin/views/argument/VocabularyVid.php
index 2b92822..597f826 100644
--- a/core/modules/taxonomy/src/Plugin/views/argument/VocabularyVid.php
+++ b/core/modules/taxonomy/src/Plugin/views/argument/VocabularyVid.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\taxonomy\Plugin\views\argument;
 
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Drupal\Component\Utility\String;
 use Drupal\taxonomy\VocabularyStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -19,7 +19,7 @@
  *
  * @ViewsArgument("vocabulary_vid")
  */
-class VocabularyVid extends NumericArgument {
+class VocabularyVid extends Numeric {
 
   /**
     * The vocabulary storage.
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 a8751d5..5bd3f45 100644
--- a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
+++ b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
@@ -230,7 +230,7 @@ public function isCacheable() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return ['url'];
+    return ['cache.context.url'];
   }
 
   /**
diff --git a/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php b/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php
index fba0f15..4985038 100644
--- a/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php
+++ b/core/modules/taxonomy/src/Tests/TaxonomyImageTest.php
@@ -78,7 +78,6 @@ public function testTaxonomyImageAccess() {
     $edit['name[0][value]'] = $this->randomMachineName();
     $edit['files[field_test_0]'] = drupal_realpath($image->uri);
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id()  . '/add', $edit, t('Save'));
-    $this->drupalPostForm(NULL, ['field_test[0][alt]' => $this->randomMachineName()], t('Save'));
     $terms = entity_load_multiple_by_properties('taxonomy_term', array('name' => $edit['name[0][value]']));
     $term = reset($terms);
     $this->assertText(t('Created new term @name.', array('@name' => $term->getName())));
diff --git a/core/modules/taxonomy/src/Tests/TermLanguageTest.php b/core/modules/taxonomy/src/Tests/TermLanguageTest.php
index c679204..011404d 100644
--- a/core/modules/taxonomy/src/Tests/TermLanguageTest.php
+++ b/core/modules/taxonomy/src/Tests/TermLanguageTest.php
@@ -102,7 +102,7 @@ function testDefaultTermLanguage() {
 
     // Change the default language of the site and check if the default terms
     // language is still correctly selected.
-    $this->config('system.site')->set('default_langcode', 'cc')->save();
+    $this->config('system.site')->set('langcode', 'cc')->save();
     $edit = array(
       'default_language[langcode]' => LanguageInterface::LANGCODE_SITE_DEFAULT,
       'default_language[language_alterable]' => TRUE,
diff --git a/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php b/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php
index 1c174d4..4e3a9f0 100644
--- a/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php
+++ b/core/modules/taxonomy/src/Tests/VocabularyCrudTest.php
@@ -41,10 +41,9 @@ function testTaxonomyVocabularyDeleteWithTerms() {
     foreach (Vocabulary::loadMultiple() as $vocabulary) {
       $vocabulary->delete();
     }
-    $query = \Drupal::entityQuery('taxonomy_term')->count();
 
     // Assert that there are no terms left.
-    $this->assertEqual(0, $query->execute(), 'There are no terms remaining.');
+    $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {taxonomy_term_data}')->fetchField(), 'There are no terms remaining.');
 
     $terms = array();
     for ($i = 0; $i < 5; $i++) {
@@ -58,12 +57,12 @@ function testTaxonomyVocabularyDeleteWithTerms() {
     $terms[4]->save();
 
     // Assert that there are now 5 terms.
-    $this->assertEqual(5, $query->execute(), 'There are 5 terms found.');
+    $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {taxonomy_term_data}')->fetchField(), 'There are 5 terms found.');
 
     $vocabulary->delete();
 
     // Assert that there are no terms left.
-    $this->assertEqual(0, $query->execute(), 'All terms are deleted.');
+    $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {taxonomy_term_data}')->fetchField(), 'All terms are deleted.');
   }
 
   /**
diff --git a/core/modules/text/text.js b/core/modules/text/text.js
index 0895415..10aed14 100644
--- a/core/modules/text/text.js
+++ b/core/modules/text/text.js
@@ -7,7 +7,7 @@
    */
   Drupal.behaviors.textSummary = {
     attach: function (context, settings) {
-      $(context).find('.text-summary').once('text-summary').each(function () {
+      $(context).find('.text-summary').once('text-summary', function () {
         var $widget = $(this).closest('.text-format-wrapper');
 
         var $summary = $widget.find('.text-summary-wrapper');
diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js
index efbad03..dcfbb2a 100644
--- a/core/modules/toolbar/js/toolbar.js
+++ b/core/modules/toolbar/js/toolbar.js
@@ -43,7 +43,7 @@
         return;
       }
       // Process the administrative toolbar.
-      $(context).find('#toolbar-administration').once('toolbar').each(function () {
+      $(context).find('#toolbar-administration').once('toolbar', function () {
 
         // Establish the toolbar models and views.
         var model = Drupal.toolbar.models.toolbarModel = new Drupal.toolbar.ToolbarModel({
diff --git a/core/modules/tour/js/tour.js b/core/modules/tour/js/tour.js
index f8bc85f..cee9feb 100644
--- a/core/modules/tour/js/tour.js
+++ b/core/modules/tour/js/tour.js
@@ -23,7 +23,7 @@
    */
   Drupal.behaviors.tour = {
     attach: function (context) {
-      $('body').once('tour').each(function() {
+      $('body').once('tour', function (index, element) {
         var model = new Drupal.tour.models.StateModel();
         new Drupal.tour.views.ToggleTourView({
           el: $(context).find('#toolbar-tab-tour'),
@@ -42,6 +42,7 @@
         if (/tour=?/i.test(queryString)) {
           model.set('isActive', true);
         }
+
       });
     }
   };
diff --git a/core/modules/update/src/Access/UpdateManagerAccessCheck.php b/core/modules/update/src/Access/UpdateManagerAccessCheck.php
index d057ce3..dc4fd7b 100644
--- a/core/modules/update/src/Access/UpdateManagerAccessCheck.php
+++ b/core/modules/update/src/Access/UpdateManagerAccessCheck.php
@@ -17,23 +17,6 @@
 class UpdateManagerAccessCheck implements AccessInterface {
 
   /**
-   * Settings Service.
-   *
-   * @var \Drupal\Core\Site\Settings
-   */
-  protected $settings;
-
-  /**
-   * Constructs a UpdateManagerAccessCheck object.
-   *
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The read-only settings container.
-   */
-  public function __construct(Settings $settings) {
-    $this->settings = $settings;
-  }
-
-  /**
    * Checks access.
    *
    * @return \Drupal\Core\Access\AccessResultInterface
@@ -42,7 +25,7 @@ public function __construct(Settings $settings) {
   public function access() {
     // Uncacheable because the access result depends on a Settings key-value
     // pair, and can therefore change at any time.
-    return AccessResult::allowedIf($this->settings->get('allow_authorize_operations', TRUE))->setCacheable(FALSE);
+    return AccessResult::allowedIf(Settings::get('allow_authorize_operations', TRUE))->setCacheable(FALSE);
   }
 
 }
diff --git a/core/modules/update/update.services.yml b/core/modules/update/update.services.yml
index c14b8cc..8bcd5d6 100644
--- a/core/modules/update/update.services.yml
+++ b/core/modules/update/update.services.yml
@@ -1,7 +1,6 @@
 services:
   access_check.update.manager_access:
     class: Drupal\update\Access\UpdateManagerAccessCheck
-    arguments: ['@settings']
     tags:
       - { name: access_check, applies_to: _access_update_manager }
   update.manager:
diff --git a/core/modules/user/config/optional/rdf.mapping.user.user.yml b/core/modules/user/config/install/rdf.mapping.user.user.yml
similarity index 100%
rename from core/modules/user/config/optional/rdf.mapping.user.user.yml
rename to core/modules/user/config/install/rdf.mapping.user.user.yml
diff --git a/core/modules/user/config/optional/search.page.user_search.yml b/core/modules/user/config/install/search.page.user_search.yml
similarity index 100%
rename from core/modules/user/config/optional/search.page.user_search.yml
rename to core/modules/user/config/install/search.page.user_search.yml
diff --git a/core/modules/user/config/install/user.settings.yml b/core/modules/user/config/install/user.settings.yml
index 8372ccd..788d95a 100644
--- a/core/modules/user/config/install/user.settings.yml
+++ b/core/modules/user/config/install/user.settings.yml
@@ -10,6 +10,7 @@ notify:
   register_no_approval_required: true
   register_pending_approval: true
 register: visitors
+signatures: false
 cancel_method: user_cancel_block
 password_reset_timeout: 86400
 password_strength: true
diff --git a/core/modules/user/config/optional/views.view.user_admin_people.yml b/core/modules/user/config/install/views.view.user_admin_people.yml
similarity index 100%
rename from core/modules/user/config/optional/views.view.user_admin_people.yml
rename to core/modules/user/config/install/views.view.user_admin_people.yml
diff --git a/core/modules/user/config/optional/views.view.who_s_new.yml b/core/modules/user/config/install/views.view.who_s_new.yml
similarity index 100%
rename from core/modules/user/config/optional/views.view.who_s_new.yml
rename to core/modules/user/config/install/views.view.who_s_new.yml
diff --git a/core/modules/user/config/optional/views.view.who_s_online.yml b/core/modules/user/config/install/views.view.who_s_online.yml
similarity index 100%
rename from core/modules/user/config/optional/views.view.who_s_online.yml
rename to core/modules/user/config/install/views.view.who_s_online.yml
diff --git a/core/modules/user/config/schema/user.schema.yml b/core/modules/user/config/schema/user.schema.yml
index 09e5989..f38fd4c 100644
--- a/core/modules/user/config/schema/user.schema.yml
+++ b/core/modules/user/config/schema/user.schema.yml
@@ -41,6 +41,9 @@ user.settings:
     register:
       type: string
       label: 'Who can register accounts?'
+    signatures:
+      type: boolean
+      label: 'Enable signatures'
     cancel_method:
       type: string
       label: 'When cancelling a user account'
diff --git a/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php
index 4c6db06..8c14682 100644
--- a/core/modules/user/src/AccountForm.php
+++ b/core/modules/user/src/AccountForm.php
@@ -232,6 +232,29 @@ public function form(array $form, FormStateInterface $form_state) {
       '#access' => $register && $admin,
     );
 
+    // Signature.
+    $form['signature_settings'] = array(
+      '#type' => 'details',
+      '#title' => $this->t('Signature settings'),
+      '#open' => TRUE,
+      '#weight' => 1,
+      '#access' => (!$register && $config->get('signatures')),
+    );
+    // While the details group will simply not be rendered if empty, the actual
+    // signature element cannot use #access, since #type 'text_format' is not
+    // available when Filter module is not installed. If the user account has an
+    // existing signature value and format, then the existing field values will
+    // just be re-saved to the database in case of an entity update.
+    if ($this->moduleHandler->moduleExists('filter')) {
+      $form['signature_settings']['signature'] = array(
+        '#type' => 'text_format',
+        '#title' => $this->t('Signature'),
+        '#default_value' => $account->getSignature(),
+        '#description' => $this->t('Your signature will be publicly displayed at the end of your comments.'),
+        '#format' => $account->getSignatureFormat(),
+      );
+    }
+
     $user_preferred_langcode = $register ? $language_interface->getId() : $account->getPreferredLangcode();
 
     $user_preferred_admin_langcode = $register ? $language_interface->getId() : $account->getPreferredAdminLangcode(FALSE);
@@ -342,6 +365,12 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
     /** @var \Drupal\user\UserInterface $account */
     $account = parent::buildEntity($form, $form_state);
 
+    // Take care of mapping signature form element values as their structure
+    // does not directly match the field structure.
+    $signature = $form_state->getValue('signature');
+    $account->setSignature($signature['value']);
+    $account->setSignatureFormat($signature['format']);
+
     // Translate the empty value '' of language selects to an unset field.
     foreach (array('preferred_langcode', 'preferred_admin_langcode') as $field_name) {
       if ($form_state->getValue($field_name) === '') {
@@ -364,6 +393,8 @@ public function validate(array $form, FormStateInterface $form_state) {
     $field_names = array(
       'name',
       'mail',
+      'signature',
+      'signature_format',
       'timezone',
       'langcode',
       'preferred_langcode',
diff --git a/core/modules/user/src/AccountSettingsForm.php b/core/modules/user/src/AccountSettingsForm.php
index df65cb8..38c39e6 100644
--- a/core/modules/user/src/AccountSettingsForm.php
+++ b/core/modules/user/src/AccountSettingsForm.php
@@ -194,6 +194,12 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#open' => TRUE,
       '#access' => $filter_exists,
     );
+    $form['personalization']['user_signatures'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Enable signatures'),
+      '#default_value' => $filter_exists ? $config->get('signatures') : 0,
+      '#access' => $filter_exists,
+    );
 
     // Default notifications address.
     $form['mail_notification_address'] = array(
@@ -444,6 +450,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       ->set('register', $form_state->getValue('user_register'))
       ->set('password_strength', $form_state->getValue('user_password_strength'))
       ->set('verify_mail', $form_state->getValue('user_email_verification'))
+      ->set('signatures', $form_state->getValue('user_signatures'))
       ->set('cancel_method', $form_state->getValue('user_cancel_method'))
       ->set('notify.status_activated', $form_state->getValue('user_mail_status_activated_notify'))
       ->set('notify.status_blocked', $form_state->getValue('user_mail_status_blocked_notify'))
@@ -486,6 +493,9 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         $this->roleStorage->load($new_admin_role)->setIsAdmin(TRUE)->save();
       }
     }
+
+    // Clear field definition cache for signatures.
+    \Drupal::entityManager()->clearCachedFieldDefinitions();
   }
 
 }
diff --git a/core/lib/Drupal/Core/Cache/UserCacheContext.php b/core/modules/user/src/Cache/UserCacheContext.php
similarity index 83%
copy from core/lib/Drupal/Core/Cache/UserCacheContext.php
copy to core/modules/user/src/Cache/UserCacheContext.php
index d5e2825..d9d880e 100644
--- a/core/lib/Drupal/Core/Cache/UserCacheContext.php
+++ b/core/modules/user/src/Cache/UserCacheContext.php
@@ -2,11 +2,12 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Cache\UserCacheContext.
+ * Contains \Drupal\user\Cache\UserCacheContext.
  */
 
-namespace Drupal\Core\Cache;
+namespace Drupal\user\Cache;
 
+use Drupal\Core\Cache\CacheContextInterface;
 use Drupal\Core\Session\AccountInterface;
 
 /**
diff --git a/core/lib/Drupal/Core/Cache/UserCacheContext.php b/core/modules/user/src/Cache/UserRolesCacheContext.php
similarity index 50%
rename from core/lib/Drupal/Core/Cache/UserCacheContext.php
rename to core/modules/user/src/Cache/UserRolesCacheContext.php
index d5e2825..0f7975d 100644
--- a/core/lib/Drupal/Core/Cache/UserCacheContext.php
+++ b/core/modules/user/src/Cache/UserRolesCacheContext.php
@@ -2,20 +2,21 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Cache\UserCacheContext.
+ * Contains \Drupal\user\Cache\UserRolesCacheContext.
  */
 
-namespace Drupal\Core\Cache;
+namespace Drupal\user\Cache;
 
+use Drupal\Core\Cache\CacheContextInterface;
 use Drupal\Core\Session\AccountInterface;
 
 /**
- * Defines the UserCacheContext service, for "per user" caching.
+ * Defines the UserRolesCacheContext service, for "per role" caching.
  */
-class UserCacheContext implements CacheContextInterface {
+class UserRolesCacheContext implements CacheContextInterface {
 
   /**
-   * Constructs a new UserCacheContext service.
+   * Constructs a new UserRolesCacheContext service.
    *
    * @param \Drupal\Core\Session\AccountInterface $user
    *   The current user.
@@ -28,14 +29,14 @@ public function __construct(AccountInterface $user) {
    * {@inheritdoc}
    */
   public static function getLabel() {
-    return t('User');
+    return t("User's roles");
   }
 
   /**
    * {@inheritdoc}
    */
   public function getContext() {
-    return "u." . $this->user->id();
+    return 'r.' . implode(',', $this->user->getRoles());
   }
 
 }
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 1cecfdc..96b40ee 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -286,6 +286,36 @@ public function setEmail($mail) {
   /**
    * {@inheritdoc}
    */
+  public function getSignature() {
+    return $this->get('signature')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setSignature($signature) {
+    $this->get('signature')->value = $signature;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSignatureFormat() {
+    return $this->get('signature_format')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setSignatureFormat($signature_format) {
+    $this->get('signature_format')->value = $signature_format;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getCreatedTime() {
     return $this->get('created')->value;
   }
@@ -495,6 +525,20 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->addConstraint('UserMailUnique')
       ->addConstraint('UserMailRequired');
 
+    // @todo Convert to a text field in https://drupal.org/node/1548204.
+    $fields['signature'] = BaseFieldDefinition::create('string')
+      ->setLabel(t('Signature'))
+      ->setDescription(t('The signature of this user.'))
+      ->setTranslatable(TRUE);
+    $fields['signature_format'] = BaseFieldDefinition::create('string')
+      ->setLabel(t('Signature format'))
+      ->setDescription(t('The signature format of this user.'))
+      // @todo: Define this via an options provider once
+      // https://www.drupal.org/node/2329937 is completed.
+      ->addPropertyConstraints('value', array(
+        'AllowedValues' => array('callback' => __CLASS__ . '::getAllowedSignatureFormats'),
+      ));
+
     $fields['timezone'] = BaseFieldDefinition::create('string')
       ->setLabel(t('Timezone'))
       ->setDescription(t('The timezone of this user.'))
@@ -553,6 +597,20 @@ protected function getRoleStorage() {
   }
 
   /**
+   * Defines allowed signature formats for the field's AllowedValues constraint.
+   *
+   * @return string[]
+   *   The allowed values.
+   */
+  public static function getAllowedSignatureFormats() {
+    if (\Drupal::moduleHandler()->moduleExists('filter')) {
+      return array_keys(filter_formats());
+    }
+    // If filter.module is disabled, no value may be assigned.
+    return array();
+  }
+
+  /**
    * Defines allowed timezones for the field's AllowedValues constraint.
    *
    * @return string[]
diff --git a/core/modules/user/src/Plugin/Block/UserLoginBlock.php b/core/modules/user/src/Plugin/Block/UserLoginBlock.php
index 64c4990..8fc92f0 100644
--- a/core/modules/user/src/Plugin/Block/UserLoginBlock.php
+++ b/core/modules/user/src/Plugin/Block/UserLoginBlock.php
@@ -113,13 +113,4 @@ public function build() {
     );
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Make cacheable once https://www.drupal.org/node/2351015 lands.
-   */
-  public function getCacheMaxAge() {
-    return 0;
-  }
-
 }
diff --git a/core/modules/user/src/Plugin/views/argument/Uid.php b/core/modules/user/src/Plugin/views/argument/Uid.php
index 63db23c..2c4a087 100644
--- a/core/modules/user/src/Plugin/views/argument/Uid.php
+++ b/core/modules/user/src/Plugin/views/argument/Uid.php
@@ -9,7 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -19,7 +19,7 @@
  *
  * @ViewsArgument("user_uid")
  */
-class Uid extends NumericArgument {
+class Uid extends Numeric {
 
   /**
    * The user storage.
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 269be4e..e3d9644 100644
--- a/core/modules/user/src/Plugin/views/argument_default/User.php
+++ b/core/modules/user/src/Plugin/views/argument_default/User.php
@@ -123,7 +123,7 @@ public function isCacheable() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return ['url'];
+    return ['cache.context.url'];
   }
 
 }
diff --git a/core/modules/user/src/Tests/UserEditTest.php b/core/modules/user/src/Tests/UserEditTest.php
index 308fad9..38acdb8 100644
--- a/core/modules/user/src/Tests/UserEditTest.php
+++ b/core/modules/user/src/Tests/UserEditTest.php
@@ -17,11 +17,50 @@
 class UserEditTest extends WebTestBase {
 
   /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('filter');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->config('user.settings')->set('signatures', TRUE)->save();
+
+    // Prefetch and create text formats.
+    $this->filtered_html_format = entity_create('filter_format', array(
+      'format' => 'filtered_html_format',
+      'name' => 'Filtered HTML',
+      'weight' => -1,
+      'filters' => array(
+        'filter_html' => array(
+          'module' => 'filter',
+          'status' => TRUE,
+          'settings' => array(
+            'allowed_html' => '<a> <em> <strong>',
+          ),
+        ),
+      ),
+    ));
+    $this->filtered_html_format->save();
+
+    $this->full_html_format = entity_create('filter_format', array(
+      'format' => 'full_html',
+      'name' => 'Full HTML',
+    ));
+    $this->full_html_format->save();
+  }
+
+  /**
    * Test user edit page.
    */
   function testUserEdit() {
     // Test user edit functionality.
-    $user1 = $this->drupalCreateUser(array('change own username'));
+    $user1 = $this->drupalCreateUser(array('change own username', $this->full_html_format->getPermissionName(), $this->filtered_html_format->getPermissionName()));
     $user2 = $this->drupalCreateUser(array());
     $this->drupalLogin($user1);
 
@@ -85,6 +124,11 @@ function testUserEdit() {
     $config->set('password_strength', FALSE)->save();
     $this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
     $this->assertNoRaw(t('Password strength:'), 'The password strength indicator is not displayed.');
+
+    // Test user signature
+    $edit = array('signature[format]' => $this->full_html_format->id(), 'signature[value]' => $this->randomString(256));
+    $this->drupalPostForm('user/' . $user1->id() . '/edit', $edit, t('Save'));
+    $this->assertRaw(t("%name: may not be longer than @max characters.", array('%name' => t('Signature'), '@max' => 255)));
   }
 
   /**
diff --git a/core/modules/user/src/Tests/UserRegistrationTest.php b/core/modules/user/src/Tests/UserRegistrationTest.php
index 2666665..447a7cb 100644
--- a/core/modules/user/src/Tests/UserRegistrationTest.php
+++ b/core/modules/user/src/Tests/UserRegistrationTest.php
@@ -184,6 +184,7 @@ function testRegistrationDefaultValues() {
     $new_user = reset($accounts);
     $this->assertEqual($new_user->getUsername(), $name, 'Username matches.');
     $this->assertEqual($new_user->getEmail(), $mail, 'Email address matches.');
+    $this->assertEqual($new_user->getSignature(), '', 'Correct signature field.');
     $this->assertTrue(($new_user->getCreatedTime() > REQUEST_TIME - 20 ), 'Correct creation time.');
     $this->assertEqual($new_user->isActive(), $config_user_settings->get('register') == USER_REGISTER_VISITORS ? 1 : 0, 'Correct status field.');
     $this->assertEqual($new_user->getTimezone(), $config_system_date->get('timezone.default'), 'Correct time zone field.');
diff --git a/core/modules/user/src/Tests/UserSignatureTest.php b/core/modules/user/src/Tests/UserSignatureTest.php
new file mode 100644
index 0000000..47b1636
--- /dev/null
+++ b/core/modules/user/src/Tests/UserSignatureTest.php
@@ -0,0 +1,174 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\user\Tests\UserSignatureTest.
+ */
+
+namespace Drupal\user\Tests;
+
+use Drupal\comment\Tests\CommentTestTrait;
+use Drupal\simpletest\WebTestBase;
+use Drupal\user\RoleInterface;
+
+/**
+ * Tests case for user signatures.
+ *
+ * @group user
+ */
+class UserSignatureTest extends WebTestBase {
+
+  use CommentTestTrait;
+
+  /**
+   * A regular user.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $webUser;
+
+  /**
+   * User with admin privileges.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $adminUser;
+
+  /**
+   * Filtered HTML format.
+   *
+   * @var \Drupal\filter\FilterFormatInterface
+   */
+  protected $filteredHtmlFormat;
+
+  /**
+   * Full HTML format.
+   *
+   * @var \Drupal\filter\FilterFormatInterface
+   */
+  protected $fullHtmlFormat;
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('node', 'comment', 'field_ui');
+
+  protected function setUp() {
+    parent::setUp();
+
+    // Enable user signatures.
+    $this->config('user.settings')->set('signatures', 1)->save();
+
+    // Create Basic page node type.
+    $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+    // Add a comment field with commenting enabled by default.
+    $this->addDefaultCommentField('node', 'page');
+
+    // Prefetch and create text formats.
+    $this->filteredHtmlFormat = entity_create('filter_format', array(
+      'format' => 'filtered_html_format',
+      'name' => 'Filtered HTML',
+      'weight' => -1,
+      'filters' => array(
+        'filter_html' => array(
+          'module' => 'filter',
+          'status' => TRUE,
+          'settings' => array(
+            'allowed_html' => '<a> <em> <strong>',
+          ),
+        ),
+      ),
+    ));
+    $this->filteredHtmlFormat->save();
+
+    $this->fullHtmlFormat = entity_create('filter_format', array(
+      'format' => 'full_html',
+      'name' => 'Full HTML',
+    ));
+    $this->fullHtmlFormat->save();
+
+    user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, array($this->filteredHtmlFormat->getPermissionName()));
+
+    // Create regular and administrative users.
+    $this->webUser = $this->drupalCreateUser(array('post comments'));
+
+    $admin_permissions = array('post comments', 'administer comments', 'administer user form display', 'administer account settings');
+    foreach (filter_formats() as $format) {
+      if ($permission = $format->getPermissionName()) {
+        $admin_permissions[] = $permission;
+      }
+    }
+    $this->adminUser = $this->drupalCreateUser($admin_permissions);
+  }
+
+  /**
+   * Test that a user can change their signature format and that it is respected
+   * upon display.
+   */
+  function testUserSignature() {
+    $node = $this->drupalCreateNode(array(
+      'body' => array(
+        0 => array(
+          'value' => $this->randomMachineName(32),
+          'format' => 'full_html',
+        ),
+      ),
+    ));
+
+    // Verify that user signature field is not displayed on registration form.
+    $this->drupalGet('user/register');
+    $this->assertNoText(t('Signature'));
+
+    // Log in as a regular user and create a signature.
+    $this->drupalLogin($this->webUser);
+    $signature_text = "<h1>" . $this->randomMachineName() . "</h1>";
+    $edit = array(
+      'signature[value]' => $signature_text,
+    );
+    $this->drupalPostForm('user/' . $this->webUser->id() . '/edit', $edit, t('Save'));
+
+    // Verify that values were stored.
+    $this->assertFieldByName('signature[value]', $edit['signature[value]'], 'Submitted signature text found.');
+
+    // Verify that the user signature's text format's cache tag is absent.
+    $this->drupalGet('node/' . $node->id());
+    $this->assertTrue(!in_array('filter_format:filtered_html_format', explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags'))));
+
+    // Create a comment.
+    $edit = array();
+    $edit['subject[0][value]'] = $this->randomMachineName(8);
+    $edit['comment_body[0][value]'] = $this->randomMachineName(16);
+    $this->drupalPostForm('comment/reply/node/' . $node->id() .'/comment', $edit, t('Preview'));
+    $this->drupalPostForm(NULL, array(), t('Save'));
+
+    // Get the comment ID. (This technique is the same one used in the Comment
+    // module's CommentTestBase test case.)
+    preg_match('/#comment-([0-9]+)/', $this->getURL(), $match);
+    $comment_id = $match[1];
+
+    // Log in as an administrator and edit the comment to use Full HTML, so
+    // that the comment text itself is not filtered at all.
+    $this->drupalLogin($this->adminUser);
+    $edit['comment_body[0][format]'] = $this->fullHtmlFormat->id();
+    $this->drupalPostForm('comment/' . $comment_id . '/edit', $edit, t('Save'));
+
+    // Assert that the signature did not make it through unfiltered.
+    $this->drupalGet('node/' . $node->id());
+    $this->assertNoRaw($signature_text, 'Unfiltered signature text not found.');
+    $this->assertRaw(check_markup($signature_text, $this->filteredHtmlFormat->id()), 'Filtered signature text found.');
+    // Verify that the user signature's text format's cache tag is present.
+    $this->drupalGet('node/' . $node->id());
+    $this->assertTrue(in_array('config:filter.format.filtered_html_format', explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags'))));
+
+    // Verify the signature field is available on Manage form display page.
+    $this->config('user.settings')->set('signatures', 0)->save();
+    \Drupal::entityManager()->clearCachedFieldDefinitions();
+    $this->drupalGet('admin/config/people/accounts/form-display');
+    $this->assertNoText('Signature settings');
+    $this->drupalPostForm('admin/config/people/accounts', array('user_signatures' => TRUE), t('Save configuration'));
+    $this->drupalGet('admin/config/people/accounts/form-display');
+    $this->assertText('Signature settings');
+  }
+}
diff --git a/core/modules/user/src/Tests/UserValidationTest.php b/core/modules/user/src/Tests/UserValidationTest.php
index d0d4864..acc64b7 100644
--- a/core/modules/user/src/Tests/UserValidationTest.php
+++ b/core/modules/user/src/Tests/UserValidationTest.php
@@ -139,6 +139,14 @@ function testValidation() {
     $this->assertEqual($violations[0]->getMessage(), t('!name field is required.', array('!name' => String::placeholder($user->getFieldDefinition('mail')->getLabel()))));
     $user->set('mail', 'someone@example.com');
 
+    $user->set('signature', $this->randomString(256));
+    $this->assertLengthViolation($user, 'signature', 255);
+    $user->set('signature', NULL);
+
+    $user->set('signature_format', $this->randomString(32));
+    $this->assertAllowedValuesViolation($user, 'signature_format');
+    $user->set('signature_format', NULL);
+
     $user->set('timezone', $this->randomString(33));
     $this->assertLengthViolation($user, 'timezone', 32, 2, 1);
     $user->set('timezone', 'invalid zone');
diff --git a/core/modules/user/src/UserAccessControlHandler.php b/core/modules/user/src/UserAccessControlHandler.php
index ab104f0..91d163e 100644
--- a/core/modules/user/src/UserAccessControlHandler.php
+++ b/core/modules/user/src/UserAccessControlHandler.php
@@ -95,6 +95,8 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
 
       case 'preferred_langcode':
       case 'preferred_admin_langcode':
+      case 'signature':
+      case 'signature_format':
       case 'timezone':
       case 'mail':
         // Allow view access to own mail address and other personalization
diff --git a/core/modules/user/src/UserInterface.php b/core/modules/user/src/UserInterface.php
index 0797776..c6f3b2a 100644
--- a/core/modules/user/src/UserInterface.php
+++ b/core/modules/user/src/UserInterface.php
@@ -87,6 +87,44 @@ public function setPassword($password);
   public function setEmail($mail);
 
   /**
+   * Returns the user signature.
+   *
+   * @todo: Convert this to a configurable field.
+   *
+   * @return string
+   *   The signature text.
+   */
+  public function getSignature();
+
+  /**
+   * Sets the user signature.
+   *
+   * @param string $signature
+   *   The new signature text of the user.
+   *
+   * @return $this
+   */
+  public function setSignature($signature);
+
+  /**
+   * Returns the signature format.
+   *
+   * @return string
+   *   Name of the filter format.
+   */
+  public function getSignatureFormat();
+
+  /**
+   * Sets the signature format.
+   *
+   * @param string $signature_format
+   *   The name of the new filter format.
+   *
+   * @return $this
+   */
+  public function setSignatureFormat($signature_format);
+
+  /**
    * Returns the creation time of the user as a UNIX timestamp.
    *
    * @return int
diff --git a/core/modules/user/src/UserViewsData.php b/core/modules/user/src/UserViewsData.php
index 621da71..e043ac1 100644
--- a/core/modules/user/src/UserViewsData.php
+++ b/core/modules/user/src/UserViewsData.php
@@ -218,6 +218,24 @@ public function getViewsData() {
       ),
     );
 
+    unset($data['users_field_data']['signature']);
+    unset($data['users_field_data']['signature_format']);
+
+    if (\Drupal::moduleHandler()->moduleExists('filter')) {
+      $data['users_field_data']['signature'] = array(
+        'title' => t('Signature'),
+        'help' => t("The user's signature."),
+        'field' => array(
+          'id' => 'markup',
+          'format' => filter_fallback_format(),
+          'click sortable' => FALSE,
+        ),
+        'filter' => array(
+          'id' => 'string',
+        ),
+      );
+    }
+
     if (\Drupal::moduleHandler()->moduleExists('content_translation')) {
       $data['users']['translation_link'] = array(
         'title' => t('Translation link'),
diff --git a/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php b/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php
index 79463bc..04cdef9 100644
--- a/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php
+++ b/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php
@@ -205,6 +205,8 @@ public function hiddenUserSettingsProvider() {
     $fields = array(
       'preferred_langcode',
       'preferred_admin_langcode',
+      'signature',
+      'signature_format',
       'timezone',
       'mail',
     );
diff --git a/core/modules/user/user.info.yml b/core/modules/user/user.info.yml
index 8aec70e..45a421a 100644
--- a/core/modules/user/user.info.yml
+++ b/core/modules/user/user.info.yml
@@ -6,5 +6,3 @@ version: VERSION
 core: 8.x
 required: true
 configure: user.admin_index
-dependencies:
-  - system
diff --git a/core/modules/user/user.js b/core/modules/user/user.js
index 45f554c..ded4c0a 100644
--- a/core/modules/user/user.js
+++ b/core/modules/user/user.js
@@ -9,7 +9,7 @@
   Drupal.behaviors.password = {
     attach: function (context, settings) {
       var translate = settings.password;
-      $(context).find('input.password-field').once('password').each(function () {
+      $(context).find('input.password-field').once('password', function () {
         var passwordInput = $(this);
         var innerWrapper = $(this).parent();
         var outerWrapper = $(this).parent().parent();
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 2f00cfe..665b43d 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -62,7 +62,7 @@ function user_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<dt>' . t('Setting permissions') . '</dt>';
       $output .= '<dd>' . t('After creating roles, you can set permissions for each role on the <a href="!permissions_user">Permissions page</a>. Granting a permission allows users who have been assigned a particular role to perform an action on the site, such as viewing content, editing or creating  a particular type of content, administering settings for a particular module, or using a particular function of the site (such as search).', array('!permissions_user' => \Drupal::url('user.admin_permissions'))) . '</dd>';
       $output .= '<dt>' . t('Managing account settings') . '</dt>';
-      $output .= '<dd>' . t('The <a href="!accounts">Account settings page</a> allows you to manage settings for the displayed name of the Anonymous user role, personal contact forms, user registration settings, and account cancellation settings. On this page you can also manage settings for account personalization, and adapt the text for the email messages that users receive when they register or request a password recovery. You may also set which role is automatically assigned new permissions whenever a module is enabled (the Administrator role).', array('!accounts'  => \Drupal::url('entity.user.admin_form'))) . '</dd>';
+      $output .= '<dd>' . t('The <a href="!accounts">Account settings page</a> allows you to manage settings for the displayed name of the Anonymous user role, personal contact forms, user registration settings, and account cancellation settings. On this page you can also manage settings for account personalization (including signatures), and adapt the text for the email messages that users receive when they register or request a password recovery. You may also set which role is automatically assigned new permissions whenever a module is enabled (the Administrator role).', array('!accounts'  => \Drupal::url('entity.user.admin_form'))) . '</dd>';
       $output .= '<dt>' . t('Managing user account fields') . '</dt>';
       $output .= '<dd>' . t('Because User accounts are an entity type, you can extend them by adding fields through the Manage fields tab on the <a href="!accounts">Account settings page</a>. By adding fields for e.g., a picture, a biography, or address, you can a create a custom profile for the users of the website. For background information on entities and fields, see the <a href="!field_help">Field module help page</a>.', array('!field_help'=>\Drupal::url('help.page', array('name' => 'field')), '!accounts' => \Drupal::url('entity.user.admin_form'))) . '</dd>';
       $output .= '</dl>';
@@ -168,6 +168,13 @@ function user_entity_extra_field_info() {
     'description' => t('User module account form elements.'),
     'weight' => -10,
   );
+  if (\Drupal::config('user.settings')->get('signatures')) {
+    $fields['user']['user']['form']['signature_settings'] = array(
+      'label' => t('Signature settings'),
+      'description' => t('User module form element.'),
+      'weight' => 1,
+    );
+  }
   $fields['user']['user']['form']['language'] = array(
     'label' => t('Language settings'),
     'description' => t('User module form element.'),
@@ -1330,6 +1337,10 @@ function user_form_process_password_confirm($element) {
 function user_modules_uninstalled($modules) {
   // Remove any potentially orphan module data stored for users.
   \Drupal::service('user.data')->delete($modules);
+  // User signatures require Filter module.
+  if (in_array('filter', $modules)) {
+    \Drupal::configFactory()->getEditable('user.settings')->set('signatures', FALSE)->save();
+  }
 }
 
 /**
diff --git a/core/modules/user/user.permissions.js b/core/modules/user/user.permissions.js
index d47ee9a..415fc53 100644
--- a/core/modules/user/user.permissions.js
+++ b/core/modules/user/user.permissions.js
@@ -8,7 +8,7 @@
   Drupal.behaviors.permissions = {
     attach: function (context) {
       var self = this;
-      $('table#permissions').once('permissions').each(function () {
+      $('table#permissions').once('permissions', function () {
         // On a site with many roles and permissions, this behavior initially has
         // to perform thousands of DOM manipulations to inject checkboxes and hide
         // them. By detaching the table from the DOM, all operations can be
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index cb1b741..4bee869 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -20,6 +20,16 @@ services:
     arguments: ['@session_configuration']
     tags:
       - { name: authentication_provider, priority: 0 }
+  cache_context.user:
+    class: Drupal\user\Cache\UserCacheContext
+    arguments: ['@current_user']
+    tags:
+      - { name: cache.context}
+  cache_context.user.roles:
+    class: Drupal\user\Cache\UserRolesCacheContext
+    arguments: ['@current_user']
+    tags:
+      - { name: cache.context}
   user.data:
     class: Drupal\user\UserData
     arguments: ['@database']
diff --git a/core/modules/views/js/ajax_view.js b/core/modules/views/js/ajax_view.js
index 3e0b680..3139112 100644
--- a/core/modules/views/js/ajax_view.js
+++ b/core/modules/views/js/ajax_view.js
@@ -63,14 +63,14 @@
 
     // Add the ajax to exposed forms.
     this.$exposed_form = $('form#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-'));
-    this.$exposed_form.once('exposed-form').each(jQuery.proxy(this.attachExposedFormAjax, this));
+    this.$exposed_form.once('exposed-form', jQuery.proxy(this.attachExposedFormAjax, this));
 
     // Add the ajax to pagers.
     this.$view
       // Don't attach to nested views. Doing so would attach multiple behaviors
       // to a given element.
       .filter(jQuery.proxy(this.filterNestedViews, this))
-      .once('ajax-pager').each(jQuery.proxy(this.attachPagerAjax, this));
+      .once('ajax-pager', jQuery.proxy(this.attachPagerAjax, this));
 
     // Add a trigger to update this view specifically. In order to trigger a
     // refresh use the following code.
diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php
index 24d1ec3..51ad1a6 100644
--- a/core/modules/views/src/Entity/View.php
+++ b/core/modules/views/src/Entity/View.php
@@ -8,7 +8,6 @@
 namespace Drupal\views\Entity;
 
 use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\views\Views;
@@ -316,9 +315,10 @@ protected function addCacheMetadata() {
       $executable->setDisplay($display_id);
 
       list($display['cache_metadata']['cacheable'], $display['cache_metadata']['contexts']) = $executable->getDisplay()->calculateCacheMetadata();
-      // Always include at least the 'languages' context as there will most
-      // probably be translatable strings in the view output.
-      $display['cache_metadata']['contexts'] = Cache::mergeContexts($display['cache_metadata']['contexts'], ['languages']);
+      // Always include at least the language context as there will be most
+      // probable translatable strings in the view output.
+      $display['cache_metadata']['contexts'][] = 'language';
+      $display['cache_metadata']['contexts'] = array_unique($display['cache_metadata']['contexts']);
     }
     // Restore the previous active display.
     $executable->setDisplay($current_display);
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index 08d56b0..2f29533 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -116,6 +116,9 @@ protected function getFieldStorageDefinitions() {
   public function getViewsData() {
     $data = [];
 
+    // @todo In theory we should use the data table as base table, as this would
+    //   save one pointless join (and one more for every relationship).
+    // @see https://drupal.org/node/2337509
     $base_table = $this->entityType->getBaseTable();
     $base_field = $this->entityType->getKey('id');
     $data_table = $this->entityType->getDataTable();
diff --git a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
index 4e5469b..069276b 100644
--- a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
+++ b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
@@ -1208,7 +1208,7 @@ public function getCacheContexts() {
     // By definition arguments depends on the URL.
     // @todo Once contexts are properly injected into block views we could pull
     //   the information from there.
-    $contexts[] = 'url';
+    $contexts[] = 'cache.context.url';
 
     // Asks all subplugins (argument defaults, argument validator and styles).
     if (($plugin = $this->getPlugin('argument_default')) && $plugin instanceof CacheablePluginInterface) {
diff --git a/core/modules/views/src/Plugin/views/argument/FieldList.php b/core/modules/views/src/Plugin/views/argument/FieldList.php
index 64d9bb4..39d02cb 100644
--- a/core/modules/views/src/Plugin/views/argument/FieldList.php
+++ b/core/modules/views/src/Plugin/views/argument/FieldList.php
@@ -12,7 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Plugin\views\argument\NumericArgument;
+use Drupal\views\Plugin\views\argument\Numeric;
 
 /**
  * Argument handler for list field to show the human readable name in the
@@ -22,7 +22,7 @@
  *
  * @ViewsArgument("field_list")
  */
-class FieldList extends NumericArgument {
+class FieldList extends Numeric {
 
   use AllowedTagsXssTrait;
 
diff --git a/core/modules/views/src/Plugin/views/argument/ListString.php b/core/modules/views/src/Plugin/views/argument/ListString.php
index 3237e80..f24ca79 100644
--- a/core/modules/views/src/Plugin/views/argument/ListString.php
+++ b/core/modules/views/src/Plugin/views/argument/ListString.php
@@ -12,7 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Plugin\views\argument\StringArgument;
+use Drupal\views\Plugin\views\argument\String;
 
 /**
  * Argument handler for list field to show the human readable name in the
@@ -22,7 +22,7 @@
  *
  * @ViewsArgument("field_list_string")
  */
-class ListString extends StringArgument {
+class ListString extends String {
 
   use AllowedTagsXssTrait;
 
@@ -34,7 +34,7 @@ class ListString extends StringArgument {
   var $allowed_values = NULL;
 
   /**
-   * Overrides \Drupal\views\Plugin\views\argument\StringArgument::init().
+   * Overrides \Drupal\views\Plugin\views\argument\String::init().
    */
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
     parent::init($view, $display, $options);
diff --git a/core/modules/views/src/Plugin/views/argument/NullArgument.php b/core/modules/views/src/Plugin/views/argument/Null.php
similarity index 93%
rename from core/modules/views/src/Plugin/views/argument/NullArgument.php
rename to core/modules/views/src/Plugin/views/argument/Null.php
index d21ce52..051e352 100644
--- a/core/modules/views/src/Plugin/views/argument/NullArgument.php
+++ b/core/modules/views/src/Plugin/views/argument/Null.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\argument\NullArgument.
+ * Definition of Drupal\views\Plugin\views\argument\Null.
  */
 
 namespace Drupal\views\Plugin\views\argument;
@@ -16,7 +16,7 @@
  *
  * @ViewsArgument("null")
  */
-class NullArgument extends ArgumentPluginBase {
+class Null extends ArgumentPluginBase {
 
   protected function defineOptions() {
     $options = parent::defineOptions();
diff --git a/core/modules/views/src/Plugin/views/argument/NumericArgument.php b/core/modules/views/src/Plugin/views/argument/Numeric.php
similarity index 97%
rename from core/modules/views/src/Plugin/views/argument/NumericArgument.php
rename to core/modules/views/src/Plugin/views/argument/Numeric.php
index 799d5cb..e926da3 100644
--- a/core/modules/views/src/Plugin/views/argument/NumericArgument.php
+++ b/core/modules/views/src/Plugin/views/argument/Numeric.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\argument\NumericArgument.
+ * Definition of Drupal\views\Plugin\views\argument\Numeric.
  */
 
 namespace Drupal\views\Plugin\views\argument;
@@ -17,7 +17,7 @@
  *
  * @ViewsArgument("numeric")
  */
-class NumericArgument extends ArgumentPluginBase {
+class Numeric extends ArgumentPluginBase {
 
   /**
    * The operator used for the query: or|and.
diff --git a/core/modules/views/src/Plugin/views/argument/StringArgument.php b/core/modules/views/src/Plugin/views/argument/String.php
similarity index 98%
rename from core/modules/views/src/Plugin/views/argument/StringArgument.php
rename to core/modules/views/src/Plugin/views/argument/String.php
index eeda44b..b542bfb 100644
--- a/core/modules/views/src/Plugin/views/argument/StringArgument.php
+++ b/core/modules/views/src/Plugin/views/argument/String.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\argument\StringArgument.
+ * Definition of Drupal\views\Plugin\views\argument\String.
  */
 
 namespace Drupal\views\Plugin\views\argument;
@@ -20,7 +20,7 @@
  *
  * @ViewsArgument("string")
  */
-class StringArgument extends ArgumentPluginBase {
+class String extends ArgumentPluginBase {
 
   /**
    * Overrides \Drupal\views\Plugin\views\argument\ArgumentPluginBase::init().
diff --git a/core/modules/views/src/Plugin/views/argument_default/QueryParameter.php b/core/modules/views/src/Plugin/views/argument_default/QueryParameter.php
index feccd21..337b722 100644
--- a/core/modules/views/src/Plugin/views/argument_default/QueryParameter.php
+++ b/core/modules/views/src/Plugin/views/argument_default/QueryParameter.php
@@ -95,7 +95,7 @@ public function isCacheable() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return ['url'];
+    return ['cache.context.url'];
   }
 
 }
diff --git a/core/modules/views/src/Plugin/views/argument_default/Raw.php b/core/modules/views/src/Plugin/views/argument_default/Raw.php
index 40bddf3..4239c50 100644
--- a/core/modules/views/src/Plugin/views/argument_default/Raw.php
+++ b/core/modules/views/src/Plugin/views/argument_default/Raw.php
@@ -124,7 +124,7 @@ public function isCacheable() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return ['url'];
+    return ['cache.context.url'];
   }
 
 }
diff --git a/core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php b/core/modules/views/src/Plugin/views/argument_validator/Numeric.php
similarity index 70%
rename from core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php
rename to core/modules/views/src/Plugin/views/argument_validator/Numeric.php
index c7ffc75..ff7e5a3 100644
--- a/core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php
+++ b/core/modules/views/src/Plugin/views/argument_validator/Numeric.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\argument_validator\NumericArgumentValidator.
+ * Definition of Drupal\views\Plugin\views\argument_validator\Numeric.
  */
 
 namespace Drupal\views\Plugin\views\argument_validator;
@@ -17,7 +17,7 @@
  *   title = @Translation("Numeric")
  * )
  */
-class NumericArgumentValidator extends ArgumentValidatorPluginBase {
+class Numeric extends ArgumentValidatorPluginBase {
 
   public function validateArgument($argument) {
     return is_numeric($argument);
diff --git a/core/modules/views/src/Plugin/views/field/NumericField.php b/core/modules/views/src/Plugin/views/field/Numeric.php
similarity index 98%
rename from core/modules/views/src/Plugin/views/field/NumericField.php
rename to core/modules/views/src/Plugin/views/field/Numeric.php
index 5e2db03..da99d15 100644
--- a/core/modules/views/src/Plugin/views/field/NumericField.php
+++ b/core/modules/views/src/Plugin/views/field/Numeric.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\field\NumericField.
+ * Definition of Drupal\views\Plugin\views\field\Numeric.
  */
 
 namespace Drupal\views\Plugin\views\field;
@@ -21,7 +21,7 @@
  *
  * @ViewsField("numeric")
  */
-class NumericField extends FieldPluginBase {
+class Numeric extends FieldPluginBase {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/views/src/Plugin/views/filter/Combine.php b/core/modules/views/src/Plugin/views/filter/Combine.php
index 7ed5aea..cad7eb9 100644
--- a/core/modules/views/src/Plugin/views/filter/Combine.php
+++ b/core/modules/views/src/Plugin/views/filter/Combine.php
@@ -16,7 +16,7 @@
  *
  * @ViewsFilter("combine")
  */
-class Combine extends StringFilter {
+class Combine extends String {
 
   /**
    * @var views_plugin_query_default
diff --git a/core/modules/views/src/Plugin/views/filter/Date.php b/core/modules/views/src/Plugin/views/filter/Date.php
index 0da9300..7e5417f 100644
--- a/core/modules/views/src/Plugin/views/filter/Date.php
+++ b/core/modules/views/src/Plugin/views/filter/Date.php
@@ -16,7 +16,7 @@
  *
  * @ViewsFilter("date")
  */
-class Date extends NumericFilter {
+class Date extends Numeric {
 
   protected function defineOptions() {
     $options = parent::defineOptions();
diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
index 9abf63e..b5f8bf8 100644
--- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
@@ -1477,7 +1477,7 @@ public function getCacheContexts() {
     // input from GET parameters, which are part of the URL. Hence a view with
     // an exposed filter is cacheable per URL.
     if ($this->isExposed()) {
-      $cache_contexts[] = 'url';
+      $cache_contexts[] = 'cache.context.url';
     }
     return $cache_contexts;
   }
diff --git a/core/modules/views/src/Plugin/views/filter/GroupByNumeric.php b/core/modules/views/src/Plugin/views/filter/GroupByNumeric.php
index e7157a9..9bd321b 100644
--- a/core/modules/views/src/Plugin/views/filter/GroupByNumeric.php
+++ b/core/modules/views/src/Plugin/views/filter/GroupByNumeric.php
@@ -14,7 +14,7 @@
  *
  * @ViewsFilter("groupby_numeric")
  */
-class GroupByNumeric extends NumericFilter {
+class GroupByNumeric extends Numeric {
 
   public function query() {
     $this->ensureMyTable();
diff --git a/core/modules/views/src/Plugin/views/filter/NumericFilter.php b/core/modules/views/src/Plugin/views/filter/Numeric.php
similarity index 98%
rename from core/modules/views/src/Plugin/views/filter/NumericFilter.php
rename to core/modules/views/src/Plugin/views/filter/Numeric.php
index e234bf2..38c0fca 100644
--- a/core/modules/views/src/Plugin/views/filter/NumericFilter.php
+++ b/core/modules/views/src/Plugin/views/filter/Numeric.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\filter\NumericFilter.
+ * Definition of Drupal\views\Plugin\views\filter\Numeric.
  */
 
 namespace Drupal\views\Plugin\views\filter;
@@ -18,7 +18,7 @@
  *
  * @ViewsFilter("numeric")
  */
-class NumericFilter extends FilterPluginBase {
+class Numeric extends FilterPluginBase {
 
   protected $alwaysMultiple = TRUE;
 
diff --git a/core/modules/views/src/Plugin/views/filter/StringFilter.php b/core/modules/views/src/Plugin/views/filter/String.php
similarity index 98%
rename from core/modules/views/src/Plugin/views/filter/StringFilter.php
rename to core/modules/views/src/Plugin/views/filter/String.php
index 41e2e9a..54dbb49 100644
--- a/core/modules/views/src/Plugin/views/filter/StringFilter.php
+++ b/core/modules/views/src/Plugin/views/filter/String.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\views\Plugin\views\filter\StringFilter.
+ * Definition of Drupal\views\Plugin\views\filter\String.
  */
 
 namespace Drupal\views\Plugin\views\filter;
@@ -19,7 +19,7 @@
  *
  * @ViewsFilter("string")
  */
-class StringFilter extends FilterPluginBase {
+class String extends FilterPluginBase {
 
   // exposed filter options
   protected $alwaysMultiple = TRUE;
diff --git a/core/modules/views/src/Plugin/views/query/Sql.php b/core/modules/views/src/Plugin/views/query/Sql.php
index 72cc5f9..d39ad46 100644
--- a/core/modules/views/src/Plugin/views/query/Sql.php
+++ b/core/modules/views/src/Plugin/views/query/Sql.php
@@ -1679,7 +1679,7 @@ public function getDateField($field) {
         break;
       case 'sqlite':
         if (!empty($offset)) {
-          $field = "($field + $offset_seconds)";
+          $field = "($field + '$offset_seconds')";
         }
         break;
     }
@@ -1793,18 +1793,7 @@ public function getDateFormat($field, $format) {
           'A' => '',
         );
         $format = strtr($format, $replace);
-        $expression = "strftime('$format', $field, 'unixepoch')";
-        // The expression yields a string, but the comparison value is an
-        // integer in case the comparison value is a float, integer, or numeric.
-        // All of the above SQLite format tokens only produce integers. However,
-        // the given $format may contain 'Y-m-d', which results in a string.
-        // @see \Drupal\Core\Database\Driver\sqlite\Connection::expandArguments()
-        // @see http://www.sqlite.org/lang_datefunc.html
-        // @see http://www.sqlite.org/lang_expr.html#castexpr
-        if (preg_match('/^(?:%\w)+$/', $format)) {
-          $expression = "CAST($expression AS NUMERIC)";
-        }
-        return $expression;
+        return "strftime('$format', $field, 'unixepoch')";
     }
   }
 
diff --git a/core/modules/views/src/Plugin/views/sort/SortPluginBase.php b/core/modules/views/src/Plugin/views/sort/SortPluginBase.php
index 8fe2b43..45b86be 100644
--- a/core/modules/views/src/Plugin/views/sort/SortPluginBase.php
+++ b/core/modules/views/src/Plugin/views/sort/SortPluginBase.php
@@ -241,7 +241,7 @@ public function getCacheContexts() {
     $cache_contexts = [];
     // Exposed sorts use GET parameters, so it depends on the current URL.
     if ($this->isExposed()) {
-      $cache_contexts[] = 'url';
+      $cache_contexts[] = 'cache.context.url';
     }
     return $cache_contexts;
   }
diff --git a/core/modules/views/src/Tests/GlossaryTest.php b/core/modules/views/src/Tests/GlossaryTest.php
index 1df4701..fd97978 100644
--- a/core/modules/views/src/Tests/GlossaryTest.php
+++ b/core/modules/views/src/Tests/GlossaryTest.php
@@ -87,7 +87,7 @@ public function testGlossaryView() {
 
     // Verify cache tags.
     $this->enablePageCaching();
-    $this->assertPageCacheContextsAndTags(Url::fromRoute('view.glossary.page_1'), ['languages', 'url', 'user'], [
+    $this->assertPageCacheContextsAndTags(Url::fromRoute('view.glossary.page_1'), ['cache.context.url', 'node_view_grants', 'language', 'user'], [
       'config:views.view.glossary',
       'node:' . $nodes_by_char['a'][0]->id(), 'node:' . $nodes_by_char['a'][1]->id(), 'node:' . $nodes_by_char['a'][2]->id(),
       'node_list',
diff --git a/core/modules/views/src/Tests/Handler/ArgumentNullTest.php b/core/modules/views/src/Tests/Handler/ArgumentNullTest.php
index 3e078bf..50684bd 100644
--- a/core/modules/views/src/Tests/Handler/ArgumentNullTest.php
+++ b/core/modules/views/src/Tests/Handler/ArgumentNullTest.php
@@ -11,7 +11,7 @@
 use Drupal\views\Views;
 
 /**
- * Tests the core Drupal\views\Plugin\views\argument\NullArgument handler.
+ * Tests the core Drupal\views\Plugin\views\argument\Null handler.
  *
  * @group views
  */
diff --git a/core/modules/views/src/Tests/Handler/ArgumentStringTest.php b/core/modules/views/src/Tests/Handler/ArgumentStringTest.php
index 4b5b9fe..021fcf1 100644
--- a/core/modules/views/src/Tests/Handler/ArgumentStringTest.php
+++ b/core/modules/views/src/Tests/Handler/ArgumentStringTest.php
@@ -10,7 +10,7 @@
 use Drupal\views\Views;
 
 /**
- * Tests the core Drupal\views\Plugin\views\argument\StringArgument handler.
+ * Tests the core Drupal\views\Plugin\views\argument\String handler.
  *
  * @group views
  */
diff --git a/core/modules/views/src/Tests/Handler/FilterStringTest.php b/core/modules/views/src/Tests/Handler/FilterStringTest.php
index 95be9df..f738d34 100644
--- a/core/modules/views/src/Tests/Handler/FilterStringTest.php
+++ b/core/modules/views/src/Tests/Handler/FilterStringTest.php
@@ -11,7 +11,7 @@
 use Drupal\views\Views;
 
 /**
- * Tests the core Drupal\views\Plugin\views\filter\StringFilter handler.
+ * Tests the core Drupal\views\Plugin\views\filter\String handler.
  *
  * @group views
  */
diff --git a/core/modules/views/src/Tests/Handler/HandlerAllTest.php b/core/modules/views/src/Tests/Handler/HandlerAllTest.php
index 018ec2b..89339c9 100644
--- a/core/modules/views/src/Tests/Handler/HandlerAllTest.php
+++ b/core/modules/views/src/Tests/Handler/HandlerAllTest.php
@@ -79,13 +79,9 @@ public function testHandlers() {
               $options = array();
               if ($type == 'filter') {
                 $handler = $this->container->get("plugin.manager.views.$type")->getHandler($item);
-                // Set the value to use for the filter based on the filter type.
                 if ($handler instanceof InOperator) {
                   $options['value'] = array(1);
                 }
-                else {
-                  $options['value'] = 1;
-                }
               }
               $view->addHandler('default', $type, $base_table, $field, $options);
             }
diff --git a/core/modules/views/src/Tests/ModuleTest.php b/core/modules/views/src/Tests/ModuleTest.php
index cbb067e..e801a09 100644
--- a/core/modules/views/src/Tests/ModuleTest.php
+++ b/core/modules/views/src/Tests/ModuleTest.php
@@ -142,8 +142,8 @@ public function customErrorHandler($error_level, $message, $filename, $line, $co
    * Tests the load wrapper/helper functions.
    */
   public function testLoadFunctions() {
-    $this->enableModules(array('field', 'text', 'node'));
-    $this->installConfig(array('node'));
+    $this->enableModules(['text', 'node']);
+    $this->installConfig(['node']);
     $storage = $this->container->get('entity.manager')->getStorage('view');
 
     // Test views_view_is_enabled/disabled.
diff --git a/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php b/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php
index b8488a1..b1f34e6 100644
--- a/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php
+++ b/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\views\Tests\Plugin;
 
-use Drupal\Core\Cache\Cache;
 use Drupal\views\Tests\ViewUnitTestBase;
 
 /**
@@ -83,7 +82,7 @@ public function testViewsBlock() {
    *   - region: 'sidebar_first'.
    *   - theme: The default theme.
    *   - visibility: Empty array.
-   *   - cache: array('max_age' => Cache::PERMANENT).
+   *   - cache: array('max_age' => 0).
    *
    * @return \Drupal\block\Entity\Block
    *   The block entity.
@@ -98,7 +97,7 @@ protected function createBlock($plugin_id, array $settings = array()) {
       'visibility' => array(),
       'weight' => 0,
       'cache' => array(
-        'max_age' => Cache::PERMANENT,
+        'max_age' => 0,
       ),
     );
     $values = [];
diff --git a/core/modules/views/src/Tests/RenderCacheIntegrationTest.php b/core/modules/views/src/Tests/RenderCacheIntegrationTest.php
index 4a9276f..da94ab4 100644
--- a/core/modules/views/src/Tests/RenderCacheIntegrationTest.php
+++ b/core/modules/views/src/Tests/RenderCacheIntegrationTest.php
@@ -221,7 +221,7 @@ public function testViewAddCacheMetadata() {
     $view = View::load('test_display');
     $view->save();
 
-    $this->assertEqual(['languages', 'user', 'user.node_grants:view'], $view->getDisplay('default')['cache_metadata']['contexts']);
+    $this->assertEqual(['node_view_grants', 'user', 'language'], $view->getDisplay('default')['cache_metadata']['contexts']);
   }
 
 }
diff --git a/core/modules/views/src/Tests/ViewExecutableTest.php b/core/modules/views/src/Tests/ViewExecutableTest.php
index 6555c5b..b39abef 100644
--- a/core/modules/views/src/Tests/ViewExecutableTest.php
+++ b/core/modules/views/src/Tests/ViewExecutableTest.php
@@ -84,7 +84,7 @@ protected function setUpFixtures() {
     $this->installEntitySchema('node');
     $this->installEntitySchema('comment');
     $this->installSchema('comment', array('comment_entity_statistics'));
-    $this->installConfig(array('system', 'field', 'node', 'comment'));
+    $this->installConfig(array('field'));
 
     entity_create('node_type', array(
       'type' => 'page',
diff --git a/core/modules/views/src/Tests/ViewResultAssertionTrait.php b/core/modules/views/src/Tests/ViewResultAssertionTrait.php
index b8ad34f..222bf25 100644
--- a/core/modules/views/src/Tests/ViewResultAssertionTrait.php
+++ b/core/modules/views/src/Tests/ViewResultAssertionTrait.php
@@ -98,11 +98,7 @@ protected function assertIdenticalResultsetHelper($view, $expected_result, $colu
         // For entity fields we don't have the raw value. Let's try to fetch it
         // using the entity itself.
         elseif (empty($value->$view_column) && isset($view->field[$expected_column]) && ($field = $view->field[$expected_column]) && $field instanceof Field) {
-          $column = NULL;
-          if (count(explode(':', $view_column)) == 2) {
-            $column = explode(':', $view_column)[1];
-          }
-          $row[$expected_column] = $field->getValue($value, $column);
+          $row[$expected_column] = $field->getValue($value);
         }
       }
       $result[$key] = $row;
diff --git a/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php b/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php
index fbd6682..10cc379 100644
--- a/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php
+++ b/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php
@@ -57,7 +57,7 @@ public function testCreateView() {
 
     // Add a new language and mark it as default.
     ConfigurableLanguage::createFromLangcode('it')->save();
-    $this->config('system.site')->set('default_langcode', 'it')->save();
+    $this->config('system.site')->set('langcode', 'it')->save();
 
     $form_state->setValues([
       'id' => $random_id,
diff --git a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/MappingTest.php b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/MappingTest.php
index ec0ac1a..6d221ae 100644
--- a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/MappingTest.php
+++ b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/style/MappingTest.php
@@ -8,7 +8,7 @@
 namespace Drupal\views_test_data\Plugin\views\style;
 
 use Drupal\views\Plugin\views\style\Mapping;
-use Drupal\views\Plugin\views\field\NumericField;
+use Drupal\views\Plugin\views\field\Numeric;
 
 /**
  * Provides a test plugin for the mapping style.
@@ -59,7 +59,7 @@ protected function defineMapping() {
    */
   protected function filterNumericFields(&$fields) {
     foreach ($this->view->field as $id => $field) {
-      if (!($field instanceof NumericField)) {
+      if (!($field instanceof Numeric)) {
         unset($fields[$id]);
       }
     }
diff --git a/core/modules/views_ui/config/optional/tour.tour.views-ui.yml b/core/modules/views_ui/config/install/tour.tour.views-ui.yml
similarity index 100%
rename from core/modules/views_ui/config/optional/tour.tour.views-ui.yml
rename to core/modules/views_ui/config/install/tour.tour.views-ui.yml
diff --git a/core/modules/views_ui/css/views_ui.admin.theme.css b/core/modules/views_ui/css/views_ui.admin.theme.css
index a9b1eab..a4ebe73 100644
--- a/core/modules/views_ui/css/views_ui.admin.theme.css
+++ b/core/modules/views_ui/css/views_ui.admin.theme.css
@@ -820,7 +820,7 @@ td.group-title {
   border-top:  1px solid #ccc;
 }
 
-.views-filterable-options .filterable-option.odd .form-type-checkbox {
+.views-filterable-options .filterable-option:nth-of-type(even) .form-type-checkbox {
   background-color: #f3f4ee;
 }
 
diff --git a/core/modules/views_ui/js/views-admin.js b/core/modules/views_ui/js/views-admin.js
index 236b746..5310062 100644
--- a/core/modules/views_ui/js/views-admin.js
+++ b/core/modules/views_ui/js/views-admin.js
@@ -233,7 +233,7 @@
   Drupal.behaviors.viewsUiRenderAddViewButton = {
     attach: function (context) {
       // Build the add display menu and pull the display input buttons into it.
-      var $menu = $(context).find('#views-display-menu-tabs').once('views-ui-render-add-view-button');
+      var $menu = $(context).find('#views-display-menu-tabs').once('views-ui-render-add-view-button-processed');
       if (!$menu.length) {
         return;
       }
@@ -358,16 +358,13 @@
      * Keyup handler for the search box that hides or shows the relevant options.
      */
     handleKeyup: function (event) {
-      var found, i, j, option, zebraClass;
+      var found, i, j, option, search, words, wordsLength;
 
       // Determine the user's search query. The search text has been converted to
       // lowercase.
-      var search = this.$searchBox.val().toLowerCase();
-      var words = search.split(' ');
-      var wordsLength = words.length;
-
-      // Start the counter for restriping rows.
-      var zebraCounter = 0;
+      search = this.$searchBox.val().toLowerCase();
+      words = search.split(' ');
+      wordsLength = words.length;
 
       // Search through the search texts in the form for matching text.
       var length = this.options.length;
@@ -383,12 +380,9 @@
           }
         }
         if (found) {
-          zebraClass = (zebraCounter % 2) ? 'odd' : 'even';
           // Show the checkbox row, and restripe it.
-          option.$div.removeClass('even odd');
-          option.$div.addClass(zebraClass);
           option.$div.show();
-          zebraCounter++;
+          option.$div.removeClass('even odd');
         }
         else {
           // The search string wasn't found; hide this item.
@@ -801,7 +795,9 @@
    */
   Drupal.behaviors.viewsRemoveIconClass = {
     attach: function (context) {
-      $(context).find('.dropbutton').once('dropbutton-icon').find('.icon').removeClass('icon');
+      $(context).find('.dropbutton').once('dropbutton-icon', function () {
+        $(this).find('.icon').removeClass('icon');
+      });
     }
   };
 
@@ -878,7 +874,7 @@
    */
   Drupal.behaviors.viewsUiOverrideSelect = {
     attach: function (context) {
-      $(context).find('#edit-override-dropdown').once('views-ui-override-button-text').each(function () {
+      $(context).find('#edit-override-dropdown').once('views-ui-override-button-text', function () {
         // Closures! :(
         var $context = $(context);
         var $submit = $context.find('[id^=edit-submit]');
diff --git a/core/modules/views_ui/src/Tests/FilterNumericWebTest.php b/core/modules/views_ui/src/Tests/FilterNumericWebTest.php
index d687b4a..b9ba565 100644
--- a/core/modules/views_ui/src/Tests/FilterNumericWebTest.php
+++ b/core/modules/views_ui/src/Tests/FilterNumericWebTest.php
@@ -13,7 +13,7 @@
  * Tests the numeric filter UI.
  *
  * @group views_ui
- * @see \Drupal\views\Plugin\views\filter\NumericFilter
+ * @see \Drupal\views\Plugin\views\filter\Numeric
  */
 class FilterNumericWebTest extends UITestBase {
   use SchemaCheckTestTrait;
diff --git a/core/modules/views_ui/src/Tests/HandlerTest.php b/core/modules/views_ui/src/Tests/HandlerTest.php
index eebd4ed..4c9c786 100644
--- a/core/modules/views_ui/src/Tests/HandlerTest.php
+++ b/core/modules/views_ui/src/Tests/HandlerTest.php
@@ -123,8 +123,8 @@ public function testUICRUD() {
 
     $add_handler_url = "admin/structure/views/nojs/add-handler/test_view_empty/default/field";
     $type_info = $handler_types['field'];
-    $this->drupalPostForm($add_handler_url, array('name[users_field_data.name]' => TRUE), t('Add and configure @handler', array('@handler' => $type_info['ltitle'])));
-    $id = 'name';
+    $this->drupalPostForm($add_handler_url, array('name[users_field_data.signature]' => TRUE), t('Add and configure @handler', array('@handler' => $type_info['ltitle'])));
+    $id = 'signature';
     $edit_handler_url = "admin/structure/views/nojs/handler/test_view_empty/default/field/$id";
 
     $this->assertUrl($edit_handler_url, array(), 'The user got redirected to the handler edit form.');
diff --git a/core/modules/views_ui/src/ViewPreviewForm.php b/core/modules/views_ui/src/ViewPreviewForm.php
index 513ab28..1737d29 100644
--- a/core/modules/views_ui/src/ViewPreviewForm.php
+++ b/core/modules/views_ui/src/ViewPreviewForm.php
@@ -25,6 +25,12 @@ public function form(array $form, FormStateInterface $form_state) {
     $form['#suffix'] = '</div>';
     $form['#id'] = 'views-ui-preview-form';
 
+    // Reset the cache of IDs. Drupal rather aggressively prevents ID
+    // duplication but this causes it to remember IDs that are no longer even
+    // being used.
+    $seen_ids_init = &drupal_static('drupal_html_id:init');
+    $seen_ids_init = array();
+
     $form_state->disableCache();
 
     $form['controls']['#attributes'] = array('class' => array('clearfix'));
diff --git a/core/profiles/minimal/config/install/block.block.stark_admin.yml b/core/profiles/minimal/config/install/block.block.stark_admin.yml
index 68ac791..ffbc2fb 100644
--- a/core/profiles/minimal/config/install/block.block.stark_admin.yml
+++ b/core/profiles/minimal/config/install/block.block.stark_admin.yml
@@ -9,6 +9,9 @@ settings:
   label: Administration
   provider: system
   label_display: visible
+  cache:
+    max_age: -1
+    contexts: {  }
   level: 1
   depth: 0
 dependencies:
diff --git a/core/profiles/minimal/config/install/block.block.stark_tools.yml b/core/profiles/minimal/config/install/block.block.stark_tools.yml
index e833fe0..aa82311 100644
--- a/core/profiles/minimal/config/install/block.block.stark_tools.yml
+++ b/core/profiles/minimal/config/install/block.block.stark_tools.yml
@@ -9,6 +9,9 @@ settings:
   label: Tools
   provider: system
   label_display: visible
+  cache:
+    max_age: -1
+    contexts: {  }
   level: 1
   depth: 0
 dependencies:
diff --git a/core/profiles/minimal/minimal.info.yml b/core/profiles/minimal/minimal.info.yml
index d1f83de..628dcd3 100644
--- a/core/profiles/minimal/minimal.info.yml
+++ b/core/profiles/minimal/minimal.info.yml
@@ -7,5 +7,3 @@ dependencies:
   - node
   - block
   - dblog
-themes:
-  - stark
diff --git a/core/profiles/standard/config/install/block.block.bartik_account_menu.yml b/core/profiles/standard/config/install/block.block.bartik_account_menu.yml
index ef0f44c..db8f8ec 100644
--- a/core/profiles/standard/config/install/block.block.bartik_account_menu.yml
+++ b/core/profiles/standard/config/install/block.block.bartik_account_menu.yml
@@ -10,6 +10,9 @@ settings:
   label: 'User account menu'
   provider: system
   label_display: '0'
+  cache:
+    max_age: -1
+    contexts: {  }
   level: 1
   depth: 1
 dependencies:
diff --git a/core/profiles/standard/config/install/block.block.bartik_footer.yml b/core/profiles/standard/config/install/block.block.bartik_footer.yml
index f3a4dcf..e98fcb8 100644
--- a/core/profiles/standard/config/install/block.block.bartik_footer.yml
+++ b/core/profiles/standard/config/install/block.block.bartik_footer.yml
@@ -9,7 +9,10 @@ settings:
   id: 'system_menu_block:footer'
   label: 'Footer menu'
   provider: system
-  label_display: '0'
+  label_display: visible
+  cache:
+    max_age: -1
+    contexts: {  }
   level: 1
   depth: 0
 dependencies:
diff --git a/core/profiles/standard/config/install/block.block.bartik_main_menu.yml b/core/profiles/standard/config/install/block.block.bartik_main_menu.yml
index 32a3d1d..3da0571 100644
--- a/core/profiles/standard/config/install/block.block.bartik_main_menu.yml
+++ b/core/profiles/standard/config/install/block.block.bartik_main_menu.yml
@@ -10,6 +10,9 @@ settings:
   label: 'Main navigation'
   provider: system
   label_display: '0'
+  cache:
+    max_age: -1
+    contexts: {  }
   level: 1
   depth: 1
 dependencies:
diff --git a/core/profiles/standard/config/install/block.block.bartik_tools.yml b/core/profiles/standard/config/install/block.block.bartik_tools.yml
index af3672d..aa24e61 100644
--- a/core/profiles/standard/config/install/block.block.bartik_tools.yml
+++ b/core/profiles/standard/config/install/block.block.bartik_tools.yml
@@ -10,6 +10,9 @@ settings:
   label: Tools
   provider: system
   label_display: visible
+  cache:
+    max_age: -1
+    contexts: {  }
   level: 1
   depth: 0
 dependencies:
diff --git a/core/profiles/standard/config/install/field.field.node.article.field_image.yml b/core/profiles/standard/config/install/field.field.node.article.field_image.yml
index 0a7c7f6..f4b1734 100644
--- a/core/profiles/standard/config/install/field.field.node.article.field_image.yml
+++ b/core/profiles/standard/config/install/field.field.node.article.field_image.yml
@@ -15,7 +15,7 @@ settings:
   min_resolution: ''
   alt_field: true
   title_field: false
-  alt_field_required: true
+  alt_field_required: false
   title_field_required: false
   default_image:
     uuid: null
diff --git a/core/profiles/testing/config/optional/locale.settings.yml b/core/profiles/testing/config/install/locale.settings.yml
similarity index 100%
rename from core/profiles/testing/config/optional/locale.settings.yml
rename to core/profiles/testing/config/install/locale.settings.yml
diff --git a/core/profiles/testing_config_overrides/config/install/system.cron.yml b/core/profiles/testing/config/install/system.cron.yml
similarity index 100%
rename from core/profiles/testing_config_overrides/config/install/system.cron.yml
rename to core/profiles/testing/config/install/system.cron.yml
diff --git a/core/profiles/testing_config_overrides/config/install/system.action.user_block_user_action.yml b/core/profiles/testing_config_overrides/config/install/system.action.user_block_user_action.yml
deleted file mode 100644
index f902ff1..0000000
--- a/core/profiles/testing_config_overrides/config/install/system.action.user_block_user_action.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-id: user_block_user_action
-label: 'Overridden block the selected user(s)'
-status: true
-langcode: en
-type: user
-plugin: user_block_user_action
-dependencies:
-  module:
-    - user
diff --git a/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml b/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml
deleted file mode 100644
index 6f90240..0000000
--- a/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-id: language
-module: language
-label: Language
-langcode: en
-routes:
-  - route_name: entity.configurable_language.collection
-tips:
-  language-overview:
-    id: language-overview
-    plugin: text
-    label: Languages
-    body: '<p>The "Languages" page allows you to add, edit, delete, and reorder languages for the site.</p>'
-    weight: 1
diff --git a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.dotted.default.yml b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.dotted.default.yml
deleted file mode 100644
index db97f0f..0000000
--- a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.dotted.default.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-id: dotted.default
-label: 'Default install profile override'
-weight: 0
-protected_property: Default
-# Intentionally commented out to verify default status behavior.
-# status: 1
diff --git a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml
deleted file mode 100644
index 4a54a33..0000000
--- a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-id: override
-label: Override
-weight: 0
-protected_property: Default
-status: 1
-dependencies:
-  module:
-    - tour
diff --git a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml
deleted file mode 100644
index f20365f..0000000
--- a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-id: override_unmet
-label: Override
-weight: 0
-protected_property: Default
-status: 1
-dependencies:
-  module:
-    - dblog
diff --git a/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml b/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml
deleted file mode 100644
index f0ef399..0000000
--- a/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-id: testing_config_overrides
-module: testing_config_overrides
-label: Config override test
-langcode: en
-routes:
-  - route_name: entity.configurable_language.collection
-tips:
-  language-overview:
-    id: language-overview
-    plugin: text
-    label: Languages
-    body: '<p>The "Languages" page allows you to add, edit, delete, and reorder languages for the site.</p>'
-    weight: 1
diff --git a/core/profiles/testing_config_overrides/testing_config_overrides.info.yml b/core/profiles/testing_config_overrides/testing_config_overrides.info.yml
deleted file mode 100644
index f88724c..0000000
--- a/core/profiles/testing_config_overrides/testing_config_overrides.info.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-name: Testing config overrides
-type: profile
-description: 'Minimal profile for running tests with config overrides in a profile.'
-version: VERSION
-core: 8.x
-hidden: true
-dependencies:
-  - action
-  - language
-  - tour
diff --git a/core/scripts/migrate-dump-d6.sh b/core/scripts/migrate-dump-d6.sh
index 6d9b366..11e05c5 100755
--- a/core/scripts/migrate-dump-d6.sh
+++ b/core/scripts/migrate-dump-d6.sh
@@ -29,7 +29,7 @@
   return;
 }
 
-$autoloader  = require __DIR__ . '/../../autoload.php';
+$autoloader  = require __DIR__ . '/../vendor/autoload.php';
 require_once __DIR__ . '/../includes/bootstrap.inc';
 
 $request = Request::createFromGlobals();
diff --git a/core/scripts/password-hash.sh b/core/scripts/password-hash.sh
index cf5e9e3..b1cfa2f 100755
--- a/core/scripts/password-hash.sh
+++ b/core/scripts/password-hash.sh
@@ -55,7 +55,7 @@
 // Password list to be processed.
 $passwords = $_SERVER['argv'];
 
-$autoloader = require __DIR__ . '/../../autoload.php';
+$autoloader = require __DIR__ . '/../vendor/autoload.php';
 
 $request = Request::createFromGlobals();
 $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod', FALSE);
diff --git a/core/scripts/rebuild_token_calculator.sh b/core/scripts/rebuild_token_calculator.sh
index 38a64ab..87c3069 100755
--- a/core/scripts/rebuild_token_calculator.sh
+++ b/core/scripts/rebuild_token_calculator.sh
@@ -15,7 +15,7 @@
   return;
 }
 
-require __DIR__ . '/../../autoload.php';
+require __DIR__ . '/../vendor/autoload.php';
 require_once __DIR__ . '/../includes/bootstrap.inc';
 
 $request = Request::createFromGlobals();
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
old mode 100755
new mode 100644
diff --git a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
index 18b07f7..a60ea90 100644
--- a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
@@ -210,45 +210,4 @@ public function providerTestHtmlGetId() {
     );
   }
 
-  /**
-   * Tests Html::decodeEntities().
-   *
-   * @dataProvider providerDecodeEntities
-   * @covers ::decodeEntities
-   */
-  public function testDecodeEntities($text, $expected) {
-    $this->assertEquals($expected, Html::decodeEntities($text));
-  }
-
-  /**
-   * Data provider for testDecodeEntities().
-   *
-   * @see testCheckPlain()
-   */
-  public function providerDecodeEntities() {
-    return array(
-      array('Drupal', 'Drupal'),
-      array('<script>', '<script>'),
-      array('&lt;script&gt;', '<script>'),
-      array('&#60;script&#62;', '<script>'),
-      array('&amp;lt;script&amp;gt;', '&lt;script&gt;'),
-      array('"', '"'),
-      array('&#34;', '"'),
-      array('&amp;#34;', '&#34;'),
-      array('&quot;', '"'),
-      array('&amp;quot;', '&quot;'),
-      array("'", "'"),
-      array('&#39;', "'"),
-      array('&amp;#39;', '&#39;'),
-      array('©', '©'),
-      array('&copy;', '©'),
-      array('&#169;', '©'),
-      array('→', '→'),
-      array('&#8594;', '→'),
-      array('➼', '➼'),
-      array('&#10172;', '➼'),
-      array('&euro;', '€'),
-    );
-  }
-
 }
diff --git a/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php b/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
index 1e7d355..eadc122 100644
--- a/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
@@ -45,7 +45,7 @@ public function testSet($text, $message) {
    */
   public function providerSet() {
     // Checks that invalid multi-byte sequences are rejected.
-    $tests[] = array("Foo\xC0barbaz", '', 'SafeMarkup::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
+    $tests[] = array("Foo\xC0barbaz", '', 'String::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
     $tests[] = array("Fooÿñ", 'SafeMarkup::set() accepts valid sequence "Fooÿñ"');
     $tests[] = array(new TextWrapper("Fooÿñ"), 'SafeMarkup::set() accepts valid sequence "Fooÿñ" in an object implementing __toString()');
     $tests[] = array("<div>", 'SafeMarkup::set() accepts HTML');
@@ -101,91 +101,4 @@ public function testInvalidSetMultiple() {
     SafeMarkup::setMultiple($texts);
   }
 
-  /**
-   * Tests SafeMarkup::checkPlain().
-   *
-   * @dataProvider providerCheckPlain
-   * @covers ::checkPlain
-   *
-   * @param string $text
-   *   The text to provide to SafeMarkup::checkPlain().
-   * @param string $expected
-   *   The expected output from the function.
-   * @param string $message
-   *   The message to provide as output for the test.
-   * @param bool $ignorewarnings
-   *   Whether or not to ignore PHP 5.3+ invalid multibyte sequence warnings.
-   */
-  function testCheckPlain($text, $expected, $message, $ignorewarnings = FALSE) {
-    $result = $ignorewarnings ? @SafeMarkup::checkPlain($text) : SafeMarkup::checkPlain($text);
-    $this->assertEquals($expected, $result, $message);
-  }
-
-  /**
-   * Data provider for testCheckPlain().
-   *
-   * @see testCheckPlain()
-   */
-  function providerCheckPlain() {
-    // Checks that invalid multi-byte sequences are rejected.
-    $tests[] = array("Foo\xC0barbaz", '', 'SafeMarkup::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
-    $tests[] = array("\xc2\"", '', 'SafeMarkup::checkPlain() rejects invalid sequence "\xc2\""', TRUE);
-    $tests[] = array("Fooÿñ", "Fooÿñ", 'SafeMarkup::checkPlain() accepts valid sequence "Fooÿñ"');
-
-    // Checks that special characters are escaped.
-    $tests[] = array("<script>", '&lt;script&gt;', 'SafeMarkup::checkPlain() escapes &lt;script&gt;');
-    $tests[] = array('<>&"\'', '&lt;&gt;&amp;&quot;&#039;', 'SafeMarkup::checkPlain() escapes reserved HTML characters.');
-
-    return $tests;
-  }
-
-  /**
-   * Tests string formatting with SafeMarkup::format().
-   *
-   * @dataProvider providerFormat
-   * @covers ::format
-   *
-   * @param string $string
-   *   The string to run through SafeMarkup::format().
-   * @param string $args
-   *   The arguments to pass into SafeMarkup::format().
-   * @param string $expected
-   *   The expected result from calling the function.
-   * @param string $message
-   *   The message to display as output to the test.
-   * @param bool $expected_is_safe
-   *   Whether the result is expected to be safe for HTML display.
-   */
-  function testFormat($string, $args, $expected, $message, $expected_is_safe) {
-    $result = SafeMarkup::format($string, $args);
-    $this->assertEquals($expected, $result, $message);
-    $this->assertEquals($expected_is_safe, SafeMarkup::isSafe($result), 'SafeMarkup::format correctly sets the result as safe or not safe.');
-  }
-
-  /**
-   * Data provider for testFormat().
-   *
-   * @see testFormat()
-   */
-  function providerFormat() {
-    $tests[] = array('Simple text', array(), 'Simple text', 'SafeMarkup::format leaves simple text alone.', TRUE);
-    $tests[] = array('Escaped text: @value', array('@value' => '<script>'), 'Escaped text: &lt;script&gt;', 'SafeMarkup::format replaces and escapes string.', TRUE);
-    $tests[] = array('Escaped text: @value', array('@value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Escaped text: <span>Safe HTML</span>', 'SafeMarkup::format does not escape an already safe string.', TRUE);
-    $tests[] = array('Placeholder text: %value', array('%value' => '<script>'), 'Placeholder text: <em class="placeholder">&lt;script&gt;</em>', 'SafeMarkup::format replaces, escapes and themes string.', TRUE);
-    $tests[] = array('Placeholder text: %value', array('%value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Placeholder text: <em class="placeholder"><span>Safe HTML</span></em>', 'SafeMarkup::format does not escape an already safe string themed as a placeholder.', TRUE);
-    $tests[] = array('Verbatim text: !value', array('!value' => '<script>'), 'Verbatim text: <script>', 'SafeMarkup::format replaces verbatim string as-is.', FALSE);
-    $tests[] = array('Verbatim text: !value', array('!value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Verbatim text: <span>Safe HTML</span>', 'SafeMarkup::format replaces verbatim string as-is.', TRUE);
-
-    return $tests;
-  }
-
-  /**
-   * Tests SafeMarkup::placeholder().
-   *
-   * @covers ::placeholder
-   */
-  function testPlaceholder() {
-    $this->assertEquals('<em class="placeholder">Some text</em>', SafeMarkup::placeholder('Some text'));
-  }
-
 }
diff --git a/core/tests/Drupal/Tests/Component/Utility/StringTest.php b/core/tests/Drupal/Tests/Component/Utility/StringTest.php
new file mode 100644
index 0000000..307385a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Utility/StringTest.php
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\Utility\StringTest.
+ */
+
+namespace Drupal\Tests\Component\Utility;
+
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Tests\UnitTestCase;
+use Drupal\Component\Utility\String;
+
+/**
+ * Tests string filtering.
+ *
+ * @group Utility
+ *
+ * @coversDefaultClass \Drupal\Component\Utility\String
+ */
+class StringTest extends UnitTestCase {
+
+  /**
+   * Tests String::checkPlain().
+   *
+   * @dataProvider providerCheckPlain
+   * @covers ::checkPlain
+   *
+   * @param string $text
+   *   The text to provide to String::checkPlain().
+   * @param string $expected
+   *   The expected output from the function.
+   * @param string $message
+   *   The message to provide as output for the test.
+   * @param bool $ignorewarnings
+   *   Whether or not to ignore PHP 5.3+ invalid multibyte sequence warnings.
+   */
+  function testCheckPlain($text, $expected, $message, $ignorewarnings = FALSE) {
+    $result = $ignorewarnings ? @String::checkPlain($text) : String::checkPlain($text);
+    $this->assertEquals($expected, $result, $message);
+  }
+
+  /**
+   * Data provider for testCheckPlain().
+   *
+   * @see testCheckPlain()
+   */
+  function providerCheckPlain() {
+    // Checks that invalid multi-byte sequences are rejected.
+    $tests[] = array("Foo\xC0barbaz", '', 'String::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
+    $tests[] = array("\xc2\"", '', 'String::checkPlain() rejects invalid sequence "\xc2\""', TRUE);
+    $tests[] = array("Fooÿñ", "Fooÿñ", 'String::checkPlain() accepts valid sequence "Fooÿñ"');
+
+    // Checks that special characters are escaped.
+    $tests[] = array("<script>", '&lt;script&gt;', 'String::checkPlain() escapes &lt;script&gt;');
+    $tests[] = array('<>&"\'', '&lt;&gt;&amp;&quot;&#039;', 'String::checkPlain() escapes reserved HTML characters.');
+
+    return $tests;
+  }
+
+  /**
+   * Tests string formatting with String::format().
+   *
+   * @dataProvider providerFormat
+   * @covers ::format
+   *
+   * @param string $string
+   *   The string to run through String::format().
+   * @param string $args
+   *   The arguments to pass into String::format().
+   * @param string $expected
+   *   The expected result from calling the function.
+   * @param string $message
+   *   The message to display as output to the test.
+   * @param bool $expected_is_safe
+   *   Whether the result is expected to be safe for HTML display.
+   */
+  function testFormat($string, $args, $expected, $message, $expected_is_safe) {
+    $result = String::format($string, $args);
+    $this->assertEquals($expected, $result, $message);
+    $this->assertEquals($expected_is_safe, SafeMarkup::isSafe($result), 'String::format correctly sets the result as safe or not safe.');
+  }
+
+  /**
+   * Data provider for testFormat().
+   *
+   * @see testFormat()
+   */
+  function providerFormat() {
+    $tests[] = array('Simple text', array(), 'Simple text', 'String::format leaves simple text alone.', TRUE);
+    $tests[] = array('Escaped text: @value', array('@value' => '<script>'), 'Escaped text: &lt;script&gt;', 'String::format replaces and escapes string.', TRUE);
+    $tests[] = array('Escaped text: @value', array('@value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Escaped text: <span>Safe HTML</span>', 'String::format does not escape an already safe string.', TRUE);
+    $tests[] = array('Placeholder text: %value', array('%value' => '<script>'), 'Placeholder text: <em class="placeholder">&lt;script&gt;</em>', 'String::format replaces, escapes and themes string.', TRUE);
+    $tests[] = array('Placeholder text: %value', array('%value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Placeholder text: <em class="placeholder"><span>Safe HTML</span></em>', 'String::format does not escape an already safe string themed as a placeholder.', TRUE);
+    $tests[] = array('Verbatim text: !value', array('!value' => '<script>'), 'Verbatim text: <script>', 'String::format replaces verbatim string as-is.', FALSE);
+    $tests[] = array('Verbatim text: !value', array('!value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Verbatim text: <span>Safe HTML</span>', 'String::format replaces verbatim string as-is.', TRUE);
+
+    return $tests;
+  }
+
+  /**
+   * Tests String::placeholder().
+   *
+   * @covers ::placeholder
+   */
+  function testPlaceholder() {
+    $this->assertEquals('<em class="placeholder">Some text</em>', String::placeholder('Some text'));
+  }
+
+  /**
+   * Tests String::decodeEntities().
+   *
+   * @dataProvider providerDecodeEntities
+   * @covers ::decodeEntities
+   */
+  public function testDecodeEntities($text, $expected) {
+    $this->assertEquals($expected, String::decodeEntities($text));
+  }
+
+  /**
+   * Data provider for testDecodeEntities().
+   *
+   * @see testCheckPlain()
+   */
+  public function providerDecodeEntities() {
+    return array(
+      array('Drupal', 'Drupal'),
+      array('<script>', '<script>'),
+      array('&lt;script&gt;', '<script>'),
+      array('&#60;script&#62;', '<script>'),
+      array('&amp;lt;script&amp;gt;', '&lt;script&gt;'),
+      array('"', '"'),
+      array('&#34;', '"'),
+      array('&amp;#34;', '&#34;'),
+      array('&quot;', '"'),
+      array('&amp;quot;', '&quot;'),
+      array("'", "'"),
+      array('&#39;', "'"),
+      array('&amp;#39;', '&#39;'),
+      array('©', '©'),
+      array('&copy;', '©'),
+      array('&#169;', '©'),
+      array('→', '→'),
+      array('&#8594;', '→'),
+      array('➼', '➼'),
+      array('&#10172;', '➼'),
+      array('&euro;', '€'),
+    );
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheContextsTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheContextsTest.php
index a81f52d..1563a6d 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheContextsTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheContextsTest.php
@@ -20,63 +20,6 @@
 class CacheContextsTest extends UnitTestCase {
 
   /**
-   * @covers ::optimizeTokens
-   *
-   * @dataProvider providerTestOptimizeTokens
-   */
-  public function testOptimizeTokens(array $context_tokens, array $optimized_context_tokens) {
-    $container = $this->getMockBuilder('Drupal\Core\DependencyInjection\Container')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $container->expects($this->any())
-      ->method('get')
-      ->will($this->returnValueMap([
-        ['a', Container::EXCEPTION_ON_INVALID_REFERENCE, new FooCacheContext()],
-        ['a.b', Container::EXCEPTION_ON_INVALID_REFERENCE, new FooCacheContext()],
-        ['a.b.c', Container::EXCEPTION_ON_INVALID_REFERENCE, new BazCacheContext()],
-        ['x', Container::EXCEPTION_ON_INVALID_REFERENCE, new BazCacheContext()],
-      ]));
-    $cache_contexts = new CacheContexts($container, $this->getContextsFixture());
-
-    $this->assertSame($optimized_context_tokens, $cache_contexts->optimizeTokens($context_tokens));
-  }
-
-  /**
-   * Provides a list of context token sets.
-   */
-  public function providerTestOptimizeTokens() {
-    return [
-      [['a', 'x'], ['a', 'x']],
-      [['a.b', 'x'], ['a.b', 'x']],
-
-      // Direct ancestor, single-level hierarchy.
-      [['a', 'a.b'], ['a']],
-      [['a.b', 'a'], ['a']],
-
-      // Direct ancestor, multi-level hierarchy.
-      [['a.b', 'a.b.c'], ['a.b']],
-      [['a.b.c', 'a.b'], ['a.b']],
-
-      // Indirect ancestor.
-      [['a', 'a.b.c'], ['a']],
-      [['a.b.c', 'a'], ['a']],
-
-      // Direct & indirect ancestors.
-      [['a', 'a.b', 'a.b.c'], ['a']],
-      [['a', 'a.b.c', 'a.b'], ['a']],
-      [['a.b', 'a', 'a.b.c'], ['a']],
-      [['a.b', 'a.b.c', 'a'], ['a']],
-      [['a.b.c', 'a.b', 'a'], ['a']],
-      [['a.b.c', 'a', 'a.b'], ['a']],
-
-      // Using parameters.
-      [['a', 'a.b.c:foo'], ['a']],
-      [['a.b.c:foo', 'a'], ['a']],
-      [['a.b.c:foo', 'a.b.c'], ['a.b.c']],
-    ];
-  }
-
-  /**
    * @covers ::convertTokensToKeys
    */
   public function testConvertTokensToKeys() {
@@ -203,7 +146,7 @@ public static function getLabel() {
   /**
    * {@inheritdoc}
    */
-  public function getContext($parameter = NULL) {
+  public function getContext($parameter) {
     if (!is_string($parameter) || strlen($parameter) ===  0) {
       throw new \Exception();
     }
diff --git a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
index 1a4c2db..1b1e6a0 100644
--- a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Config\CachedStorage;
+use Drupal\Core\Cache\MemoryBackend;
 use Drupal\Core\Cache\NullBackend;
 
 /**
@@ -38,4 +39,133 @@ public function testListAllStaticCache() {
     $this->assertEquals($response, $cachedStorage->listAll($prefix));
   }
 
+  /**
+   * Test CachedStorage::listAll() persistent cache.
+   */
+  public function testListAllPrimedPersistentCache() {
+    $prefix = __FUNCTION__;
+    $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
+    $storage->expects($this->never())->method('listAll');
+
+    $response = array("$prefix." . $this->randomMachineName(), "$prefix." . $this->randomMachineName());
+    $cache = new MemoryBackend(__FUNCTION__);
+    $cache->set('find:' . $prefix, $response);
+
+    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->assertEquals($response, $cachedStorage->listAll($prefix));
+  }
+
+  /**
+   * Test that we don't fall through to file storage with a primed cache.
+   */
+  public function testGetMultipleOnPrimedCache() {
+    $configNames = array(
+      'foo.bar',
+      'baz.back',
+    );
+    $configCacheValues = array(
+      'foo.bar' => array(
+        'foo' => 'bar',
+      ),
+      'baz.back' => array(
+        'foo' => 'bar',
+      ),
+    );
+    $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
+    $storage->expects($this->never())->method('readMultiple');
+    $cache = new MemoryBackend(__FUNCTION__);
+    foreach ($configCacheValues as $key => $value) {
+      $cache->set($key, $value);
+    }
+
+    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->assertEquals($configCacheValues, $cachedStorage->readMultiple($configNames));
+  }
+
+  /**
+   * Test fall through to file storage in CachedStorage::readMultiple().
+   */
+  public function testGetMultipleOnPartiallyPrimedCache() {
+    $configNames = array(
+      'foo.bar',
+      'baz.back',
+      'config.exists_not_cached',
+      'config.does_not_exist_cached',
+      'config.does_not_exist',
+    );
+    $configCacheValues = array(
+      'foo.bar' => array(
+        'foo' => 'bar',
+      ),
+      'baz.back' => array(
+        'foo' => 'bar',
+      ),
+    );
+    $cache = new MemoryBackend(__FUNCTION__);
+    foreach ($configCacheValues as $key => $value) {
+      $cache->set($key, $value);
+    }
+    $cache->set('config.does_not_exist_cached', FALSE);
+
+    $config_exists_not_cached_data = array('foo' => 'bar');
+    $response = array(
+      $configNames[2] => $config_exists_not_cached_data,
+      $configNames[4] => FALSE,
+    );
+    $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
+    $storage->expects($this->once())
+      ->method('readMultiple')
+      ->with(array($configNames[2], $configNames[4]))
+      ->will($this->returnValue($response));
+
+    $cachedStorage = new CachedStorage($storage, $cache);
+    $expected_data = $configCacheValues + array($configNames[2] => $config_exists_not_cached_data);
+    $this->assertEquals($expected_data, $cachedStorage->readMultiple($configNames));
+
+    // Ensure that the a missing file is cached.
+    $entry = $cache->get('config.does_not_exist');
+    $this->assertFalse($entry->data);
+
+    // Ensure that the a file containing data is cached.
+    $entry = $cache->get('config.exists_not_cached');
+    $this->assertEquals($config_exists_not_cached_data, $entry->data);
+  }
+
+  /**
+   * Test fall through to file storage on a cache miss in CachedStorage::read().
+   */
+  public function testReadNonExistentFileCacheMiss() {
+    $name = 'config.does_not_exist';
+    $cache = new MemoryBackend(__FUNCTION__);
+    $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
+    $storage->expects($this->once())
+            ->method('read')
+            ->with($name)
+            ->will($this->returnValue(FALSE));
+
+    $cachedStorage = new CachedStorage($storage, $cache);
+
+    $this->assertFalse($cachedStorage->read($name));
+
+    // Ensure that the a missing file is cached.
+    $entry = $cache->get('config.does_not_exist');
+    $this->assertFalse($entry->data);
+  }
+
+  /**
+   * Test file storage on a cache hit in CachedStorage::read().
+   */
+  public function testReadNonExistentFileCached() {
+    $name = 'config.does_not_exist';
+    $cache = new MemoryBackend(__FUNCTION__);
+    $cache->set($name, FALSE);
+
+    $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
+    $storage->expects($this->never())
+            ->method('read');
+
+    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->assertFalse($cachedStorage->read($name));
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/File/FileSystemTest.php b/core/tests/Drupal/Tests/Core/File/FileSystemTest.php
index ba39d17..393c035 100644
--- a/core/tests/Drupal/Tests/Core/File/FileSystemTest.php
+++ b/core/tests/Drupal/Tests/Core/File/FileSystemTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\Tests\Core\File;
 
 use Drupal\Core\File\FileSystem;
-use Drupal\Core\Site\Settings;
 use Drupal\Tests\UnitTestCase;
 use org\bovigo\vfs\vfsStream;
 
@@ -37,10 +36,9 @@ class FileSystemTest extends UnitTestCase {
   protected function setUp() {
     parent::setUp();
 
-    $settings = new Settings([]);
     $stream_wrapper_manager = $this->getMock('Drupal\Core\StreamWrapper\StreamWrapperManagerInterface');
     $this->logger = $this->getMock('Psr\Log\LoggerInterface');
-    $this->fileSystem = new FileSystem($stream_wrapper_manager, $settings, $this->logger);
+    $this->fileSystem = new FileSystem($stream_wrapper_manager, [], $this->logger);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
index ce7bfee..e677fdc 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
@@ -354,6 +354,24 @@ public function testGetCache() {
   }
 
   /**
+   * Tests the sendResponse() method.
+   *
+   * @expectedException \Exception
+   */
+  public function testSendResponse() {
+    $form_id = 'test_form_id';
+    $expected_form = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $form_arg = $this->getMockForm($form_id, $expected_form);
+
+    // Do an initial build of the form and track the build ID.
+    $form_state = new FormState();
+    $this->formBuilder->buildForm($form_arg, $form_state);
+  }
+
+  /**
    * Tests that HTML IDs are unique when rebuilding a form with errors.
    */
   public function testUniqueHtmlId() {
diff --git a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php
index 24c4ddd..0c8a478 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php
@@ -565,7 +565,8 @@ public function testAddCleanValueKey() {
    */
   public function testCleanValues($form_state) {
     $form_state->setValue('value_to_keep', 'magic_ponies');
-    $this->assertSame($form_state->cleanValues()->getValues(), ['value_to_keep' => 'magic_ponies']);
+    $form_state->cleanValues();
+    $this->assertSame($form_state->getValues(), ['value_to_keep' => 'magic_ponies']);
   }
 }
 
diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
index 3ad3d09..2386eb2 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
@@ -256,6 +256,16 @@ protected function assertFormElement(array $expected_form, array $actual_form, $
  * Provides a test form builder class.
  */
 class TestFormBuilder extends FormBuilder {
+  protected static $seenIds = array();
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function sendResponse(Response $response) {
+    parent::sendResponse($response);
+    // Throw an exception instead of exiting.
+    throw new \Exception('exit');
+  }
 
   /**
    * @param \Drupal\Core\Session\AccountInterface $account
@@ -290,6 +300,41 @@ protected function getElementInfo($type) {
     }
     return $types[$type];
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function drupalHtmlClass($class) {
+    return $class;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function drupalHtmlId($id) {
+    if (isset(static::$seenIds[$id])) {
+      $id = $id . '--' . ++static::$seenIds[$id];
+    }
+    else {
+      static::$seenIds[$id] = 1;
+    }
+    return $id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function drupalStaticReset($name = NULL) {
+    static::$seenIds = array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function requestUri() {
+    return '';
+  }
+
 }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php
index efe5ef5..e2cfd91 100644
--- a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php
@@ -96,6 +96,33 @@ public function testContextBubblingEdgeCases(array $element, array $expected_top
   public function providerTestContextBubblingEdgeCases() {
     $data = [];
 
+    // Bubbled cache contexts cannot override a cache ID set by #cache['cid'].
+    // But the cache context is bubbled nevertheless.
+    $test_element = [
+      '#cache' => [
+        'cid' => 'parent',
+      ],
+      '#markup' => 'parent',
+      'child' => [
+        '#cache' => [
+          'contexts' => ['foo'],
+        ],
+      ],
+    ];
+    $expected_cache_items = [
+      'parent' => [
+        '#attached' => [],
+        '#cache' => [
+          'contexts' => ['foo'],
+          'tags' => [],
+          'max-age' => Cache::PERMANENT,
+        ],
+        '#post_render_cache' => [],
+        '#markup' => 'parent',
+      ],
+    ];
+    $data[] = [$test_element, ['foo'], $expected_cache_items];
+
     // Cache contexts of inaccessible children aren't bubbled (because those
     // children are not rendered at all).
     $test_element = [
@@ -555,11 +582,11 @@ public static function bubblingPreRender($elements) {
         '#markup' => $placeholder,
       ],
       'child_nested_pre_render_uncached' => [
-        '#cache' => ['keys' => ['uncached_nested']],
+        '#cache' => ['cid' => 'uncached_nested'],
         '#pre_render' => [__CLASS__ . '::bubblingNestedPreRenderUncached'],
       ],
       'child_nested_pre_render_cached' => [
-        '#cache' => ['keys' => ['cached_nested']],
+        '#cache' => ['cid' => 'cached_nested'],
         '#pre_render' => [__CLASS__ . '::bubblingNestedPreRenderCached'],
       ],
     ];
diff --git a/core/tests/Drupal/Tests/Core/Render/RendererPostRenderCacheTest.php b/core/tests/Drupal/Tests/Core/Render/RendererPostRenderCacheTest.php
index c76554d..53e30d6 100644
--- a/core/tests/Drupal/Tests/Core/Render/RendererPostRenderCacheTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/RendererPostRenderCacheTest.php
@@ -72,7 +72,7 @@ public function testPostRenderCacheWithColdCache() {
     $this->setUpRequest('GET');
 
     // GET request: #cache enabled, cache miss.
-    $element['#cache'] = ['keys' => ['post_render_cache_test_GET']];
+    $element['#cache'] = ['cid' => 'post_render_cache_test_GET'];
     $element['#markup'] = '<p>#cache enabled, GET</p>';
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, '<p>overridden</p>', 'Output is overridden.');
@@ -100,7 +100,7 @@ public function testPostRenderCacheWithColdCache() {
 
     // GET request: #cache enabled, cache hit.
     $element = $test_element;
-    $element['#cache'] = ['keys' => ['post_render_cache_test_GET']];
+    $element['#cache'] = ['cid' => 'post_render_cache_test_GET'];
     $element['#markup'] = '<p>#cache enabled, GET</p>';
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, '<p>overridden</p>', 'Output is overridden.');
@@ -129,7 +129,7 @@ public function testPostRenderCacheWithPostRequest() {
 
     // POST request: #cache enabled, cache miss.
     $element = $test_element;
-    $element['#cache'] = ['keys' => ['post_render_cache_test_POST']];
+    $element['#cache'] = ['cid' => 'post_render_cache_test_POST'];
     $element['#markup'] = '<p>#cache enabled, POST</p>';
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, '<p>overridden</p>', 'Output is overridden.');
@@ -435,7 +435,7 @@ public function testPlaceholder() {
     // GET request: #cache enabled, cache miss.
     $this->setUpRequest();
     $element = $test_element;
-    $element['#cache'] = ['keys' => ['render_cache_placeholder_test_GET']];
+    $element['#cache'] = ['cid' => 'render_cache_placeholder_test_GET'];
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, $expected_output, 'Placeholder was replaced in output');
     $this->assertTrue(isset($element['#printed']), 'No cache hit');
@@ -475,7 +475,7 @@ public function testPlaceholder() {
 
     // GET request: #cache enabled, cache hit.
     $element = $test_element;
-    $element['#cache'] = ['keys' => ['render_cache_placeholder_test_GET']];
+    $element['#cache'] = ['cid' => 'render_cache_placeholder_test_GET'];
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, $expected_output, 'Placeholder was replaced in output');
     $this->assertFalse(isset($element['#printed']), 'Cache hit');
@@ -533,8 +533,8 @@ public function testChildElementPlaceholder() {
     // GET request: #cache enabled, cache miss.
     $this->setUpRequest();
     $element = $test_element;
-    $element['#cache'] = ['keys' => ['render_cache_placeholder_test_GET']];
-    $element['foo']['#cache'] = ['keys' => ['render_cache_placeholder_test_child_GET']];
+    $element['#cache'] = ['cid' => 'render_cache_placeholder_test_GET'];
+    $element['foo']['#cache'] = ['cid' => 'render_cache_placeholder_test_child_GET'];
     // Render, which will use the common-test-render-element.html.twig template.
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, $expected_output, 'Placeholder was replaced in output');
@@ -635,7 +635,7 @@ public function testChildElementPlaceholder() {
 
     // GET request: #cache enabled, cache hit.
     $element = $test_element;
-    $element['#cache'] = ['keys' => ['render_cache_placeholder_test_GET']];
+    $element['#cache'] = ['cid' => 'render_cache_placeholder_test_GET'];
     // Render, which will use the common-test-render-element.html.twig template.
     $output = $this->renderer->renderRoot($element);
     $this->assertSame($output, $expected_output, 'Placeholder was replaced in output');
diff --git a/core/tests/Drupal/Tests/Core/Render/RendererTest.php b/core/tests/Drupal/Tests/Core/Render/RendererTest.php
index 36cc3bc..a53155f 100644
--- a/core/tests/Drupal/Tests/Core/Render/RendererTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/RendererTest.php
@@ -538,13 +538,13 @@ public function testRenderCache() {
     // Create an empty element.
     $test_element = [
       '#cache' => [
-        'keys' => ['render_cache_test'],
+        'cid' => 'render_cache_test',
         'tags' => ['render_cache_tag'],
       ],
       '#markup' => '',
       'child' => [
         '#cache' => [
-          'keys' => ['render_cache_test_child'],
+          'cid' => 'render_cache_test_child',
           'tags' => ['render_cache_tag_child:1', 'render_cache_tag_child:2'],
         ],
         '#markup' => '',
@@ -577,46 +577,6 @@ public function testRenderCache() {
     $this->assertSame(Cache::mergeTags($expected_tags, ['rendered']), $cache_item->tags);
   }
 
-  /**
-   * @covers ::render
-   * @covers ::doRender
-   * @covers ::cacheGet
-   * @covers ::cacheSet
-   * @covers ::createCacheID
-   *
-   * @dataProvider providerTestRenderCacheMaxAge
-   */
-  public function testRenderCacheMaxAge($max_age, $is_render_cached, $render_cache_item_expire) {
-    $this->setUpRequest();
-    $this->setupMemoryCache();
-
-    $element = [
-      '#cache' => [
-        'keys' => ['render_cache_test'],
-        'max-age' => $max_age,
-      ],
-      '#markup' => '',
-    ];
-    $this->renderer->render($element);
-
-    $cache_item = $this->cacheFactory->get('render')->get('render_cache_test');
-    if (!$is_render_cached) {
-      $this->assertFalse($cache_item);
-    }
-    else {
-      $this->assertNotFalse($cache_item);
-      $this->assertSame($render_cache_item_expire, $cache_item->expire);
-    }
-  }
-
-  public function providerTestRenderCacheMaxAge() {
-    return [
-      [0, FALSE, NULL],
-      [60, TRUE, REQUEST_TIME + 60],
-      [Cache::PERMANENT, TRUE, -1],
-    ];
-  }
-
 }
 
 class TestAccessClass {
diff --git a/core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php b/core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php
index d0c811c..6f47816 100644
--- a/core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/AcceptHeaderMatcherTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Routing;
 
+use Drupal\Core\ContentNegotiation;
 use Drupal\Core\Routing\AcceptHeaderMatcher;
 use Drupal\Tests\Core\Routing\RoutingFixtures;
 use Drupal\Tests\UnitTestCase;
@@ -40,7 +41,7 @@ protected function setUp() {
     parent::setUp();
 
     $this->fixtures = new RoutingFixtures();
-    $this->matcher = new AcceptHeaderMatcher();
+    $this->matcher = new AcceptHeaderMatcher(new ContentNegotiation());
   }
 
   /**
@@ -49,14 +50,14 @@ protected function setUp() {
    * @see Drupal\Tests\Core\Routing\AcceptHeaderMatcherTest::testAcceptFiltering()
    */
   public function acceptFilterProvider() {
-    return [
+    return array(
       // Check that JSON routes get filtered and prioritized correctly.
-      ['application/json, text/xml;q=0.9', 'json', 'route_c', 'route_e'],
+      array('application/json, text/xml;q=0.9', 'route_c', 'route_e'),
       // Tests a JSON request with alternative JSON MIME type Accept header.
-      ['application/x-json, text/xml;q=0.9', 'json', 'route_c', 'route_e'],
+      array('application/x-json, text/xml;q=0.9', 'route_c', 'route_e'),
       // Tests a standard HTML request.
-      ['text/html, text/xml;q=0.9', 'html', 'route_e', 'route_c'],
-    ];
+      array('text/html, text/xml;q=0.9', 'route_e', 'route_c'),
+    );
   }
 
   /**
@@ -64,8 +65,6 @@ public function acceptFilterProvider() {
    *
    * @param string $accept_header
    *   The HTTP Accept header value of the request.
-   * @param string $format
-   *   The request format.
    * @param string $included_route
    *   The route name that should survive the filter and be ranked first.
    * @param string $excluded_route
@@ -73,12 +72,11 @@ public function acceptFilterProvider() {
    *
    * @dataProvider acceptFilterProvider
    */
-  public function testAcceptFiltering($accept_header, $format, $included_route, $excluded_route) {
+  public function testAcceptFiltering($accept_header, $included_route, $excluded_route) {
     $collection = $this->fixtures->sampleRouteCollection();
 
     $request = Request::create('path/two', 'GET');
     $request->headers->set('Accept', $accept_header);
-    $request->setRequestFormat($format);
     $routes = $this->matcher->filter($collection, $request);
     $this->assertEquals(count($routes), 4, 'The correct number of routes was found.');
     $this->assertNotNull($routes->get($included_route), "Route $included_route was found when matching $accept_header.");
@@ -105,8 +103,6 @@ public function testNoRouteFound() {
 
     $request = Request::create('path/two', 'GET');
     $request->headers->set('Accept', 'application/json, text/xml;q=0.9');
-    $request->setRequestFormat('json');
-    $this->matcher->filter($routes, $request);
     $this->matcher->filter($routes, $request);
     $this->fail('No exception was thrown.');
   }
diff --git a/core/tests/Drupal/Tests/Core/Routing/RoutePreloaderTest.php b/core/tests/Drupal/Tests/Core/Routing/RoutePreloaderTest.php
index 5692e6a..109a3f2 100644
--- a/core/tests/Drupal/Tests/Core/Routing/RoutePreloaderTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/RoutePreloaderTest.php
@@ -35,6 +35,13 @@ class RoutePreloaderTest extends UnitTestCase {
   protected $state;
 
   /**
+   * The mocked content negotiator.
+   *
+   * @var \Drupal\Core\ContentNegotiation|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $negotiation;
+
+  /**
    * The tested preloader.
    *
    * @var \Drupal\Core\Routing\RoutePreloader
@@ -47,7 +54,10 @@ class RoutePreloaderTest extends UnitTestCase {
   protected function setUp() {
     $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
     $this->state = $this->getMock('\Drupal\Core\State\StateInterface');
-    $this->preloader = new RoutePreloader($this->routeProvider, $this->state);
+    $this->negotiation = $this->getMockBuilder('\Drupal\Core\ContentNegotiation')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->preloader = new RoutePreloader($this->routeProvider, $this->state, $this->negotiation);
   }
 
   /**
@@ -126,10 +136,12 @@ public function testOnRequestNonHtml() {
       ->disableOriginalConstructor()
       ->getMock();
     $request = new Request();
-    $request->setRequestFormat('non-html');
     $event->expects($this->any())
       ->method('getRequest')
       ->will($this->returnValue($request));
+    $this->negotiation->expects($this->once())
+      ->method('getContentType')
+      ->will($this->returnValue('non-html'));
 
     $this->routeProvider->expects($this->never())
       ->method('getRoutesByNames');
@@ -147,10 +159,12 @@ public function testOnRequestOnHtml() {
       ->disableOriginalConstructor()
       ->getMock();
     $request = new Request();
-    $request->setRequestFormat('html');
     $event->expects($this->any())
       ->method('getRequest')
       ->will($this->returnValue($request));
+    $this->negotiation->expects($this->once())
+      ->method('getContentType')
+      ->will($this->returnValue('html'));
 
     $this->routeProvider->expects($this->once())
       ->method('getRoutesByNames')
diff --git a/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php b/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
index f92109b..efea670 100644
--- a/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
+++ b/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Tests\Core\StackMiddleware;
 
-use Drupal\Core\Site\Settings;
 use Drupal\Core\StackMiddleware\ReverseProxyMiddleware;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\HttpFoundation\Request;
@@ -35,10 +34,7 @@ public function setUp() {
    * Tests that subscriber does not act when reverse proxy is not set.
    */
   public function testNoProxy() {
-    $settings = new Settings(array());
-    $this->assertEquals(0, $settings->get('reverse_proxy'));
-
-    $middleware = new ReverseProxyMiddleware($this->mockHttpKernel, $settings);
+    $middleware = new ReverseProxyMiddleware($this->mockHttpKernel, []);
     // Mock a request object.
     $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array('setTrustedHeaderName', 'setTrustedProxies'));
     // setTrustedHeaderName() should never fire.
@@ -55,8 +51,7 @@ public function testNoProxy() {
    */
   public function testReverseProxyEnabled($provided_settings) {
       // Enable reverse proxy and add test values.
-      $settings = new Settings(array('reverse_proxy' => 1) + $provided_settings);
-      $this->trustedHeadersAreSet($settings);
+      $this->trustedHeadersAreSet(['enabled' => TRUE] + $provided_settings);
   }
 
   /**
@@ -66,15 +61,15 @@ public function reverseProxyEnabledProvider() {
     return array(
       array(
         array(
-          'reverse_proxy_header' => 'HTTP_X_FORWARDED_FOR',
-          'reverse_proxy_addresses' => array(),
+          'header' => 'HTTP_X_FORWARDED_FOR',
+          'addresses' => array(),
         ),
       ),
       array(
         array(
-          'reverse_proxy_header' => 'X_FORWARDED_HOST',
-          'reverse_proxy_addresses' => array('127.0.0.2', '127.0.0.3'),
-        ),
+          'header' => 'X_FORWARDED_HOST',
+          'addresses' => array('127.0.0.2', '127.0.0.3'),
+        )
       ),
     );
   }
@@ -85,16 +80,13 @@ public function reverseProxyEnabledProvider() {
    * \Symfony\Component\HttpFoundation\Request::setTrustedHeaderName() and
    * \Symfony\Component\HttpFoundation\Request::setTrustedProxies() should
    * always be called when reverse proxy settings are enabled.
-   *
-   * @param \Drupal\Core\Site\Settings $settings
-   *   The settings object that holds reverse proxy configuration.
    */
-  protected function trustedHeadersAreSet(Settings $settings) {
-    $middleware = new ReverseProxyMiddleware($this->mockHttpKernel, $settings);
+  protected function trustedHeadersAreSet(array $configuration) {
+    $middleware = new ReverseProxyMiddleware($this->mockHttpKernel, $configuration);
     $request = new Request();
 
     $middleware->handle($request);
-    $this->assertSame($settings->get('reverse_proxy_header'), $request->getTrustedHeaderName($request::HEADER_CLIENT_IP));
-    $this->assertSame($settings->get('reverse_proxy_addresses'), $request->getTrustedProxies());
+    $this->assertSame($configuration['header'], $request->getTrustedHeaderName($request::HEADER_CLIENT_IP));
+    $this->assertSame($configuration['addresses'], $request->getTrustedProxies());
   }
 }
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index d0512e1..76f745c 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -68,7 +68,7 @@ function drupal_phpunit_register_extension_dirs(Composer\Autoload\ClassLoader $l
 }
 
 // Start with classes in known locations.
-$loader = require __DIR__ . '/../../autoload.php';
+$loader = require __DIR__ . '/../vendor/autoload.php';
 $loader->add('Drupal\\Tests', __DIR__);
 
 // Scan for arbitrary extension namespaces from core and contrib.
diff --git a/core/themes/bartik/css/components/footer.css b/core/themes/bartik/css/components/footer.css
index 9f5e47b..0d7727d 100644
--- a/core/themes/bartik/css/components/footer.css
+++ b/core/themes/bartik/css/components/footer.css
@@ -42,10 +42,6 @@
     clear: none;
   }
 }
-#site-footer__wrapper h2 {
-  color: #c0c0c0;
-  color: rgba(255, 255, 255, 0.65);
-}
 #site-footer__wrapper .block .content {
   color: #c0c0c0;
   color: rgba(255, 255, 255, 0.65);
@@ -79,6 +75,13 @@
   padding: 0.5em 0;
   margin-top: 0;
 }
+#site-footer__bottom .block > h2 {
+  /* @extend .visually-hidden */
+  position: absolute !important;
+  clip: rect(1px, 1px, 1px, 1px);
+  overflow: hidden;
+  height: 1px;
+}
 #site-footer__bottom .block h2 {
   margin: 0;
 }
diff --git a/core/themes/bartik/css/components/vertical-tabs.component.css b/core/themes/bartik/css/components/vertical-tabs.component.css
index ce4d6cd..444fd9d 100644
--- a/core/themes/bartik/css/components/vertical-tabs.component.css
+++ b/core/themes/bartik/css/components/vertical-tabs.component.css
@@ -1,14 +1,9 @@
-/**
- * @file
- * Vertical tabs component.
- */
-
 /* Vertical Tabs Reset */
-.vertical-tabs__menu {
+ul.vertical-tabs-list {
   margin: -1px 0 -1px -15em; /* LTR */
   padding: 0;
 }
-[dir="rtl"] .vertical-tabs__menu {
+[dir="rtl"] ul.vertical-tabs-list {
   margin-left: 0;
   margin-right: -15em;
   /* This is required to win specificity over [dir="rtl"] .region-content ul */
diff --git a/core/themes/bartik/templates/comment.html.twig b/core/themes/bartik/templates/comment.html.twig
index 21cca3c..1d6718d 100644
--- a/core/themes/bartik/templates/comment.html.twig
+++ b/core/themes/bartik/templates/comment.html.twig
@@ -22,6 +22,7 @@
  * - submitted: Submission information created from author and created
  *   during template_preprocess_comment().
  * - user_picture: The comment author's profile picture.
+ * - signature: The comment author's signature.
  * - status: Comment status. Possible values are:
  *   unpublished, published, or preview.
  * - title: Comment title, linked to the comment.
@@ -107,6 +108,9 @@
       {{ content|without('links') }}
     </div>
     <footer class="comment__footer">
+      {% if signature %}
+        <div class="user-signature clearfix">{{ signature }}</div>
+      {% endif %}
       {% if content.links %}
         <nav>{{ content.links }}</nav>
       {% endif %}
diff --git a/core/themes/classy/templates/content/comment.html.twig b/core/themes/classy/templates/content/comment.html.twig
index 97baf55..6b521a5 100644
--- a/core/themes/classy/templates/content/comment.html.twig
+++ b/core/themes/classy/templates/content/comment.html.twig
@@ -22,6 +22,7 @@
  * - submitted: Submission information created from author and created
  *   during template_preprocess_comment().
  * - user_picture: The comment author's profile picture.
+ * - signature: The comment author's signature.
  * - status: Comment status. Possible values are:
  *   unpublished, published, or preview.
  * - title: Comment title, linked to the comment.
@@ -108,6 +109,12 @@
 
   <div{{ content_attributes.addClass('content') }}>
     {{ content|without('links') }}
+
+    {% if signature %}
+      <div class="user-signature">
+        {{ signature }}
+      </div>
+    {% endif %}
   </div>
   {% if content.links %}
     {{ content.links }}
diff --git a/core/themes/seven/css/components/vertical-tabs.css b/core/themes/seven/css/components/vertical-tabs.css
index d42da4a..325a3af 100644
--- a/core/themes/seven/css/components/vertical-tabs.css
+++ b/core/themes/seven/css/components/vertical-tabs.css
@@ -1,8 +1,6 @@
 /**
- * @file
  * Override of misc/vertical-tabs.css.
  */
-
 .vertical-tabs {
   position: relative;
   overflow: hidden;
@@ -11,7 +9,7 @@
   border-radius: 4px;
   background: #e6e5e1;
 }
-.vertical-tabs__menu {
+.vertical-tabs-list {
   float: left; /* LTR */
   width: 240px;
   margin: 0 -100% -1px 0; /* LTR */
@@ -19,29 +17,32 @@
   border-bottom: 1px solid #ccc;
   line-height: 1;
 }
-[dir="rtl"] .vertical-tabs__menu {
+[dir="rtl"] .vertical-tabs-list {
   float: right;
   margin: 0 0 -1px -100%;
 }
-.vertical-tabs__menu-item {
+.vertical-tab-button {
   position: relative;
+  margin: 0;
+  list-style: none;
+  list-style-image: none;
 }
-.vertical-tabs__menu-item.is-selected {
+.vertical-tab-button.selected {
   z-index: 1;
   overflow-x: hidden;
   width: 100%;
   border-right: 1px solid #fcfcfa; /* LTR */
   box-shadow: 0 5px 5px -5px hsla(0, 0%, 0%, 0.3);
 }
-[dir="rtl"] .vertical-tabs__menu-item.is-selected {
+[dir="rtl"] .vertical-tab-button.selected {
   border-left: 1px solid #fcfcfa;
   border-right: none;
 }
-.vertical-tabs__menu-item:focus,
-.vertical-tabs__menu-item:active {
+.vertical-tab-button:focus,
+.vertical-tab-button:active {
   z-index: 2;
 }
-.vertical-tabs__menu-item a {
+.vertical-tab-button a {
   display: block;
   padding: 10px 15px 15px;
   border-bottom: 1px solid #b3b2ad;
@@ -49,59 +50,60 @@
   text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
   text-decoration: none;
 }
-.vertical-tabs__menu-item:last-child a {
+.vertical-tab-button:last-child a {
   border-bottom: 0;
 }
-.vertical-tabs__menu-item.is-selected a,
-.vertical-tabs__menu-item a:hover,
-.vertical-tabs__menu-item a:focus {
+.vertical-tab-button.selected a,
+.vertical-tab-button a:hover,
+.vertical-tab-button a:focus {
   background: #fcfcfa;
   text-shadow: none;
+  text-decoration: none;
 }
-.vertical-tabs__menu-item.is-selected a {
+.vertical-tab-button.selected a {
   border-bottom-color: #b3b2ad;
   color: #004f80;
 }
-.vertical-tabs__menu-item.is-selected a:hover,
-.vertical-tabs__menu-item.is-selected a:focus {
+.vertical-tab-button.selected a:hover,
+.vertical-tab-button.selected a:focus {
   color: #007ecc;
 }
 [data-vertical-tabs-panes] {
   background-color: #fcfcfa;
 }
-.vertical-tabs__panes {
+.vertical-tabs-panes {
   margin: 0 0 0 240px; /* LTR */
   padding: 10px 15px 10px 15px;
   border-left: 1px solid #a6a5a1; /* LTR */
 }
-[dir="rtl"] .vertical-tabs__panes {
+[dir="rtl"] .vertical-tabs-panes {
   margin: 0 240px 0 0;
   border-left: none;
   border-right: 1px solid #a6a5a1;
 }
-.vertical-tabs__panes:after {
+.vertical-tabs-panes:after {
   content: "";
   display: table;
   clear: both;
 }
-.vertical-tabs__pane {
+.vertical-tabs-pane {
   margin: 0;
   padding: 0;
   border: 0;
   color: #595959;
 }
-.vertical-tabs__menu-item-title {
+.vertical-tab-button strong {
   font-size: 0.923em;
 }
-.vertical-tabs__menu-item-summary {
+.vertical-tab-button .summary {
   display: block;
   padding-top: 0.4em;
   color: #666;
   font-size: 0.846em;
 }
-.vertical-tabs__menu-item.is-selected a:focus .vertical-tabs__menu-item-title {
+.vertical-tab-button.selected a:focus strong {
   text-decoration: underline;
 }
-.vertical-tabs__pane > summary {
+.vertical-tabs-pane > summary {
   display: none;
 }
diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml
index 77e99cc..31d651c 100644
--- a/sites/default/default.services.yml
+++ b/sites/default/default.services.yml
@@ -88,3 +88,73 @@ parameters:
     # Default key/value expirable storage service to use.
     # @default keyvalue.database.expirable
     # default: keyvalue.database.expirable
+  #
+  # Queue configuration.
+  # The following values can be set in the factory.queue container parameter:
+  #
+  # - reliable_service_$name: The container service to use for the reliable
+  #   queue $name.
+  # - service_$name: The container service to use for the queue $name.
+  # - default: The container service to use by default for queues without
+  #   overrides. This defaults to 'queue.database'.
+  #
+  factory.queue: {}
+  #
+  # Reverse Proxy Configuration:
+  #
+  # Reverse proxy servers are often used to enhance the performance
+  # of heavily visited sites and may also provide other site caching,
+  # security, or encryption benefits. In an environment where Drupal
+  # is behind a reverse proxy, the real IP address of the client should
+  # be determined such that the correct client IP address is available
+  # to Drupal's logging, statistics, and access management systems. In
+  # the most simple scenario, the proxy server will add an
+  # X-Forwarded-For header to the request that contains the client IP
+  # address. However, HTTP headers are vulnerable to spoofing, where a
+  # malicious client could bypass restrictions by setting the
+  #  X-Forwarded-For header directly. Therefore, Drupal's proxy
+  # configuration requires the IP addresses of all remote proxies to be
+  # specified in $settings['reverse_proxy_addresses'] to work correctly.
+  #
+  # Enable this setting to get Drupal to determine the client IP from
+  # the X-Forwarded-For header (or $settings['reverse_proxy_header'] if set).
+  # If you are unsure about this setting, do not have a reverse proxy,
+  # or Drupal operates in a shared hosting environment, this setting
+  # should remain commented out.
+  #
+  # In order for this setting to be used you must specify every possible
+  # reverse proxy IP address in $settings['reverse_proxy_addresses'].
+  # If a complete list of reverse proxies is not available in your
+  # environment (for example, if you use a CDN) you may set the
+  # $_SERVER['REMOTE_ADDR'] variable directly in settings.php.
+  # Be aware, however, that it is likely that this would allow IP
+  # address spoofing unless more advanced precautions are taken.
+  #
+  # Available keys:
+  #   - enabled: Switch on the reverse_proxy
+  #   - adresses: Specify every reverse proxy IP address in your environment.
+  #     This setting is required if $settings['reverse_proxy'] is TRUE.
+  #   - header: Set this value if your proxy server sends the client IP in a
+  #       header other than X-Forwarded-For.
+
+  reverse_proxy: {}
+  # reverse_proxy:
+  #   enabled: true
+  #   addresses: ['a.b.c.d']
+  #   header: 'HTTP_X_CLUSTER_CLIENT_IP';
+
+  # Default mode for for directories and files written by Drupal.
+  #
+  # Value should be in PHP Octal Notation, with leading zero.
+
+  file_chmod: {}
+  # file_chmod:
+  #   directory: 0775
+  #   file: 0664
+
+  # Session write interval:
+  #
+  # Set the minimum interval between each session write to database.
+  # For performance reasons it defaults to 180.
+  #
+  session_write_interval: 180
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index d5d8704..d7c57c8 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -414,14 +414,6 @@
 # $settings['allow_authorize_operations'] = FALSE;
 
 /**
- * Default mode for for directories and files written by Drupal.
- *
- * Value should be in PHP Octal Notation, with leading zero.
- */
-# $settings['file_chmod_directory'] = 0775;
-# $settings['file_chmod_file'] = 0664;
-
-/**
  * Public file path:
  *
  * A local file system path where public files will be stored. This directory
@@ -446,14 +438,6 @@
 # $settings['file_private_path'] = '';
 
 /**
- * Session write interval:
- *
- * Set the minimum interval between each session write to database.
- * For performance reasons it defaults to 180.
- */
-# $settings['session_write_interval'] = 180;
-
-/**
  * String overrides:
  *
  * To override specific strings on your site with or without enabling the Locale
