diff --git a/core/core.services.yml b/core/core.services.yml
index 4006ceb..951c458 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -179,6 +179,10 @@ services:
     class: Drupal\Core\Http\Client
     tags:
       - { name: service_collector, tag: http_client_subscriber, call: attach }
+  http_client_simpletest_subscriber:
+    class: Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber
+    tags:
+      - { name: http_client_subscriber }
   theme.negotiator:
     class: Drupal\Core\Theme\ThemeNegotiator
     arguments: ['@access_check.theme', '@request_stack']
@@ -581,7 +585,7 @@ services:
     class: Drupal\Core\EventSubscriber\FinishResponseSubscriber
     tags:
       - { name: event_subscriber }
-    arguments: ['@language_manager', '@config.factory']
+    arguments: ['@language_manager']
     scope: request
   redirect_response_subscriber:
     class: Drupal\Core\EventSubscriber\RedirectResponseSubscriber
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index d33d1ee..d00f819 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -650,27 +650,26 @@ function drupal_page_cache_get_cid(Request $request) {
 /**
  * Retrieves the current page from the cache.
  *
+ * Note: we do not serve cached pages to authenticated users, or to anonymous
+ * users when $_SESSION is non-empty. $_SESSION may contain status messages
+ * from a form submission, the contents of a shopping cart, or other user-
+ * specific content that should not be cached and displayed to other users.
+ *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The request for this page.
  *
- * @return \Symfony\Component\HttpFoundation\Response
- *   The response, if the page was found in the cache, NULL otherwise.
+ * @return
+ *   The cache object, if the page was found in the cache, NULL otherwise.
  */
 function drupal_page_get_cache(Request $request) {
-  $cache = \Drupal::cache('render')->get(drupal_page_cache_get_cid($request));
-  if ($cache) {
-    return $cache->data;
+  if (drupal_page_is_cacheable()) {
+    return \Drupal::cache('render')->get(drupal_page_cache_get_cid($request));
   }
 }
 
 /**
  * Determines the cacheability of the current page.
  *
- * Note: we do not serve cached pages to authenticated users, or to anonymous
- * users when $_SESSION is non-empty. $_SESSION may contain status messages
- * from a form submission, the contents of a shopping cart, or other user-
- * specific content that should not be cached and displayed to other users.
- *
  * @param $allow_caching
  *   Set to FALSE if you want to prevent this page to get cached.
  *
@@ -819,7 +818,7 @@ function drupal_send_headers($default_headers = array(), $only_default = FALSE)
  * fresh page on every request. This prevents authenticated users from seeing
  * locally cached pages.
  *
- * Also give each page a unique ETag. This should force clients to include both
+ * Also give each page a unique ETag. This will force clients to include both
  * an If-Modified-Since header and an If-None-Match header when doing
  * conditional requests for the page (required by RFC 2616, section 13.3.4),
  * making the validation more robust. This is a workaround for a bug in Mozilla
@@ -869,59 +868,100 @@ function drupal_page_header() {
  * and the conditions match those currently in the cache, a 304 Not Modified
  * response is sent.
  */
-function drupal_serve_page_from_cache(Response $response, Request $request) {
-  // Only allow caching in the browser and prevent that the response is stored
-  // by an external proxy server when the following conditions apply:
-  // 1. There is a session cookie on the request.
-  // 2. The Vary: Cookie header is on the response.
-  // 3. The Cache-Control header does not contain the no-cache directive.
-  if ($request->cookies->has(session_name()) &&
-    in_array('Cookie', $response->getVary()) &&
-    !$response->headers->hasCacheControlDirective('no-cache')) {
+function drupal_serve_page_from_cache(stdClass $cache, Response $response, Request $request) {
+  $config = \Drupal::config('system.performance');
 
-    $response->setPrivate();
-  }
+  // First half: we must determine if we should be returning a 304.
 
   // Negotiate whether to use compression.
-  if ($response->headers->get('Content-Encoding') == 'gzip' && extension_loaded('zlib')) {
-    if (strpos($request->headers->get('Accept-Encoding'), 'gzip') !== FALSE) {
-      // The response content is already gzip'ed, so make sure
+  $page_compression = !empty($cache->data['page_compressed']) && extension_loaded('zlib');
+  $return_compressed = $page_compression && $request->server->has('HTTP_ACCEPT_ENCODING') && strpos($request->server->get('HTTP_ACCEPT_ENCODING'), 'gzip') !== FALSE;
+
+  // Get headers. Keys are lower-case.
+  $boot_headers = drupal_get_http_header();
+
+  foreach ($cache->data['headers'] as $name => $value) {
+    // In the case of a 304 response, certain headers must be sent, and the
+    // remaining may not (see RFC 2616, section 10.3.5).
+    $name_lower = strtolower($name);
+    if (in_array($name_lower, array('content-location', 'expires', 'cache-control', 'vary')) && !isset($boot_headers[$name_lower])) {
+      $response->headers->set($name, $value);
+      unset($cache->data['headers'][$name]);
+    }
+  }
+
+  // If the client sent a session cookie, a cached copy will only be served
+  // to that one particular client due to Vary: Cookie. Thus, do not set
+  // max-age > 0, allowing the page to be cached by external proxies, when a
+  // session cookie is present unless the Vary header has been replaced.
+  $max_age = !$request->cookies->has(session_name()) || isset($boot_headers['vary']) ? $config->get('cache.page.max_age') : 0;
+  // RFC 2616, section 14.21 says: 'To mark a response as "never expires," an
+  // origin server sends an Expires date approximately one year from the time
+  // the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more
+  // than one year in the future.'
+  if ($max_age > 31536000 || $max_age === \Drupal\Core\Cache\Cache::PERMANENT) {
+    $max_age = 31536000;
+  }
+  $response->headers->set('Cache-Control', 'public, max-age=' . $max_age);
+
+  // Entity tag should change if the output changes.
+  $response->setEtag($cache->created);
+
+  // See if the client has provided the required HTTP headers.
+  $if_modified_since = $request->server->has('HTTP_IF_MODIFIED_SINCE') ? strtotime($request->server->get('HTTP_IF_MODIFIED_SINCE')) : FALSE;
+  $if_none_match = $request->server->has('HTTP_IF_NONE_MATCH') ? stripslashes($request->server->get('HTTP_IF_NONE_MATCH')) : FALSE;
+
+  if ($if_modified_since && $if_none_match
+      && $if_none_match == $response->headers->get('etag') // etag must match
+      && $if_modified_since == $cache->created) {  // if-modified-since must match
+    $response->setStatusCode(304);
+    return;
+  }
+
+  // Second half: we're not returning a 304, so put in other headers.
+
+  // Send the remaining headers.
+  foreach ($cache->data['headers'] as $name => $value) {
+    $response->headers->set($name, $value);
+    drupal_add_http_header($name, $value);
+  }
+
+  $response->setLastModified(\DateTime::createFromFormat('U', $cache->created));
+
+  // HTTP/1.0 proxies does not support the Vary header, so prevent any caching
+  // by sending an Expires date in the past. HTTP/1.1 clients ignores the
+  // Expires header if a Cache-Control: max-age= directive is specified (see RFC
+  // 2616, section 14.9.3).
+  if (!$response->getExpires()) {
+    $response->setExpires(\DateTime::createFromFormat('j-M-Y H:i:s T', '19-Nov-1978 05:00:00 GMT'));
+  }
+
+  // Allow HTTP proxies to cache pages for anonymous users without a session
+  // cookie. The Vary header is used to indicates the set of request-header
+  // fields that fully determines whether a cache is permitted to use the
+  // response to reply to a subsequent request for a given URL without
+  // revalidation.
+  if (!isset($boot_headers['vary']) && !Settings::get('omit_vary_cookie')) {
+    $response->setVary('Cookie', FALSE);
+  }
+
+  if ($page_compression) {
+    $response->setVary('accept-encoding', FALSE);
+    // If page_compression is enabled, the cache contains gzipped data.
+    if ($return_compressed) {
+      // $cache->data['body'] is already gzip'ed, so make sure
       // zlib.output_compression does not compress it once more.
       ini_set('zlib.output_compression', '0');
+      $response->headers->set('content-encoding', 'gzip');
     }
     else {
-      // The client does not support compression. Decompress the content and
-      // remove the Content-Encoding header.
-      $content = $response->getContent();
-      $content = gzinflate(substr(substr($content, 10), 0, -8));
-      $response->setContent($content);
-      $response->headers->remove('Content-Encoding');
+      // The client does not support compression, so unzip the data in the
+      // cache. Strip the gzip header and run uncompress.
+      $cache->data['body'] = gzinflate(substr(substr($cache->data['body'], 10), 0, -8));
     }
   }
 
-  // Perform HTTP revalidation.
-  // @todo Use Response::isNotModified() as per https://drupal.org/node/2259489
-  $last_modified = $response->getLastModified();
-  if ($last_modified) {
-    // See if the client has provided the required HTTP headers.
-    $if_modified_since = $request->server->has('HTTP_IF_MODIFIED_SINCE') ? strtotime($request->server->get('HTTP_IF_MODIFIED_SINCE')) : FALSE;
-    $if_none_match = $request->server->has('HTTP_IF_NONE_MATCH') ? stripslashes($request->server->get('HTTP_IF_NONE_MATCH')) : FALSE;
-
-    if ($if_modified_since && $if_none_match
-      && $if_none_match == $response->getEtag() // etag must match
-      && $if_modified_since == $last_modified->getTimestamp()) {  // if-modified-since must match
-      $response->setStatusCode(304);
-      $response->setContent(NULL);
-
-      // In the case of a 304 response, certain headers must be sent, and the
-      // remaining may not (see RFC 2616, section 10.3.5).
-      foreach (array_keys($response->headers->all()) as $name) {
-        if (!in_array($name, array('content-location', 'expires', 'cache-control', 'vary'))) {
-          $response->headers->remove($name);
-        }
-      }
-    }
-  }
+  $response->setContent($cache->data['body']);
 }
 
 /**
@@ -1459,12 +1499,15 @@ function drupal_get_user_timezone() {
  *
  * @return
  *   A salt based on information in settings.php, not in the database.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. Use
- *   \Drupal\Core\Site\Settings::getHashSalt() instead.
  */
 function drupal_get_hash_salt() {
-  return Settings::getHashSalt();
+  $hash_salt = Settings::get('hash_salt');
+  // This should never happen, as it breaks user logins and many other services.
+  // Therefore, explicitly notify the user (developer) by throwing an exception.
+  if (empty($hash_salt)) {
+    throw new \RuntimeException('Missing $settings[\'hash_salt\'] in settings.php.');
+  }
+  return $hash_salt;
 }
 
 /**
@@ -1584,6 +1627,8 @@ function _drupal_bootstrap_kernel() {
  * Attempts to serve a page from the cache.
  */
 function _drupal_bootstrap_page_cache() {
+  global $user;
+
   require_once __DIR__ . '/database.inc';
   // Check for a cache mode force from settings.php.
   if (Settings::get('page_cache_without_database')) {
@@ -1594,23 +1639,30 @@ function _drupal_bootstrap_page_cache() {
     $cache_enabled = $config->get('cache.page.use_internal');
   }
 
-  $request = \Drupal::request();
+  $request = Request::createFromGlobals();
   // If there is no session cookie and cache is enabled (or forced), try
   // to serve a cached page.
-  if (!$request->cookies->has(session_name()) && $cache_enabled && drupal_page_is_cacheable()) {
+  if (!$request->cookies->has(session_name()) && $cache_enabled) {
+    // Make sure there is a user object because its timestamp will be checked.
+    $user = new AnonymousUserSession();
     // Get the page from the cache.
-    $response = drupal_page_get_cache($request);
+    $cache = drupal_page_get_cache($request);
     // If there is a cached page, display it.
-    if ($response) {
+    if (is_object($cache)) {
+      $response = new Response();
       $response->headers->set('X-Drupal-Cache', 'HIT');
+      date_default_timezone_set(drupal_get_user_timezone());
 
-      drupal_serve_page_from_cache($response, $request);
+      drupal_serve_page_from_cache($cache, $response, $request);
 
       // We are done.
       $response->prepare($request);
       $response->send();
       exit;
     }
+    else {
+      drupal_add_http_header('X-Drupal-Cache', 'MISS');
+    }
   }
 }
 
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 8e0d53e..fb370b8 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -345,6 +345,44 @@ function drupal_get_feeds($delimiter = "\n") {
  */
 
 /**
+ * Processes a URL query parameter array to remove unwanted elements.
+ *
+ * @param $query
+ *   (optional) An array to be processed. Defaults to \Drupal::request()->query
+ *   parameters.
+ * @param $exclude
+ *   (optional) A list of $query array keys to remove. Use "parent[child]" to
+ *   exclude nested items.
+ * @param $parent
+ *   Internal use only. Used to build the $query array key for nested items.
+ *
+ * @return
+ *   An array containing query parameters, which can be used for url().
+ *
+ * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ *   Use \Drupal\Component\Utility\UrlHelper::filterQueryParameters().
+ */
+function drupal_get_query_parameters(array $query = NULL, array $exclude = array(), $parent = '') {
+  if (!isset($query)) {
+    $query = \Drupal::request()->query->all();
+  }
+  return UrlHelper::filterQueryParameters($query, $exclude, $parent);
+}
+
+/**
+ * Parses an array into a valid, rawurlencoded query string.
+ *
+ * @see drupal_get_query_parameters()
+ * @ingroup php_wrappers
+ *
+ * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ *   Use \Drupal\Component\Utility\UrlHelper::buildQuery().
+ */
+function drupal_http_build_query(array $query, $parent = '') {
+  return UrlHelper::buildQuery($query, $parent);
+}
+
+/**
  * Prepares a 'destination' URL query parameter for use with url().
  *
  * Used to direct the user back to the referring page after completing a form.
@@ -811,6 +849,23 @@ function url($path = NULL, array $options = array()) {
 }
 
 /**
+ * Returns TRUE if a path is external to Drupal (e.g. http://example.com).
+ *
+ * If a path cannot be assessed by Drupal's menu handler, then we must
+ * treat it as potentially insecure.
+ *
+ * @param $path
+ *   The internal path or external URL being linked to, such as "node/34" or
+ *   "http://example.com/foo".
+ *
+ * @return
+ *   Boolean TRUE or FALSE, where TRUE indicates an external path.
+ */
+function url_is_external($path) {
+  return UrlHelper::isExternal($path);
+}
+
+/**
  * Formats an attribute string for an HTTP header.
  *
  * @param $attributes
@@ -2750,37 +2805,55 @@ function _drupal_bootstrap_full($skip = FALSE) {
  * Page compression requires the PHP zlib extension
  * (http://php.net/manual/ref.zlib.php).
  *
- * @param \Symfony\Component\HttpFoundation\Response $response
- *   The fully populated response.
- * @param \Symfony\Component\HttpFoundation\Request $request
- *   The request for this page.
+ * @param $body
+ *   The response body.
+ * @return
+ *   The cached object or NULL if the page cache was not set.
  *
  * @see drupal_page_header()
  */
 function drupal_page_set_cache(Response $response, Request $request) {
-  // Check if the current page may be compressed.
-  if (\Drupal::config('system.performance')->get('response.gzip') &&
-    !$response->headers->get('Content-Encoding') && extension_loaded('zlib')) {
-
-    $content = $response->getContent();
-    if ($content) {
-      $response->setContent(gzencode($content, 9, FORCE_GZIP));
-      $response->headers->set('Content-Encoding', 'gzip');
-    }
+  if (drupal_page_is_cacheable()) {
+
+    // Check if the current page may be compressed.
+    $page_compressed = \Drupal::config('system.performance')->get('response.gzip') && extension_loaded('zlib');
+
+    $cache = (object) array(
+      'cid' => drupal_page_cache_get_cid($request),
+      'data' => array(
+        'body' => $response->getContent(),
+        'headers' => array(),
+        // We need to store whether page was compressed or not,
+        // because by the time it is read, the configuration might change.
+        'page_compressed' => $page_compressed,
+      ),
+      'tags' => HtmlViewSubscriber::convertHeaderToCacheTags($response->headers->get('X-Drupal-Cache-Tags')),
+      'expire' => Cache::PERMANENT,
+      'created' => REQUEST_TIME,
+    );
 
-    // When page compression is enabled, ensure that proxy caches will record
-    // and deliver different versions of a page depending on whether the
-    // client supports gzip or not.
-    $response->setVary('Accept-Encoding', FALSE);
-  }
+    $cache->data['headers'] = $response->headers->all();
 
-  // Use the actual timestamp from an Expires header, if available.
-  $date = $response->getExpires();
-  $expire = ($date > (new DateTime())) ? $date->getTimestamp() : Cache::PERMANENT;
+    // Hack: exclude the x-drupal-cache header; it may make it in here because
+    // of awkwardness in how we defer sending it over in _drupal_page_get_cache.
+    if (isset($cache->data['headers']['x-drupal-cache'])) {
+      unset($cache->data['headers']['x-drupal-cache']);
+    }
 
-  $cid = drupal_page_cache_get_cid($request);
-  $tags = HtmlViewSubscriber::convertHeaderToCacheTags($response->headers->get('X-Drupal-Cache-Tags'));
-  \Drupal::cache('render')->set($cid, $response, $expire, $tags);
+     // Use the actual timestamp from an Expires header, if available.
+    if ($date = $response->getExpires()) {
+      $date = DrupalDateTime::createFromDateTime($date);
+      $cache->expire = $date->getTimestamp();
+    }
+
+    if ($cache->data['body']) {
+      if ($page_compressed) {
+        $cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
+      }
+      \Drupal::cache('render')->set($cache->cid, $cache->data, $cache->expire, $cache->tags);
+    }
+    return $cache;
+  }
 }
 
 /**
diff --git a/core/includes/form.inc b/core/includes/form.inc
index c037ce1..984daf7 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1068,20 +1068,31 @@ function template_preprocess_fieldset(&$variables) {
   _form_set_attributes($element, array('form-wrapper'));
   $variables['attributes'] = $element['#attributes'];
   $variables['attributes']['class'][] = 'form-item';
+
+  // If the element is required, a required marker is appended to the label.
+  $variables['required'] = '';
+  if (!empty($element['#required'])) {
+    $variables['required'] = array(
+      '#theme' => 'form_required_marker',
+      '#element' => $element,
+    );
+  }
+
   $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : NULL;
   $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : NULL;
   $variables['children'] = $element['#children'];
+
+  // Build legend properties.
+  $variables['legend'] = array();
   $legend_attributes = array();
   if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') {
     $legend_attributes['class'][] = 'visually-hidden';
   }
   $variables['legend']['attributes'] = new Attribute($legend_attributes);
   $variables['legend']['title'] = (isset($element['#title']) && $element['#title'] !== '') ? Xss::filterAdmin($element['#title']) : '';
-  $legend_span_attributes = array('class' => array('fieldset-legend'));
-  if (!empty($element['#required'])) {
-    $legend_span_attributes['class'][] = 'form-required';
-    $variables['legend_span']['attributes'] = new Attribute($legend_span_attributes);
-  }
+
+  // Build description properties.
+  $variables['description'] = array();
   if (!empty($element['#description'])) {
     $description_id = $element['#attributes']['id'] . '--description';
     $description_attributes = array(
@@ -2921,7 +2932,7 @@ function template_preprocess_form_element(&$variables) {
     $variables['attributes']['class'][] = 'form-disabled';
   }
 
-  // If #title is not set, we don't display any label.
+  // If #title is not set, we don't display any label or required marker.
   if (!isset($element['#title'])) {
     $element['#title_display'] = 'none';
   }
@@ -2947,6 +2958,23 @@ function template_preprocess_form_element(&$variables) {
 }
 
 /**
+ * Returns HTML for a marker for required form elements.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *
+ * @ingroup themeable
+ */
+function theme_form_required_marker($variables) {
+  $attributes = array(
+    'class' => 'form-required',
+    'aria-hidden' => 'true',
+  );
+  return '<span' . new Attribute($attributes) . '>*</span>';
+}
+
+/**
  * Returns HTML for a form element label and required marker.
  *
  * Form element labels include the #title and a #required marker. The label is
@@ -2976,16 +3004,26 @@ function theme_form_element_label($variables) {
     return '';
   }
 
+  // If the element is required, a required marker is appended to the label.
+  $required = '';
+  if (!empty($element['#required'])) {
+    $marker = array(
+      '#theme' => 'form_required_marker',
+      '#element' => $element,
+    );
+    $required = drupal_render($marker);
+  }
+
   $title = Xss::filterAdmin($element['#title']);
 
   $attributes = array();
   // Style the label as class option to display inline with the element.
   if ($element['#title_display'] == 'after') {
-    $attributes['class'][] = 'option';
+    $attributes['class'] = 'option';
   }
   // Show label only to screen readers to avoid disruption in visual flows.
   elseif ($element['#title_display'] == 'invisible') {
-    $attributes['class'][] = 'visually-hidden';
+    $attributes['class'] = 'visually-hidden';
   }
 
   // A #for property of a dedicated #type 'label' element as precedence.
@@ -3002,13 +3040,7 @@ function theme_form_element_label($variables) {
     $attributes['for'] = $element['#id'];
   }
 
-  // For required elements a 'form-required' class is appended to the
-  // label attributes.
-  if (!empty($element['#required'])) {
-    $attributes['class'][] = 'form-required';
-  }
-
-  return '<label' . new Attribute($attributes) . '>' . $title . '</label>';
+  return '<label' . new Attribute($attributes) . '>' . t('!title!required', array('!title' => $title, '!required' => $required)) . '</label>';
 }
 
 /**
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 67e41f6..f080533 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -907,7 +907,7 @@ function install_goto($path) {
  */
 function drupal_current_script_url($query = array()) {
   $uri = $_SERVER['SCRIPT_NAME'];
-  $query = array_merge(UrlHelper::filterQueryParameters(\Drupal::request()->query->all()), $query);
+  $query = array_merge(drupal_get_query_parameters(), $query);
   if (!empty($query)) {
     $uri .= '?' . UrlHelper::buildQuery($query);
   }
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 12c11e6..4230087 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1997,7 +1997,7 @@ function template_preprocess_html(&$variables) {
   // Construct page title.
   if ($page->hasTitle()) {
     $head_title = array(
-      'title' => trim(strip_tags($page->getTitle())),
+      'title' => strip_tags($page->getTitle()),
       'name' => String::checkPlain($site_config->get('name')),
     );
   }
@@ -2662,6 +2662,9 @@ function drupal_common_theme() {
       'render element' => 'element',
       'template' => 'form-element',
     ),
+    'form_required_marker' => array(
+      'render element' => 'element',
+    ),
     'form_element_label' => array(
       'render element' => 'element',
     ),
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index 5c72435..9ae8cbb 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -618,7 +618,7 @@ public static function formBuilder() {
    * @return bool
    *   Returns TRUE is syncing flag set.
    */
-  public static function isConfigSyncing() {
+  public function isConfigSyncing() {
     return static::$container->get('config.installer')->isSyncing();
   }
 
diff --git a/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php b/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php
index 4fa30e2..7d68750 100644
--- a/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php
+++ b/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php
@@ -10,7 +10,6 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Core\PrivateKey;
 use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\Site\Settings;
 
 /**
  * Generates and validates CSRF tokens.
@@ -96,7 +95,7 @@ public function validate($token, $value = '') {
    *   'drupal_private_key' configuration variable.
    */
   protected function computeToken($seed, $value = '') {
-    return Crypt::hmacBase64($value, $seed . $this->privateKey->get() . Settings::getHashSalt());
+    return Crypt::hmacBase64($value, $seed . $this->privateKey->get() . drupal_get_hash_salt());
   }
 
 }
diff --git a/core/lib/Drupal/Core/Config/CachedStorage.php b/core/lib/Drupal/Core/Config/CachedStorage.php
index a5d11fd..9fcc12d 100644
--- a/core/lib/Drupal/Core/Config/CachedStorage.php
+++ b/core/lib/Drupal/Core/Config/CachedStorage.php
@@ -238,4 +238,22 @@ public function deleteAll($prefix = '') {
   public function resetListCache() {
     $this->findByPrefixCache = array();
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    // @todo Hmmm how to change the bin name? I guess we need to inject the
+    //   cache_factory instead of the cache object so that we can create bins on
+    //   the fly.
+    $this->storage->setCollection($collection);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections() {
+    return $this->storage->getCollections();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index 11ab691..5edb660 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -38,6 +38,13 @@ class DatabaseStorage implements StorageInterface {
   protected $options = array();
 
   /**
+   * The storage collection.
+   *
+   * @var string
+   */
+  protected $collection = '';
+
+  /**
    * Constructs a new DatabaseStorage.
    *
    * @param \Drupal\Core\Database\Connection $connection
@@ -47,10 +54,11 @@ class DatabaseStorage implements StorageInterface {
    * @param array $options
    *   (optional) Any additional database connection options to use in queries.
    */
-  public function __construct(Connection $connection, $table, array $options = array()) {
+  public function __construct(Connection $connection, $table, array $options = array(), $collection = '') {
     $this->connection = $connection;
     $this->table = $table;
     $this->options = $options;
+    $this->collection = $collection;
   }
 
   /**
@@ -75,7 +83,7 @@ public function exists($name) {
   public function read($name) {
     $data = FALSE;
     try {
-      $raw = $this->connection->query('SELECT data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name = :name', array(':name' => $name), $this->options)->fetchField();
+      $raw = $this->connection->query('SELECT data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name = :name', array(':collection' => $this->collection, ':name' => $name), $this->options)->fetchField();
       if ($raw !== FALSE) {
         $data = $this->decode($raw);
       }
@@ -93,7 +101,7 @@ public function read($name) {
   public function readMultiple(array $names) {
     $list = array();
     try {
-      $list = $this->connection->query('SELECT name, data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name IN (:names)', array(':names' => $names), $this->options)->fetchAllKeyed();
+      $list = $this->connection->query('SELECT name, data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name IN (:names)', array(':collection' => $this->collection, ':names' => $names), $this->options)->fetchAllKeyed();
       foreach ($list as &$data) {
         $data = $this->decode($data);
       }
@@ -136,7 +144,7 @@ public function write($name, array $data) {
   protected function doWrite($name, $data) {
     $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
     return (bool) $this->connection->merge($this->table, $options)
-      ->key('name', $name)
+      ->keys(array('collection', 'name'), array($this->collection, $name))
       ->fields(array('data' => $data))
       ->execute();
   }
@@ -176,8 +184,15 @@ protected static function schemaDefinition() {
     $schema = array(
       'description' => 'The base table for configuration data.',
       'fields' => array(
+        'collection' => array(
+          'description' => 'Primary Key: Config object collection.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
         'name' => array(
-          'description' => 'Primary Key: Unique config object name.',
+          'description' => 'Primary Key: Config object name.',
           'type' => 'varchar',
           'length' => 255,
           'not null' => TRUE,
@@ -190,7 +205,7 @@ protected static function schemaDefinition() {
           'size' => 'big',
         ),
       ),
-      'primary key' => array('name'),
+      'primary key' => array('collection', 'name'),
     );
     return $schema;
   }
@@ -205,6 +220,7 @@ protected static function schemaDefinition() {
   public function delete($name) {
     $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
     return (bool) $this->connection->delete($this->table, $options)
+      ->condition('collection', $this->collection)
       ->condition('name', $name)
       ->execute();
   }
@@ -220,6 +236,7 @@ public function rename($name, $new_name) {
     return (bool) $this->connection->update($this->table, $options)
       ->fields(array('name' => $new_name))
       ->condition('name', $name)
+      ->condition('collection', $this->collection)
       ->execute();
   }
 
@@ -246,7 +263,8 @@ public function decode($raw) {
    */
   public function listAll($prefix = '') {
     try {
-      return $this->connection->query('SELECT name FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name LIKE :name', array(
+      return $this->connection->query('SELECT name FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name LIKE :name', array(
+        ':collection' => $this->collection,
         ':name' => $this->connection->escapeLike($prefix) . '%',
       ), $this->options)->fetchCol();
     }
@@ -263,10 +281,27 @@ public function deleteAll($prefix = '') {
       $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
       return (bool) $this->connection->delete($this->table, $options)
         ->condition('name', $prefix . '%', 'LIKE')
+        ->condition('collection', $this->collection)
         ->execute();
     }
     catch (\Exception $e) {
       return FALSE;
     }
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    $this->collection = $collection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections() {
+    return $this->connection->query('SELECT DISTINCT collection FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection <> \'\' ORDER by collection')->fetchCol();
+  }
+
+
 }
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index 1dac0f4..88ac1e3 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -17,6 +17,13 @@
 class FileStorage implements StorageInterface {
 
   /**
+   * The storage collection.
+   *
+   * @var string
+   */
+  protected $collection;
+
+  /**
    * The filesystem path for configuration objects.
    *
    * @var string
@@ -29,8 +36,9 @@ class FileStorage implements StorageInterface {
    * @param string $directory
    *   A directory path to use for reading and writing of configuration files.
    */
-  public function __construct($directory) {
+  public function __construct($directory, $collection = NULL) {
     $this->directory = $directory;
+    $this->collection = $this->setCollection($collection);
   }
 
   /**
@@ -40,7 +48,7 @@ public function __construct($directory) {
    *   The path to the configuration file.
    */
   public function getFilePath($name) {
-    return $this->directory . '/' . $name . '.' . static::getFileExtension();
+    return $this->getCollectionDirectory() . '/' . $name . '.' . static::getFileExtension();
   }
 
   /**
@@ -57,10 +65,14 @@ public static function getFileExtension() {
    * Check if the directory exists and create it if not.
    */
   protected function ensureStorage() {
-    $success = file_prepare_directory($this->directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-    $success = $success && file_save_htaccess($this->directory, TRUE, TRUE);
+    $dir = $this->getCollectionDirectory();
+    $success = file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    // Only create .htaccess file in root driectory.
+    if ($dir == $this->directory) {
+      $success = $success && file_save_htaccess($this->directory, TRUE, TRUE);
+    }
     if (!$success) {
-      throw new StorageException("Failed to create config directory {$this->directory}");
+      throw new StorageException("Failed to create config directory {$dir}");
     }
     return $this;
   }
@@ -142,12 +154,22 @@ public function write($name, array $data) {
    */
   public function delete($name) {
     if (!$this->exists($name)) {
-      if (!file_exists($this->directory)) {
-        throw new StorageException($this->directory . '/ not found.');
+      $dir = $this->getCollectionDirectory();
+      if (!file_exists($dir)) {
+        throw new StorageException($dir . '/ not found.');
       }
       return FALSE;
     }
-    return drupal_unlink($this->getFilePath($name));
+    $success = drupal_unlink($this->getFilePath($name));
+
+    // If a collection is now empty remove the directory.
+    if ($success && !empty($this->collection)) {
+      $names = $this->listAll();
+      if (empty($names)) {
+        drupal_rmdir($this->getCollectionDirectory());
+      }
+    }
+    return $success;
   }
 
   /**
@@ -186,12 +208,13 @@ public function decode($raw) {
   public function listAll($prefix = '') {
     // glob() silently ignores the error of a non-existing search directory,
     // even with the GLOB_ERR flag.
-    if (!file_exists($this->directory)) {
+    $dir = $this->getCollectionDirectory();
+    if (!file_exists($dir)) {
       return array();
     }
     $extension = '.' . static::getFileExtension();
     // \GlobIterator on Windows requires an absolute path.
-    $files = new \GlobIterator(realpath($this->directory) . '/' . $prefix . '*' . $extension);
+    $files = new \GlobIterator(realpath($dir) . '/' . $prefix . '*' . $extension);
 
     $names = array();
     foreach ($files as $file) {
@@ -215,4 +238,54 @@ public function deleteAll($prefix = '') {
 
     return $success;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    $this->collection = $collection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections($directory = NULL) {
+    $collections = array();
+    if (!isset($directory)) {
+      $directory = $this->directory;
+    }
+    foreach (new \DirectoryIterator($directory) as $fileinfo) {
+      if ($fileinfo->isDir() && !$fileinfo->isDot()) {
+        $collection = $fileinfo->getFilename();
+        $sub_collections = $this->getCollections($directory . '/' . $collection);
+        if (empty($sub_collections)) {
+          $collections[] = $collection;
+        }
+        else {
+          foreach ($sub_collections as $sub_collection) {
+            $collections[] = $collection . '.' . $sub_collection;
+          }
+        }
+      }
+    }
+    sort($collections);
+    return $collections;
+  }
+
+  /**
+   * Gets the directory for the collection.
+   *
+   * @return string
+   *   The directory for the collection.
+   */
+  protected function getCollectionDirectory() {
+    if (isset($this->collection)) {
+      $dir = $this->directory . '/' . str_replace('.', '/', $this->collection);
+    }
+    else {
+      $dir = $this->directory;
+    }
+    return $dir;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/NullStorage.php b/core/lib/Drupal/Core/Config/NullStorage.php
index c66f718..7914bd9 100644
--- a/core/lib/Drupal/Core/Config/NullStorage.php
+++ b/core/lib/Drupal/Core/Config/NullStorage.php
@@ -92,4 +92,19 @@ public function listAll($prefix = '') {
   public function deleteAll($prefix = '') {
     return FALSE;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    // No op.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections() {
+    return array();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index 8b99784..f5c0348 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -156,4 +156,25 @@ public function listAll($prefix = '');
    */
   public function deleteAll($prefix = '');
 
+  /**
+   * Sets the collection on the storage.
+   *
+   * @param string $collection
+   *   The collection key. If not set then this is normal configuration
+   *   storage. However if set the storage needs to use it to differentiate the
+   *   collections. collections can be nested for example 'language.de'. If this
+   *   is a file system then we could create a language folder with a subfolder
+   *   named de. If this is a database table then there could be a collection
+   *   column which will store the value 'language.de'.
+   */
+  public function setCollection($collection);
+
+  /**
+   * Gets the existing collections.
+   *
+   * @return array
+   *   An array of existing collections.
+   */
+  public function getCollections();
+
 }
diff --git a/core/lib/Drupal/Core/Controller/DialogController.php b/core/lib/Drupal/Core/Controller/DialogController.php
index 08e46c2..3557cf5 100644
--- a/core/lib/Drupal/Core/Controller/DialogController.php
+++ b/core/lib/Drupal/Core/Controller/DialogController.php
@@ -93,7 +93,7 @@ public function dialog(Request $request, $_content, $modal = FALSE) {
     }
 
     $content = drupal_render($page_content);
-    $title = isset($page_content['#title']) ? $page_content['#title'] : $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
+    $title = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
     $response = new AjaxResponse();
     // Fetch any modal options passed in from data-dialog-options.
     $options = $request->request->get('dialogOptions', array());
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index fe23fb6..11c7781 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -48,7 +48,6 @@ public function register(ContainerBuilder $container) {
     $container->addScope(new Scope('request'));
     $this->registerTwig($container);
     $this->registerUuid($container);
-    $this->registerTest($container);
 
     // Add the compiler pass that lets service providers modify existing
     // service definitions. This pass must come first so that later
@@ -144,18 +143,4 @@ public static function registerUuid(ContainerBuilder $container) {
     return $uuid_class;
   }
 
-  /**
-   * Registers services and event subscribers for a site under test.
-   */
-  protected function registerTest(ContainerBuilder $container) {
-    // Do nothing if we are not in a test environment.
-    if (!drupal_valid_test_ua()) {
-      return;
-    }
-    // Add the HTTP request subscriber to Guzzle.
-    $container
-      ->register('test.http_client.request_subscriber', 'Drupal\Core\Test\EventSubscriber\HttpRequestSubscriber')
-      ->addTag('http_client_subscriber');
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Database/Query/SelectInterface.php b/core/lib/Drupal/Core/Database/Query/SelectInterface.php
index 9f6bbce..645fd78 100644
--- a/core/lib/Drupal/Core/Database/Query/SelectInterface.php
+++ b/core/lib/Drupal/Core/Database/Query/SelectInterface.php
@@ -479,14 +479,6 @@ public function isPrepared();
   public function preExecute(SelectInterface $query = NULL);
 
   /**
-   * Runs the query against the database.
-   *
-   * @return \Drupal\Core\Database\StatementInterface|null
-   *   A prepared statement, or NULL if the query is not valid.
-   */
-  public function execute();
-
-  /**
    * Helper function to build most common HAVING conditional clauses.
    *
    * This method can take a variable number of parameters. If called with two
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 1895cfd..3475ad8 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -933,7 +933,7 @@ public function createDuplicate() {
     }
 
     // Check whether the entity type supports revisions and initialize it if so.
-    if ($entity_type->isRevisionable()) {
+    if ($entity_type->hasKey('revision')) {
       $duplicate->{$entity_type->getKey('revision')}->value = NULL;
     }
 
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
index 27c8e78..1a55637 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -102,7 +102,8 @@ public function __construct(EntityTypeInterface $entity_type, Connection $databa
     // Check if the entity type supports UUIDs.
     $this->uuidKey = $this->entityType->getKey('uuid');
 
-    if ($this->entityType->isRevisionable()) {
+    // Check if the entity type supports revisions.
+    if ($this->entityType->hasKey('revision')) {
       $this->revisionKey = $this->entityType->getKey('revision');
       $this->revisionTable = $this->entityType->getRevisionTable();
     }
diff --git a/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php b/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php
index 9db0a64..aac92bc 100644
--- a/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php
+++ b/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -62,28 +61,9 @@ public static function create(ContainerInterface $container) {
    *   A render array as expected by drupal_render().
    */
   public function view(EntityInterface $_entity, $view_mode = 'full', $langcode = NULL) {
-    $page = $this->entityManager
+    return $this->entityManager
       ->getViewBuilder($_entity->getEntityTypeId())
       ->view($_entity, $view_mode, $langcode);
-
-    // If the entity's label is rendered using a field formatter, set the
-    // rendered title field formatter as the page title instead of the default
-    // plain text title. This allows attributes set on the field to propagate
-    // correctly (e.g. RDFa, in-place editing).
-    if ($_entity instanceof ContentEntityInterface) {
-      $label_field = $_entity->getEntityType()->getKey('label');
-      if ($label_field && $_entity->getFieldDefinition($label_field)->getDisplayOptions('view')) {
-        // We must render the label field, because rendering the entity may be
-        // a cache hit, in which case we can't extract the rendered label field
-        // from the $page renderable array.
-        $build = $this->entityManager->getTranslationFromContext($_entity)
-          ->get($label_field)
-          ->view($view_mode);
-        $page['#title'] = drupal_render($build, TRUE);
-      }
-    }
-
-    return $page;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index 6538647..de4411c 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -548,14 +548,6 @@ public function isTranslatable() {
   /**
    * {@inheritdoc}
    */
-  public function isRevisionable() {
-    // Entity types are revisionable if a revision key has been specified.
-    return $this->hasKey('revision');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getConfigPrefix() {
     return FALSE;
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
index a6e39aa..7706a58 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
@@ -85,8 +85,8 @@ public function getClass();
    *     property and its value must be numeric.
    *   - revision: (optional) The name of the property that contains the
    *     revision ID of the entity. The Field API assumes that all revision IDs
-   *     are unique across all entities of a type. If this entry is omitted
-   *     the entities of this type are not revisionable.
+   *     are unique across all entities of a type. This entry can be omitted if
+   *     the entities of this type are not versionable.
    *   - bundle: (optional) The name of the property that contains the bundle
    *     name for the entity. The bundle name defines which set of fields are
    *     attached to the entity (e.g. what nodes call "content type"). This
@@ -542,13 +542,6 @@ public function getBaseTable();
   public function isTranslatable();
 
   /**
-   * Indicates whether entities of this type have revision support.
-   *
-   * @return bool
-   */
-  public function isRevisionable();
-
-  /**
    * Returns the config prefix used by the configuration entity type.
    *
    * @todo Used for configuration entities only.
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 9c7f56c..8e4596f 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -7,13 +7,8 @@
 
 namespace Drupal\Core\EventSubscriber;
 
-use Drupal\Core\Config\Config;
-use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
-use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -32,23 +27,13 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
   protected $languageManager;
 
   /**
-   * A config object for the system performance configuration.
-   *
-   * @var \Drupal\Core\Config\Config
-   */
-  protected $config;
-
-  /**
    * Constructs a FinishResponseSubscriber object.
    *
    * @param LanguageManager $language_manager
    *  The LanguageManager object for retrieving the correct language code.
-   * @param \Drupal\Core\Config\ConfigFactory $config_factory
-   *   A config factory for retrieving required config objects.
    */
-  public function __construct(LanguageManager $language_manager, ConfigFactory $config_factory) {
+  public function __construct(LanguageManager $language_manager) {
     $this->languageManager = $language_manager;
-    $this->config = $config_factory->get('system.performance');
   }
 
   /**
@@ -72,148 +57,57 @@ public function onRespond(FilterResponseEvent $event) {
     // Set the Content-language header.
     $response->headers->set('Content-language', $this->languageManager->getCurrentLanguage()->id);
 
+    // Because pages are highly dynamic, set the last-modified time to now
+    // since the page is in fact being regenerated right now.
+    // @todo Remove this and use a more intelligent default so that HTTP
+    // caching can function properly.
+    $response->setLastModified(new \DateTime(gmdate(DATE_RFC1123, REQUEST_TIME)));
+
+    // Also give each page a unique ETag. This will force clients to include
+    // both an If-Modified-Since header and an If-None-Match header when doing
+    // conditional requests for the page (required by RFC 2616, section 13.3.4),
+    // making the validation more robust. This is a workaround for a bug in
+    // Mozilla Firefox that is triggered when Drupal's caching is enabled and
+    // the user accesses Drupal via an HTTP proxy (see
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=269303): When an
+    // authenticated user requests a page, and then logs out and requests the
+    // same page again, Firefox may send a conditional request based on the
+    // page that was cached locally when the user was logged in. If this page
+    // did not have an ETag header, the request only contains an
+    // If-Modified-Since header. The date will be recent, because with
+    // authenticated users the Last-Modified header always refers to the time
+    // of the request. If the user accesses Drupal via a proxy server, and the
+    // proxy already has a cached copy of the anonymous page with an older
+    // Last-Modified date, the proxy may respond with 304 Not Modified, making
+    // the client think that the anonymous and authenticated pageviews are
+    // identical.
+    // @todo Remove this line as no longer necessary per
+    //   http://drupal.org/node/1573064
+    $response->setEtag(REQUEST_TIME);
+
+    // Authenticated users are always given a 'no-cache' header, and will fetch
+    // a fresh page on every request. This prevents authenticated users from
+    // seeing locally cached pages.
+    // @todo Revisit whether or not this is still appropriate now that the
+    //   Response object does its own cache control processing and we intend to
+    //   use partial page caching more extensively.
+
     // Attach globally-declared headers to the response object so that Symfony
     // can send them for us correctly.
-    // @todo remove this once we have removed all drupal_add_http_header()
-    //   calls.
+    // @todo remove this once we have removed all drupal_add_http_header() calls
     $headers = drupal_get_http_header();
     foreach ($headers as $name => $value) {
       $response->headers->set($name, $value, FALSE);
     }
 
-    $is_cacheable = drupal_page_is_cacheable();
-
-    // Add headers necessary to specify whether the response should be cached by
-    // proxies and/or the browser.
-    if ($is_cacheable && $this->config->get('cache.page.max_age') > 0) {
-      if (!$this->isCacheControlCustomized($response)) {
-        $this->setResponseCacheable($response, $request);
-      }
+    $max_age = \Drupal::config('system.performance')->get('cache.page.max_age');
+    if ($max_age > 0 && ($cache = drupal_page_set_cache($response, $request))) {
+      drupal_serve_page_from_cache($cache, $response, $request);
     }
     else {
-      $this->setResponseNotCacheable($response, $request);
+      $response->setExpires(\DateTime::createFromFormat('j-M-Y H:i:s T', '19-Nov-1978 05:00:00 GMT'));
+      $response->headers->set('Cache-Control', 'no-cache, must-revalidate, post-check=0, pre-check=0');
     }
-
-    // Store the response in the internal page cache.
-    if ($is_cacheable && $this->config->get('cache.page.use_internal')) {
-      drupal_page_set_cache($response, $request);
-      $response->headers->set('X-Drupal-Cache', 'MISS');
-      drupal_serve_page_from_cache($response, $request);
-    }
-  }
-
-  /**
-   * Determine whether the given response has a custom Cache-Control header.
-   *
-   * Upon construction, the ResponseHeaderBag is initialized with an empty
-   * Cache-Control header. Consequently it is not possible to check whether the
-   * header was set explicitly by simply checking its presence. Instead, it is
-   * necessary to examine the computed Cache-Control header and compare with
-   * values known to be present only when Cache-Control was never set
-   * explicitly.
-   *
-   * When neither Cache-Control nor any of the ETag, Last-Modified, Expires
-   * headers are set on the response, ::get('Cache-Control') returns the value
-   * 'no-cache'. If any of ETag, Last-Modified or Expires are set but not
-   * Cache-Control, then 'private, must-revalidate' (in exactly this order) is
-   * returned.
-   *
-   * @see \Symfony\Component\HttpFoundation\ResponseHeaderBag::computeCacheControlValue()
-   *
-   * @param \Symfony\Component\HttpFoundation\Response $response
-   *
-   * @return bool
-   *   TRUE when Cache-Control header was set explicitely on the given response.
-   */
-  protected function isCacheControlCustomized(Response $response) {
-    $cache_control = $response->headers->get('Cache-Control');
-    return $cache_control != 'no-cache' && $cache_control != 'private, must-revalidate';
-  }
-
-  /**
-   * Add Cache-Control and Expires headers to a response which is not cacheable.
-   *
-   * @param \Symfony\Component\HttpFoundation\Response $response
-   *   A response object.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A request object.
-   */
-  protected function setResponseNotCacheable(Response $response, Request $request) {
-    $this->setCacheControlNoCache($response);
-    $this->setExpiresNoCache($response);
-
-    // There is no point in sending along headers necessary for cache
-    // revalidation, if caching by proxies and browsers is denied in the first
-    // place. Therefore remove ETag, Last-Modified and Vary in that case.
-    $response->setEtag(NULL);
-    $response->setLastModified(NULL);
-    $response->setVary(NULL);
-  }
-
-  /**
-   * Add Cache-Control and Expires headers to a cacheable response.
-   *
-   * @param \Symfony\Component\HttpFoundation\Response $response
-   *   A response object.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A request object.
-   */
-  protected function setResponseCacheable(Response $response, Request $request) {
-    // HTTP/1.0 proxies do not support the Vary header, so prevent any caching
-    // by sending an Expires date in the past. HTTP/1.1 clients ignore the
-    // Expires header if a Cache-Control: max-age directive is specified (see
-    // RFC 2616, section 14.9.3).
-    if (!$response->headers->has('Expires')) {
-      $this->setExpiresNoCache($response);
-    }
-
-    $max_age = $this->config->get('cache.page.max_age');
-    $response->headers->set('Cache-Control', 'public, max-age=' . $max_age);
-
-    // In order to support HTTP cache-revalidation, ensure that there is a
-    // Last-Modified and an ETag header on the response.
-    if (!$response->headers->has('Last-Modified')) {
-      $timestamp = REQUEST_TIME;
-      $response->setLastModified(new \DateTime(gmdate(DATE_RFC1123, REQUEST_TIME)));
-    }
-    else {
-      $timestamp = $response->getLastModified()->getTimestamp();
-    }
-    $response->setEtag($timestamp);
-
-    // Allow HTTP proxies to cache pages for anonymous users without a session
-    // cookie. The Vary header is used to indicates the set of request-header
-    // fields that fully determines whether a cache is permitted to use the
-    // response to reply to a subsequent request for a given URL without
-    // revalidation.
-    if (!$response->hasVary() && !Settings::get('omit_vary_cookie')) {
-      $response->setVary('Cookie', FALSE);
-    }
-  }
-
-  /**
-   * Disable caching in the browser and for HTTP/1.1 proxies and clients.
-   *
-   * @param \Symfony\Component\HttpFoundation\Response $response
-   *   A response object.
-   */
-  protected function setCacheControlNoCache(Response $response) {
-    $response->headers->set('Cache-Control', 'no-cache, must-revalidate, post-check=0, pre-check=0');
-  }
-
-  /**
-   * Disable caching in ancient browsers and for HTTP/1.0 proxies and clients.
-   *
-   * HTTP/1.0 proxies do not support the Vary header, so prevent any caching by
-   * sending an Expires date in the past. HTTP/1.1 clients ignore the Expires
-   * header if a Cache-Control: max-age= directive is specified (see RFC 2616,
-   * section 14.9.3).
-   *
-   * @param \Symfony\Component\HttpFoundation\Response $response
-   *   A response object.
-   */
-  protected function setExpiresNoCache(Response $response) {
-    $response->setExpires(\DateTime::createFromFormat('j-M-Y H:i:s T', '19-Nov-1978 05:00:00 GMT'));
   }
 
   /**
@@ -222,7 +116,7 @@ protected function setExpiresNoCache(Response $response) {
    * @return array
    *   An array of event listener definitions.
    */
-  public static function getSubscribedEvents() {
+  static function getSubscribedEvents() {
     $events[KernelEvents::RESPONSE][] = array('onRespond');
     return $events;
   }
diff --git a/core/lib/Drupal/Core/Test/EventSubscriber/HttpRequestSubscriber.php b/core/lib/Drupal/Core/Http/Plugin/SimpletestHttpRequestSubscriber.php
similarity index 72%
rename from core/lib/Drupal/Core/Test/EventSubscriber/HttpRequestSubscriber.php
rename to core/lib/Drupal/Core/Http/Plugin/SimpletestHttpRequestSubscriber.php
index 776f2c1..825588c 100644
--- a/core/lib/Drupal/Core/Test/EventSubscriber/HttpRequestSubscriber.php
+++ b/core/lib/Drupal/Core/Http/Plugin/SimpletestHttpRequestSubscriber.php
@@ -2,25 +2,26 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Test\EventSubscriber\HttpRequestSubscriber.
+ * Contains Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber
  */
 
-namespace Drupal\Core\Test\EventSubscriber;
+namespace Drupal\Core\Http\Plugin;
 
 use GuzzleHttp\Event\BeforeEvent;
 use GuzzleHttp\Event\SubscriberInterface;
 
 /**
- * Overrides the User-Agent HTTP header for outbound HTTP requests.
+ * Subscribe to HTTP requests and override the User-Agent header if the request
+ * is being dispatched from inside a simpletest.
  */
-class HttpRequestSubscriber implements SubscriberInterface {
+class SimpletestHttpRequestSubscriber implements SubscriberInterface {
 
   /**
    * {@inheritdoc}
    */
   public function getEvents() {
     return array(
-      'before' => array('onBeforeSendRequest'),
+      'before'   => array('onBeforeSendRequest'),
     );
   }
 
@@ -38,5 +39,4 @@ public function onBeforeSendRequest(BeforeEvent $event) {
       $event->getRequest()->setHeader('User-Agent', drupal_generate_test_ua($test_prefix));
     }
   }
-
 }
diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index 3ac0f03..fe2260d 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -80,24 +80,4 @@ public static function getAll() {
     return self::$instance->storage;
   }
 
-  /**
-   * Gets a salt useful for hardening against SQL injection.
-   *
-   * @return string
-   *   A salt based on information in settings.php, not in the database.
-   *
-   * @throws \RuntimeException
-   */
-  public static function getHashSalt() {
-    $hash_salt = self::$instance->get('hash_salt');
-    // This should never happen, as it breaks user logins and many other
-    // services. Therefore, explicitly notify the user (developer) by throwing
-    // an exception.
-    if (empty($hash_salt)) {
-      throw new \RuntimeException('Missing $settings[\'hash_salt\'] in settings.php.');
-    }
-
-    return $hash_salt;
-  }
-
 }
diff --git a/core/misc/states.js b/core/misc/states.js
index 530f03e..701d6fc 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -522,12 +522,12 @@
       if (e.value) {
         var $label = $(e.target).attr({ 'required': 'required', 'aria-required': 'aria-required' }).closest('.form-item, .form-wrapper').find('label');
         // Avoids duplicate required markers on initialization.
-        if (!$label.hasClass('form-required').length) {
-          $label.addClass('form-required');
+        if (!$label.find('.form-required').length) {
+          $label.append(Drupal.theme('requiredMarker'));
         }
       }
       else {
-        $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label.form-required').removeClass('form-required');
+        $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label .form-required').remove();
       }
     }
   });
@@ -573,4 +573,10 @@
     return (a === b) ? (typeof a === 'undefined' ? a : true) : (typeof a === 'undefined' || typeof b === 'undefined');
   }
 
+  $.extend(Drupal.theme, {
+    requiredMarker: function () {
+      return '<abbr class="form-required" title="' + Drupal.t('This field is required.') + '">*</abbr>';
+    }
+  });
+
 })(jQuery);
diff --git a/core/modules/block/lib/Drupal/block/Controller/CategoryAutocompleteController.php b/core/modules/block/lib/Drupal/block/Controller/CategoryAutocompleteController.php
index 0c35e82..1b61147 100644
--- a/core/modules/block/lib/Drupal/block/Controller/CategoryAutocompleteController.php
+++ b/core/modules/block/lib/Drupal/block/Controller/CategoryAutocompleteController.php
@@ -59,7 +59,7 @@ public function autocomplete(Request $request) {
     $matches = array();
     foreach ($this->blockManager->getCategories() as $category) {
       if (stripos($category, $typed_category) === 0) {
-        $matches[] = array('value' => $category, 'label' => String::checkPlain($category));
+        $matches[$category] = String::checkPlain($category);
       }
     }
     return new JsonResponse($matches);
diff --git a/core/modules/block/tests/Drupal/block/Tests/CategoryAutocompleteTest.php b/core/modules/block/tests/Drupal/block/Tests/CategoryAutocompleteTest.php
index 26bd6b9..29d75d0 100644
--- a/core/modules/block/tests/Drupal/block/Tests/CategoryAutocompleteTest.php
+++ b/core/modules/block/tests/Drupal/block/Tests/CategoryAutocompleteTest.php
@@ -59,8 +59,8 @@ public function setUp() {
    */
   public function testAutocompleteSuggestions($string, $suggestions) {
     $suggestions = array_map(function ($suggestion) {
-      return array('value' => $suggestion, 'label' => String::checkPlain($suggestion));
-    }, $suggestions);
+      return String::checkPlain($suggestion);
+    }, array_combine($suggestions, $suggestions));
     $result = $this->autocompleteController->autocomplete(new Request(array('q' => $string)));
     $this->assertSame($suggestions, json_decode($result->getContent(), TRUE));
   }
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index 6ecf036..5ac6340 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -404,7 +404,7 @@ function color_scheme_form_submit($form, &$form_state) {
 
   // Prepare target locations for generated files.
   $id = $theme . '-' . substr(hash('sha256', serialize($palette) . microtime()), 0, 8);
-  $paths['color'] = 'public://color';
+  $paths['color'] = file_default_scheme() . '://color';
   $paths['target'] = $paths['color'] . '/' . $id;
   foreach ($paths as $path) {
     file_prepare_directory($path, FILE_CREATE_DIRECTORY);
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php
index 037640a..abf18c7 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php
@@ -7,14 +7,13 @@
 
 namespace Drupal\comment\Tests;
 
-use Drupal\Core\Session\UserSession;
 use Drupal\comment\CommentInterface;
-use Drupal\system\Tests\Entity\EntityUnitTestBase;
+use Drupal\simpletest\WebTestBase;
 
 /**
  * Tests CommentDefaultFormatter's cache tag bubbling.
  */
-class CommentDefaultFormatterCacheTagsTest extends EntityUnitTestBase {
+class CommentDefaultFormatterCacheTagsTest extends WebTestBase {
 
   /**
    * Modules to enable.
@@ -40,18 +39,9 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
 
-    // Set the current user to one that can access comments. Specifically, this
-    // user does not have access to the 'administer comments' permission, to
-    // ensure only published comments are visible to the end user.
-    $this->container->set('current_user', $this->createUser(array(), array('access comments')));
-
-    // Install tables and config needed to render comments.
-    $this->installSchema('comment', array('comment', 'comment_entity_statistics'));
-    $this->installConfig(array('system', 'filter'));
-
-    // Comment rendering generates links, so build the router.
-    $this->installSchema('system', array('router'));
-    $this->container->get('router.builder')->rebuild();
+    $this->drupalLogin($this->drupalCreateUser(array(
+      'access comments',
+    )));
 
     // Set up a field, so that the entity that'll be referenced bubbles up a
     // cache tag when rendering it entirely.
@@ -95,10 +85,7 @@ public function testCacheTags() {
     );
     $this->assertEqual($build['#cache']['tags'], $expected_cache_tags, 'The test entity has the expected cache tags before it has comments.');
 
-    // Create a comment on that entity. Comment loading requires that the uid
-    // also exists in the {users} table.
-    $user = $this->createUser();
-    $user->save();
+    // Create a comment on that entity..
     $comment = entity_create('comment', array(
       'subject' => 'Llama',
       'comment_body' => array(
@@ -109,7 +96,6 @@ public function testCacheTags() {
       'entity_type' => 'entity_test',
       'field_name' => 'comment',
       'status' => CommentInterface::PUBLISHED,
-      'uid' => $user->id(),
     ));
     $comment->save();
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php
index ac77a58..21ee6c5 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php
@@ -42,7 +42,6 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'config_snapshot');
     $this->installSchema('node', 'node');
 
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php
index a538c12..f2ca9aa 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php
@@ -51,7 +51,6 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'config_snapshot');
     $this->installSchema('node', 'node');
 
     // Set up the ConfigImporter object for testing.
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
index 341d3d4..b3c1633 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
@@ -43,8 +43,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'config_snapshot');
-
     $this->installConfig(array('config_test'));
     // Installing config_test's default configuration pollutes the global
     // variable being used for recording hook invocations by this test already,
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php
index 7c6c1cb..7359a35 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php
@@ -31,7 +31,6 @@ public static function getInfo() {
 
   public function setUp() {
     parent::setUp();
-    $this->installSchema('system', 'config_snapshot');
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
   }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php
index 295ff74..a0b3ecc 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php
@@ -32,7 +32,6 @@ public static function getInfo() {
 
   public function setUp() {
     parent::setUp();
-    $this->installSchema('system', 'config_snapshot');
     // Update the config snapshot. This allows the parent::setUp() to write
     // configuration files.
     \Drupal::service('config.manager')->createSnapshot(\Drupal::service('config.storage'), \Drupal::service('config.storage.snapshot'));
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
index 925ecbd..1923cce 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
@@ -24,6 +24,11 @@
 abstract class ConfigStorageTestBase extends DrupalUnitTestBase {
 
   /**
+   * @var \Drupal\Core\Config\StorageInterface;
+   */
+  protected $storage;
+
+  /**
    * Tests storage CRUD operations.
    *
    * @todo Coverage: Trigger PDOExceptions / Database exceptions.
@@ -180,4 +185,57 @@ function testDataTypes() {
   abstract protected function update($name, $data);
 
   abstract protected function delete($name);
+
+  public function testCollection() {
+    $name = 'config_test.storage';
+    $data = array('foo => bar');
+    $result = $this->storage->write($name, $data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($data, $this->storage->read($name));
+
+    // Create configuration in a new collection.
+    $this->storage->setCollection('collection.new');
+    $this->storage->write($name, $data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($data, $this->storage->read($name));
+    $new_data = array('foo' => 'baz');
+    $this->storage->write($name, $new_data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($new_data, $this->storage->read($name));
+
+    // Create configuration in another collection.
+    $this->storage->setCollection('collection.another');
+    $this->storage->write($name, $new_data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($new_data, $this->storage->read($name));
+
+    // Create configuration in yet another collection.
+    $this->storage->setCollection('alternate');
+    $this->storage->write($name, $new_data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($new_data, $this->storage->read($name));
+
+    // Switch back to the collection-less mode and check the data still exists
+    // add has not been touched.
+    $this->storage->setCollection('');
+    $this->assertIdentical($data, $this->storage->read($name));
+
+    // Check that the getCollections() method works.
+    $this->assertIdentical(array('alternate', 'collection.another', 'collection.new'), $this->storage->getCollections());
+
+    // Check that the collections are removed when they are empty.
+    $this->storage->setCollection('alternate');
+    $this->storage->delete($name);
+    $this->assertIdentical(array('collection.another', 'collection.new'), $this->storage->getCollections());
+
+    // Check that the having an empty collection-less storage does not break
+    // anything.
+    $this->storage->setCollection('');
+    // Before deleting check that the previous delete did not affect data in
+    // another collection.
+    $this->assertIdentical($data, $this->storage->read($name));
+    $this->storage->delete($name);
+    $this->assertIdentical(array('collection.another', 'collection.new'), $this->storage->getCollections());
+  }
+
 }
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index 3d13b7b..c8dd4d1 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -226,6 +226,13 @@ function template_preprocess_datetime_form(&$variables) {
 function template_preprocess_datetime_wrapper(&$variables) {
   $element = $variables['element'];
 
+  // If the element is required, a required marker is appended to the label.
+  $form_required_marker = array(
+    '#theme' => 'form_required_marker',
+    '#element' => $element,
+  );
+  $variables['required'] = !empty($element['#required']) ? drupal_render($form_required_marker) : '';
+
   if (!empty($element['#title'])) {
     $variables['title'] = $element['#title'];
   }
@@ -234,13 +241,6 @@ function template_preprocess_datetime_wrapper(&$variables) {
     $variables['description'] = $element['#description'];
   }
 
-  $title_attributes = array('class' => array('label'));
-  // For required datetime fields a 'form-required' class is appended to the
-  // label attributes.
-  if (!empty($element['#required'])) {
-    $title_attributes['class'][] = 'form-required';
-  }
-  $variables['title_attributes'] = new Attribute($title_attributes);
   $variables['content'] = $element['#children'];
 }
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php
index d8c976a..0302c72 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php
@@ -98,7 +98,7 @@ function testDateField() {
     // Display creation form.
     $this->drupalGet('entity_test/add');
     $this->assertFieldByName("{$field_name}[0][value][date]", '', 'Date element found.');
-    $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "form-required")]', TRUE, 'Required markup found');
+    $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4/span', '*', 'Required markup found');
     $this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Time element not found.');
 
     // Submit a valid date and ensure it is accepted.
diff --git a/core/modules/datetime/templates/datetime-wrapper.html.twig b/core/modules/datetime/templates/datetime-wrapper.html.twig
index 5660cf5..a4acf70 100644
--- a/core/modules/datetime/templates/datetime-wrapper.html.twig
+++ b/core/modules/datetime/templates/datetime-wrapper.html.twig
@@ -6,7 +6,8 @@
  * Available variables:
  * - content: The form element to be output, usually a datelist, or datetime.
  * - title: The title of the form element.
- * - title_attributes: HTML attributes for the title wrapper.
+ * - attributes: HTML attributes for the form wrapper.
+ * - required: (optional) A marker indicating that the form element is required.
  * - description: Description text for the form element.
  *
  * @see template_preprocess_datetime_wrapper()
@@ -15,7 +16,9 @@
  */
 #}
 {% if title %}
-  <h4{{ title_attributes }}>{{ title }}</h4>
+  <h4 class="label">
+    {% trans %}{{ title|passthrough }}{{ required|passthrough }}{% endtrans %}
+  </h4>
 {% endif %}
 {{ content }}
 {% if description %}
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
index 6bda3f2..31ea4e8 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
@@ -42,10 +42,9 @@ public function testEntityDisplayCRUD() {
     $expected = array();
 
     // Check that providing no 'weight' results in the highest current weight
-    // being assigned. The 'name' field's formatter has weight -5, therefore
-    // these follow.
-    $expected['component_1'] = array('weight' => -4);
-    $expected['component_2'] = array('weight' => -3);
+    // being assigned.
+    $expected['component_1'] = array('weight' => 0);
+    $expected['component_2'] = array('weight' => 1);
     $display->setComponent('component_1');
     $display->setComponent('component_2');
     $this->assertEqual($display->getComponent('component_1'), $expected['component_1']);
@@ -64,12 +63,6 @@ public function testEntityDisplayCRUD() {
     }
 
     // Check that getComponents() returns options for all components.
-    $expected['name'] = array(
-      'label' => 'hidden',
-      'type' => 'string',
-      'weight' => -5,
-      'settings' => array(),
-    );
     $this->assertEqual($display->getComponents(), $expected);
 
     // Check that a component can be removed.
@@ -171,7 +164,7 @@ public function testFieldComponent() {
     $default_formatter = $field_type_info['default_formatter'];
     $formatter_settings =  \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings($default_formatter);
     $expected = array(
-      'weight' => -4,
+      'weight' => 0,
       'label' => 'above',
       'type' => $default_formatter,
       'settings' => $formatter_settings,
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFormatterTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFormatterTest.php
index abbd3c4..478c506 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFormatterTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFormatterTest.php
@@ -171,12 +171,6 @@ public function testEntityFormatter() {
     $items = $referencing_entity->get($field_name);
     $build = $items->view(array('type' => $formatter));
 
-    $expected_rendered_name_field = '<div class="field field-entity-test--name field-name-name field-type-string field-label-hidden">
-    <div class="field-items">
-          <div class="field-item">' . $this->referencedEntity->label() . '</div>
-      </div>
-</div>
-';
     $expected_rendered_body_field = '<div class="field field-entity-test--body field-name-body field-type-text field-label-above">
       <div class="field-label">Body:&nbsp;</div>
     <div class="field-items">
@@ -184,7 +178,7 @@ public function testEntityFormatter() {
       </div>
 </div>
 ';
-    $this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() .  $expected_rendered_name_field . $expected_rendered_body_field, format_string('The markup returned by the @formatter formatter is correct.', array('@formatter' => $formatter)));
+    $this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() .  $expected_rendered_body_field, format_string('The markup returned by the @formatter formatter is correct.', array('@formatter' => $formatter)));
     $expected_cache_tags = array(
       $this->entityType . '_view' => TRUE,
       $this->entityType => array($this->referencedEntity->id() => $this->referencedEntity->id()),
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
index 5f77d92..5717a23 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
@@ -37,7 +37,7 @@
   function setUp() {
     parent::setUp();
     $this->installSchema('entity_test', 'entity_test');
-    $this->installSchema('system', array('sequences', 'config_snapshot'));
+    $this->installSchema('system', array('sequences'));
     $this->installSchema('user', array('users', 'users_roles'));
 
     // Set default storage backend and configure the theme system.
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php
index d446643..a59dd51 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\menu_link\Entity;
 
-use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Entity\Entity;
@@ -454,13 +453,20 @@ public static function preDelete(EntityStorageInterface $storage, array $entitie
   public static function postDelete(EntityStorageInterface $storage, array $entities) {
     parent::postDelete($storage, $entities);
 
+    $affected_menus = array();
     // Update the has_children status of the parent.
     foreach ($entities as $entity) {
       if (!$storage->getPreventReparenting()) {
         $storage->updateParentalStatus($entity);
       }
+
+      // Store all menu names for which we need to clear the cache.
+      if (!isset($affected_menus[$entity->menu_name])) {
+        $affected_menus[$entity->menu_name] = $entity->menu_name;
+      }
     }
 
+    Cache::invalidateTags(array('menu' => array_keys($affected_menus)));
     // Also clear the menu system static caches.
     menu_reset_static_cache();
     _menu_clear_page_cache();
@@ -537,22 +543,10 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
     // Check the has_children status of the parent.
     $storage->updateParentalStatus($this);
 
-
-    // Entity::postSave() calls Entity::invalidateTagsOnSave(), which only
-    // handles the regular cases. The MenuLink entity has two special cases.
-    $cache_tags = array();
-    // Case 1: a newly created menu link is *also* added to a menu, so we must
-    // invalidate the associated menu's cache tag.
-    if (!$update) {
-      $cache_tags = $this->getCacheTag();
-    }
-    // Case 2: a menu link may be moved from one menu to another; the original
-    // menu's cache tag must also be invalidated.
+    Cache::invalidateTags(array('menu' => $this->menu_name));
     if (isset($this->original) && $this->menu_name != $this->original->menu_name) {
-      $cache_tags = NestedArray::mergeDeep($cache_tags, $this->original->getCacheTag());
+      Cache::invalidateTags(array('menu' => $this->original->menu_name));
     }
-    Cache::invalidateTags($cache_tags);
-
     // Also clear the menu system static caches.
     menu_reset_static_cache();
 
@@ -663,18 +657,4 @@ public function build() {
     return $build;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheTag() {
-    return entity_load('menu', $this->menu_name)->getCacheTag();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getListCacheTags() {
-    return entity_load('menu', $this->menu_name)->getListCacheTags();
-  }
-
 }
diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php
index ccc3037..b16b93d 100644
--- a/core/modules/node/lib/Drupal/node/Controller/NodeController.php
+++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php
@@ -9,7 +9,6 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Controller\ControllerBase;
-use Drupal\node\Controller\NodeViewController;
 use Drupal\node\NodeTypeInterface;
 use Drupal\node\NodeInterface;
 
@@ -89,9 +88,9 @@ public function add(NodeTypeInterface $node_type) {
    */
   public function revisionShow($node_revision) {
     $node = $this->entityManager()->getStorage('node')->loadRevision($node_revision);
-    $node_view_controller = new NodeViewController($this->entityManager);
-    $page = $node_view_controller->view($node);
+    $page = $this->buildPage($node);
     unset($page['nodes'][$node->id()]['#cache']);
+
     return $page;
   }
 
@@ -118,6 +117,67 @@ public function revisionOverview(NodeInterface $node) {
   }
 
   /**
+   * Displays a node.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node we are displaying.
+   *
+   * @return array
+   *   An array suitable for drupal_render().
+   */
+  public function page(NodeInterface $node) {
+    $build = $this->buildPage($node);
+
+    foreach ($node->uriRelationships() as $rel) {
+      // Set the node path as the canonical URL to prevent duplicate content.
+      $build['#attached']['drupal_add_html_head_link'][] = array(
+        array(
+        'rel' => $rel,
+        'href' => $node->url($rel),
+        )
+        , TRUE);
+
+      if ($rel == 'canonical') {
+        // Set the non-aliased canonical path as a default shortlink.
+        $build['#attached']['drupal_add_html_head_link'][] = array(
+          array(
+            'rel' => 'shortlink',
+            'href' => $node->url($rel, array('alias' => TRUE)),
+          )
+        , TRUE);
+      }
+    }
+
+    return $build;
+  }
+
+  /**
+   * The _title_callback for the node.view route.
+   *
+   * @param NodeInterface $node
+   *   The current node.
+   *
+   * @return string
+   *   The page title.
+   */
+  public function pageTitle(NodeInterface $node) {
+    return String::checkPlain($this->entityManager()->getTranslationFromContext($node)->label());
+  }
+
+  /**
+   * Builds a node page render array.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node we are displaying.
+   *
+   * @return array
+   *   An array suitable for drupal_render().
+   */
+  protected function buildPage(NodeInterface $node) {
+    return array('nodes' => $this->entityManager()->getViewBuilder('node')->view($node));
+  }
+
+  /**
    * The _title_callback for the node.add route.
    *
    * @param \Drupal\node\NodeTypeInterface $node_type
diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeViewController.php b/core/modules/node/lib/Drupal/node/Controller/NodeViewController.php
deleted file mode 100644
index afdb085..0000000
--- a/core/modules/node/lib/Drupal/node/Controller/NodeViewController.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\node\Controller\NodeViewController.
- */
-
-namespace Drupal\node\Controller;
-
-use Drupal\Component\Utility\String;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\Controller\EntityViewController;
-
-/**
- * Defines a controller to render a single node.
- */
-class NodeViewController extends EntityViewController {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function view(EntityInterface $node, $view_mode = 'full', $langcode = NULL) {
-    $build = array('nodes' => parent::view($node));
-
-    $build['#title'] = $build['nodes']['#title'];
-    unset($build['nodes']['#title']);
-
-    foreach ($node->uriRelationships() as $rel) {
-      // Set the node path as the canonical URL to prevent duplicate content.
-      $build['#attached']['drupal_add_html_head_link'][] = array(
-        array(
-        'rel' => $rel,
-        'href' => $node->url($rel),
-        )
-        , TRUE);
-
-      if ($rel == 'canonical') {
-        // Set the non-aliased canonical path as a default shortlink.
-        $build['#attached']['drupal_add_html_head_link'][] = array(
-          array(
-            'rel' => 'shortlink',
-            'href' => $node->url($rel, array('alias' => TRUE)),
-          )
-        , TRUE);
-      }
-    }
-
-    return $build;
-  }
-
-  /**
-   * The _title_callback for the page that renders a single node.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $node
-   *   The current node.
-   *
-   * @return string
-   *   The page title.
-   */
-  public function title(EntityInterface $node) {
-    return String::checkPlain($this->entityManager->getTranslationFromContext($node)->label());
-  }
-
-}
diff --git a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php
index bdd2b92..f848870 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php
@@ -26,9 +26,6 @@ class NodeImportChangeTest extends DrupalUnitTestBase {
    */
   public function setUp() {
     parent::setUp();
-
-    $this->installSchema('system', array('config_snapshot'));
-
     // Set default storage backend.
     $this->installConfig(array('field', 'node_test_config'));
   }
diff --git a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
index 1d59ca1..cbc2920 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
@@ -26,8 +26,6 @@ class NodeImportCreateTest extends DrupalUnitTestBase {
    */
   public function setUp() {
     parent::setUp();
-
-    $this->installSchema('system', array('config_snapshot'));
     $this->installSchema('user', array('users'));
 
     // Set default storage backend.
diff --git a/core/modules/node/node.routing.yml b/core/modules/node/node.routing.yml
index 03ce347..e7ba52d 100644
--- a/core/modules/node/node.routing.yml
+++ b/core/modules/node/node.routing.yml
@@ -47,8 +47,8 @@ node.add:
 node.view:
   path: '/node/{node}'
   defaults:
-    _content: '\Drupal\node\Controller\NodeViewController::view'
-    _title_callback: '\Drupal\node\Controller\NodeViewController::title'
+    _content: '\Drupal\node\Controller\NodeController::page'
+    _title_callback: '\Drupal\node\Controller\NodeController::pageTitle'
   requirements:
     _entity_access: 'node.view'
 
diff --git a/core/modules/quickedit/js/views/EntityToolbarView.js b/core/modules/quickedit/js/views/EntityToolbarView.js
index 0cd7f0d..c9abd94 100644
--- a/core/modules/quickedit/js/views/EntityToolbarView.js
+++ b/core/modules/quickedit/js/views/EntityToolbarView.js
@@ -203,19 +203,9 @@
             delay = 250;
             break;
           default:
-            var fieldModels = this.model.get('fields').models;
-            var topMostPosition = 1000000;
-            var topMostField = null;
-            // Position against the topmost field.
-            for (var i = 0; i < fieldModels.length; i++) {
-              var pos = fieldModels[i].get('el').getBoundingClientRect().top;
-              if (pos < topMostPosition) {
-                topMostPosition = pos;
-                topMostField = fieldModels[i];
-              }
-            }
-            of = topMostField.get('el');
-            delay = 50;
+            // Position against the entity, or as a last resort, the body element.
+            of = this.$entity || 'body';
+            delay = 750;
             break;
         }
         // Prepare to check the next possible element to position against.
diff --git a/core/modules/quickedit/lib/Drupal/quickedit/Tests/QuickEditLoadingTest.php b/core/modules/quickedit/lib/Drupal/quickedit/Tests/QuickEditLoadingTest.php
index b5122dd..67835e0 100644
--- a/core/modules/quickedit/lib/Drupal/quickedit/Tests/QuickEditLoadingTest.php
+++ b/core/modules/quickedit/lib/Drupal/quickedit/Tests/QuickEditLoadingTest.php
@@ -298,11 +298,6 @@ public function testTitleBaseField() {
     $this->drupalLogin($this->editor_user);
     $this->drupalGet('node/1');
 
-    // Ensure that the full page title is actually in-place editable
-    $node = entity_load('node', 1);
-    $elements = $this->xpath('//h1/span[@data-quickedit-field-id="node/1/title/und/full" and normalize-space(text())=:title]', array(':title' => $node->label()));
-    $this->assertTrue(!empty($elements), 'Title with data-quickedit-field-id attribute found.');
-
     // Retrieving the metadata should result in a 200 JSON response.
     $htmlPageDrupalSettings = $this->drupalSettings;
     $post = array('fields[0]' => 'node/1/title/und/full');
diff --git a/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php b/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php
index 6c2793d..abe8c07 100644
--- a/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php
+++ b/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\rdf\Tests\RdfMappingConfigEntityUnitTest.
+ * Contains \Drupal\rdf\Tests\RdfMappingEntityUnitTest.
  */
 
 namespace Drupal\rdf\Tests;
@@ -17,7 +17,7 @@
  * @group Drupal
  * @group Config
  */
-class RdfMappingConfigEntityUnitTest extends UnitTestCase {
+class RdfMappingEntityUnitTest extends UnitTestCase {
 
   /**
    * The entity type used for testing.
diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchCommentCountToggleTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchCommentCountToggleTest.php
index 64c1171..adfb110 100644
--- a/core/modules/search/lib/Drupal/search/Tests/SearchCommentCountToggleTest.php
+++ b/core/modules/search/lib/Drupal/search/Tests/SearchCommentCountToggleTest.php
@@ -26,7 +26,10 @@ class SearchCommentCountToggleTest extends SearchTestBase {
    *
    * @var array
    */
-  public static $modules = array('node', 'comment');
+  public static $modules = array('comment');
+
+  // Requires node types, comment config, filter formats.
+  protected $profile = 'standard';
 
   protected $searching_user;
   protected $searchable_nodes;
@@ -43,7 +46,7 @@ function setUp() {
     parent::setUp();
 
     // Create searching user.
-    $this->searching_user = $this->drupalCreateUser(array('search content', 'access content', 'access comments', 'post comments', 'skip comment approval'));
+    $this->searching_user = $this->drupalCreateUser(array('search content', 'access content', 'access comments', 'skip comment approval'));
 
     // Login with sufficient privileges.
     $this->drupalLogin($this->searching_user);
@@ -81,10 +84,9 @@ function testSearchCommentCountToggle() {
     $edit = array(
       'keys' => "'SearchCommentToggleTestCase'",
     );
-    $this->drupalGet('search/node');
 
     // Test comment count display for nodes with comment status set to Open
-    $this->drupalPostForm(NULL, $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
     $this->assertText(t('0 comments'), 'Empty comment count displays for nodes with comment status set to Open');
     $this->assertText(t('1 comment'), 'Non-empty comment count displays for nodes with comment status set to Open');
 
@@ -94,7 +96,7 @@ function testSearchCommentCountToggle() {
     $this->searchable_nodes['1 comment']->set('comment', CommentItemInterface::CLOSED);
     $this->searchable_nodes['1 comment']->save();
 
-    $this->drupalPostForm(NULL, $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
     $this->assertNoText(t('0 comments'), 'Empty comment count does not display for nodes with comment status set to Closed');
     $this->assertText(t('1 comment'), 'Non-empty comment count displays for nodes with comment status set to Closed');
 
@@ -104,7 +106,7 @@ function testSearchCommentCountToggle() {
     $this->searchable_nodes['1 comment']->set('comment', CommentItemInterface::HIDDEN);
     $this->searchable_nodes['1 comment']->save();
 
-    $this->drupalPostForm(NULL, $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
     $this->assertNoText(t('0 comments'), 'Empty comment count does not display for nodes with comment status set to Hidden');
     $this->assertNoText(t('1 comment'), 'Non-empty comment count does not display for nodes with comment status set to Hidden');
   }
diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php
index 00e7253..2957d11 100644
--- a/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php
+++ b/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php
@@ -20,7 +20,9 @@ class SearchCommentTest extends SearchTestBase {
    *
    * @var array
    */
-  public static $modules = array('filter', 'node', 'comment');
+  public static $modules = array('comment');
+
+  protected $profile = 'standard';
 
   protected $admin_user;
 
@@ -35,22 +37,14 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $full_html_format = entity_create('filter_format', array(
-      'format' => 'full_html',
-      'name' => 'Full HTML',
-      'weight' => 1,
-      'filters' => array(),
-    ));
-    $full_html_format->save();
-
     // Create and log in an administrative user having access to the Full HTML
     // text format.
+    $full_html_format = entity_load('filter_format', 'full_html');
     $permissions = array(
       'administer filters',
       $full_html_format->getPermissionName(),
       'administer permissions',
       'create page content',
-      'post comments',
       'skip comment approval',
       'access comments',
     );
@@ -64,25 +58,18 @@ function setUp() {
    * Verify that comments are rendered using proper format in search results.
    */
   function testSearchResultsComment() {
-    // Create basic_html format that escapes all HTML.
-    $basic_html_format = entity_create('filter_format', array(
-      'format' => 'basic_html',
-      'name' => 'Basic HTML',
-      'weight' => 1,
-      'filters' => array(
-        'filter_html_escape' => array('status' => 1),
-      ),
-      'roles' => array(DRUPAL_AUTHENTICATED_RID),
-    ));
-    $basic_html_format->save();
-
     $comment_body = 'Test comment body';
 
     // Make preview optional.
     $instance = Field::fieldInfo()->getInstance('node', 'article', 'comment');
     $instance->settings['preview'] = DRUPAL_OPTIONAL;
     $instance->save();
-
+    // Enable check_plain() for 'Basic HTML' text format.
+    $basic_html_format_id = 'basic_html';
+    $edit = array(
+      'filters[filter_html_escape][status]' => TRUE,
+    );
+    $this->drupalPostForm('admin/config/content/formats/manage/' . $basic_html_format_id, $edit, t('Save configuration'));
     // Allow anonymous users to search content.
     $edit = array(
       DRUPAL_ANONYMOUS_RID . '[search content]' => 1,
@@ -109,7 +96,7 @@ function testSearchResultsComment() {
     $edit = array(
       'keys' => "'" . $edit_comment['subject'] . "'",
     );
-    $this->drupalPostForm('search/node', $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
     $node2 = node_load($node->id(), TRUE);
     $this->assertText($node2->label(), 'Node found in search results.');
     $this->assertText($edit_comment['subject'], 'Comment subject found in search results.');
@@ -118,7 +105,7 @@ function testSearchResultsComment() {
     $edit = array(
       'keys' => "'" . $comment_body . "'",
     );
-    $this->drupalPostForm(NULL, $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
     $this->assertText($node2->label(), 'Node found in search results.');
 
     // Verify that comment is rendered using proper format.
@@ -136,7 +123,7 @@ function testSearchResultsComment() {
     $this->cronRun();
 
     // Search for $title.
-    $this->drupalPostForm('search/node', $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
     $this->assertNoText($comment_body, 'Comment body text not found in search results.');
   }
 
@@ -224,7 +211,7 @@ function assertCommentAccess($assume_access, $message) {
     $edit = array(
       'keys' => "'" . $this->comment_subject . "'",
     );
-    $this->drupalPostForm('search/node', $edit, t('Search'));
+    $this->submitGetForm('', $edit, t('Search'));
 
     if ($assume_access) {
       $expected_node_result = $this->assertText($this->node->label());
@@ -248,20 +235,14 @@ function testAddNewComment() {
       'body' => array(array('value' => 'short body text')),
     );
 
-    $user = $this->drupalCreateUser(array(
-      'search content',
-      'create article content',
-      'access content',
-      'post comments',
-      'access comments',
-    ));
+    $user = $this->drupalCreateUser(array('search content', 'create article content', 'access content'));
     $this->drupalLogin($user);
 
     $node = $this->drupalCreateNode($settings);
     // Verify that if you view the node on its own page, 'add new comment'
     // is there.
     $this->drupalGet('node/' . $node->id());
-    $this->assertText(t('Add new comment'));
+    $this->assertText(t('Add new comment'), 'Add new comment appears on node page');
 
     // Run cron to index this page.
     $this->drupalLogout();
@@ -270,12 +251,12 @@ function testAddNewComment() {
     // Search for 'comment'. Should be no results.
     $this->drupalLogin($user);
     $this->drupalPostForm('search/node', array('keys' => 'comment'), t('Search'));
-    $this->assertText(t('Your search yielded no results'));
+    $this->assertText(t('Your search yielded no results'), 'No results searching for the word comment');
 
     // Search for the node title. Should be found, and 'Add new comment' should
     // not be part of the search snippet.
     $this->drupalPostForm('search/node', array('keys' => 'short'), t('Search'));
     $this->assertText($node->label(), 'Search for keyword worked');
-    $this->assertNoText(t('Add new comment'));
+    $this->assertNoText(t('Add new comment'), 'Add new comment does not appear on search results page');
   }
 }
diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css
index c8908b5..b8678a3 100644
--- a/core/modules/system/css/system.theme.css
+++ b/core/modules/system/css/system.theme.css
@@ -79,20 +79,11 @@ h4.label {
 .form-type-checkbox .description {
   margin-left: 2.4em;
 }
-.marker {
+.marker,
+.form-required {
   color: #e00;
 }
-
-.form-required:after {
-  color: #e00;
-  /* Use a Unicode symbol to prevent screen-readers from announcing the text. */
-  content: " \204E ";
-  line-height: 1;
-  vertical-align: super;
-}
-
-abbr.tabledrag-changed,
-abbr.ajax-changed {
+abbr.form-required, abbr.tabledrag-changed, abbr.ajax-changed {
   border-bottom: none;
 }
 .form-item input.error,
diff --git a/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php b/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php
index 7ab0ec1..fbc60bc 100644
--- a/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php
@@ -84,6 +84,7 @@ public function buildForm(array $form, array &$form_state) {
     $period = array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400);
     $period = array_map('format_interval', array_combine($period, $period));
     $period[0] = '<' . t('no caching') . '>';
+    $period[\Drupal\Core\Cache\Cache::PERMANENT] = t('Forever');
     $form['caching']['page_cache_maximum_age'] = array(
       '#type' => 'select',
       '#title' => t('Page cache maximum age'),
diff --git a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php
index fdf16b9..7f6b6a0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php
@@ -196,31 +196,15 @@ function testPageCache() {
     $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'must-revalidate, no-cache, post-check=0, pre-check=0, private', 'Cache-Control header was sent.');
     $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
     $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.');
-  }
-
-  /**
-   * Tests the omit_vary_cookie setting.
-   */
-  public function testPageCacheWithoutVaryCookie() {
-    $config = \Drupal::config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->save();
 
+    // Check the omit_vary_cookie setting.
+    $this->drupalLogout();
     $settings['settings']['omit_vary_cookie'] = (object) array(
       'value' => TRUE,
       'required' => TRUE,
     );
     $this->writeSettings($settings);
-
-    // Fill the cache.
-    $this->drupalGet('');
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.');
-    $this->assertTrue(strpos($this->drupalGetHeader('Vary'), 'Cookie') === FALSE, 'Vary: Cookie header was not sent.');
-
-    // Check cache.
-    $this->drupalGet('');
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
+    $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
     $this->assertTrue(strpos($this->drupalGetHeader('Vary'), 'Cookie') === FALSE, 'Vary: Cookie header was not sent.');
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php
index 7cda6a3..f3db246 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Language\Language;
 use Drupal\simpletest\WebTestBase;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Tests for URL generation functions.
@@ -25,7 +26,7 @@ class UrlTest extends WebTestBase {
   public static function getInfo() {
     return array(
       'name' => 'URL generation tests',
-      'description' => 'Confirm that url(), \Drupal\Component\Utility\UrlHelper::filterQueryParameters(), \Drupal\Component\Utility\UrlHelper::buildQuery(), and l() work correctly with various input.',
+      'description' => 'Confirm that url(), drupal_get_query_parameters(), \Drupal\Component\Utility\UrlHelper::buildQuery(), and l() work correctly with various input.',
       'group' => 'Common',
     );
   }
@@ -183,7 +184,7 @@ private function hasAttribute($attribute, $link, $class) {
   }
 
   /**
-   * Tests UrlHelper::filterQueryParameters().
+   * Tests drupal_get_query_parameters().
    */
   function testDrupalGetQueryParameters() {
     $original = array(
@@ -200,22 +201,22 @@ function testDrupalGetQueryParameters() {
     // First-level exclusion.
     $result = $original;
     unset($result['b']);
-    $this->assertEqual(UrlHelper::filterQueryParameters($original, array('b')), $result, "'b' was removed.");
+    $this->assertEqual(drupal_get_query_parameters($original, array('b')), $result, "'b' was removed.");
 
     // Second-level exclusion.
     $result = $original;
     unset($result['b']['d']);
-    $this->assertEqual(UrlHelper::filterQueryParameters($original, array('b[d]')), $result, "'b[d]' was removed.");
+    $this->assertEqual(drupal_get_query_parameters($original, array('b[d]')), $result, "'b[d]' was removed.");
 
     // Third-level exclusion.
     $result = $original;
     unset($result['b']['e']['f']);
-    $this->assertEqual(UrlHelper::filterQueryParameters($original, array('b[e][f]')), $result, "'b[e][f]' was removed.");
+    $this->assertEqual(drupal_get_query_parameters($original, array('b[e][f]')), $result, "'b[e][f]' was removed.");
 
     // Multiple exclusions.
     $result = $original;
     unset($result['a'], $result['b']['e'], $result['c']);
-    $this->assertEqual(UrlHelper::filterQueryParameters($original, array('a', 'b[e]', 'c')), $result, "'a', 'b[e]', 'c' were removed.");
+    $this->assertEqual(drupal_get_query_parameters($original, array('a', 'b[e]', 'c')), $result, "'a', 'b[e]', 'c' were removed.");
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityViewControllerTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityViewControllerTest.php
index 4faec44..102eeb7 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityViewControllerTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityViewControllerTest.php
@@ -53,19 +53,9 @@ function setUp() {
    * Tests EntityViewController.
    */
   function testEntityViewController() {
-    $get_label_markup = function($label) {
-      return '<h1><div class="field field-entity-test--name field-name-name field-type-string field-label-hidden">
-    <div class="field-items">
-          <div class="field-item">' . $label . '</div>
-      </div>
-</div>
-</h1>';
-    };
-
     foreach ($this->entities as $entity) {
       $this->drupalGet('entity_test/' . $entity->id());
       $this->assertRaw($entity->label());
-      $this->assertRaw($get_label_markup($entity->label()));
       $this->assertRaw('full');
 
       $this->drupalGet('entity_test_converter/' . $entity->id());
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php
index b002635..6c51a04 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php
@@ -59,10 +59,10 @@ function testFormLabels() {
 
     // Exercise various defaults for textboxes and modifications to ensure
     // appropriate override and correct behavior.
-    $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required" and @class="form-required"]/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]');
+    $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required"]/child::span[@class="form-required"]/parent::*/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]');
     $this->assertTrue(isset($elements[0]), 'Label precedes textfield, with required marker inside label.');
 
-    $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required" and @class="form-required"]');
+    $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required"]/span[@class="form-required"]');
     $this->assertTrue(isset($elements[0]), 'Label tag with required marker precedes required textfield with no title.');
 
     $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-invisible"]/preceding-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="visually-hidden"]');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index b4eebff..634b004 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -97,7 +97,8 @@ function testRequiredFields() {
     $elements['file']['empty_values'] = $empty_strings;
 
     // Regular expression to find the expected marker on required elements.
-    $required_marker_preg = '@<.*?class=".*?form-required.*?">@';
+    $required_marker_preg = '@<(?:label|legend).*<span class="form-required" aria-hidden="true">\*</span>.*</(?:label|legend)>@';
+
     // Go through all the elements and all the empty values for them.
     foreach ($elements as $type => $data) {
       foreach ($data['empty_values'] as $key => $empty) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php
index d0db0de..8148c7a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php
@@ -31,19 +31,6 @@ public static function getInfo() {
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function setUp() {
-    parent::setUp();
-
-    entity_create('menu', array(
-      'id' => 'menu_test',
-      'label' => 'Test menu',
-      'description' => 'Description text',
-    ))->save();
-  }
-
-  /**
    * Create a simple hierarchy of links.
    */
   function createLinkHierarchy($module = 'menu_test') {
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 820efa7..a14cd7b 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -956,25 +956,5 @@ function system_schema() {
     ),
   );
 
-  $schema['config_snapshot'] = array(
-    'description' => 'Stores a snapshot of the last imported configuration.',
-    'fields' => array(
-      'name' => array(
-        'description' => 'The identifier for the config object (the name of the file, minus the file extension).',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'data' => array(
-        'description' => 'The raw data for this configuration object.',
-        'type' => 'blob',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-    ),
-    'primary key' => array('name'),
-  );
-
   return $schema;
 }
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 15a1011..bef0349 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1306,7 +1306,7 @@ function system_rebuild_module_data() {
  * @return \Drupal\Core\Extension\Extension[]
  *   Array of all available themes and their data.
  *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ * @deprecated 8.x
  *   Use \Drupal::service('theme_handler')->rebuildThemeData().
  */
 function system_rebuild_theme_data() {
diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig
index 52d410f..9e4fe68 100644
--- a/core/modules/system/templates/fieldset.html.twig
+++ b/core/modules/system/templates/fieldset.html.twig
@@ -25,7 +25,7 @@
 <fieldset{{ attributes }}>
   {% if legend.title is not empty or required -%}
     {#  Always wrap fieldset legends in a SPAN for CSS positioning. #}
-    <legend{{ legend.attributes }}><span class="{{ legend_span.attributes.class }}">{{ legend.title }}{{ required }}</span></legend>
+    <legend{{ legend.attributes }}><span class="fieldset-legend">{{ legend.title }}{{ required }}</span></legend>
   {%- endif %}
   <div class="fieldset-wrapper">
     {% if prefix %}
diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.module b/core/modules/system/tests/modules/ajax_test/ajax_test.module
index eee24f3..356f7d6 100644
--- a/core/modules/system/tests/modules/ajax_test/ajax_test.module
+++ b/core/modules/system/tests/modules/ajax_test/ajax_test.module
@@ -95,7 +95,6 @@ function ajax_test_error() {
 function ajax_test_dialog_contents() {
   // This is a regular render array; the keys do not have special meaning.
   $content = array(
-    '#title' => 'AJAX Dialog contents',
     'content' => array(
       '#markup' => 'Example message',
     ),
diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml b/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml
index e3c7cf5..8be4f0a 100644
--- a/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml
+++ b/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml
@@ -1,7 +1,7 @@
 ajax_test.dialog_contents:
   path: '/ajax-test/dialog-contents'
   defaults:
-    _title: 'AJAX Dialog contents routing'
+    _title: 'AJAX Dialog contents'
     _content: '\Drupal\ajax_test\Controller\AjaxTestController::dialogContents'
   requirements:
     _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.routing.yml b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml
index 38b0c44..8b99660 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.routing.yml
+++ b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml
@@ -2,7 +2,6 @@ entity_test.render:
   path: '/entity_test/{entity_test}'
   defaults:
     _entity_view: 'entity_test.full'
-    _title: 'Test full view mode'
   requirements:
     _access: 'TRUE'
 
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
index 01e6872..a2f2d2c 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
@@ -82,12 +82,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setLabel(t('Name'))
       ->setDescription(t('The name of the test entity.'))
       ->setTranslatable(TRUE)
-      ->setSetting('max_length', 32)
-      ->setDisplayOptions('view', array(
-        'label' => 'hidden',
-        'type' => 'string',
-        'weight' => -5,
-      ));
+      ->setSetting('max_length', 32);
 
     // @todo: Add allowed values validation.
     $fields['type'] = FieldDefinition::create('string')
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestViewBuilder.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestViewBuilder.php
index e45ddc0..15f6b6d 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestViewBuilder.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestViewBuilder.php
@@ -24,15 +24,12 @@ public function buildComponents(array &$build, array $entities, array $displays,
 
     foreach ($entities as $id => $entity) {
       $build[$id]['label'] = array(
-        '#weight' => -100,
         '#markup' => check_plain($entity->label()),
       );
       $build[$id]['separator'] = array(
-        '#weight' => -150,
         '#markup' => ' | ',
       );
       $build[$id]['view_mode'] = array(
-        '#weight' => -200,
         '#markup' => check_plain($view_mode),
       );
     }
diff --git a/core/modules/system/tests/modules/menu_test/config/install/system.menu.changed.yml b/core/modules/system/tests/modules/menu_test/config/install/system.menu.changed.yml
deleted file mode 100644
index 4530fee..0000000
--- a/core/modules/system/tests/modules/menu_test/config/install/system.menu.changed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-id: changed
-label: Changed test menu
-description: 'The changed menu for menu_test tests.'
-langcode: en
-locked: true
diff --git a/core/modules/system/tests/modules/menu_test/config/install/system.menu.original.yml b/core/modules/system/tests/modules/menu_test/config/install/system.menu.original.yml
deleted file mode 100644
index c3443fd..0000000
--- a/core/modules/system/tests/modules/menu_test/config/install/system.menu.original.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-id: original
-label: Original test menu
-description: 'The original menu for menu_test tests.'
-langcode: en
-locked: true
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
index c7035c9..cddfefd 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
@@ -8,19 +8,13 @@
 namespace Drupal\taxonomy\Tests;
 
 use Drupal\Core\Datetime\DrupalDateTime;
-use Drupal\Core\Field\FieldDefinitionInterface;
 
 /**
  * Test for legacy node bug.
  */
 class LegacyTest extends TaxonomyTestBase {
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('node', 'datetime');
+  protected $profile = 'standard';
 
   public static function getInfo() {
     return array(
@@ -32,42 +26,6 @@ public static function getInfo() {
 
   function setUp() {
     parent::setUp();
-
-    // Create a tags vocabulary for the 'article' content type.
-    $vocabulary = entity_create('taxonomy_vocabulary', array(
-      'name' => 'Tags',
-      'vid' => 'tags',
-    ));
-    $vocabulary->save();
-    $field_name = 'field_' . $vocabulary->id();
-
-    entity_create('field_config', array(
-      'name' => $field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
-      ),
-    ))->save();
-    entity_create('field_instance_config', array(
-      'entity_type' => 'node',
-      'field_name' => $field_name,
-      'bundle' => 'article',
-      'label' => 'Tags',
-    ))->save();
-
-    entity_get_form_display('node', 'article', 'default')
-      ->setComponent($field_name, array(
-        'type' => 'taxonomy_autocomplete',
-      ))
-      ->save();
-
     $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'administer nodes', 'bypass node access'));
     $this->drupalLogin($this->admin_user);
   }
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 4d810d6..2a76441 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -121,11 +121,13 @@ function _toolbar_initialize_page_cache() {
   // If we have a cache, serve it.
   // @see _drupal_bootstrap_page_cache()
   $request = \Drupal::request();
-  $response = drupal_page_get_cache($request);
-  if ($response) {
+  $cache = drupal_page_get_cache($request);
+  if (is_object($cache)) {
+    $response = new Response();
     $response->headers->set('X-Drupal-Cache', 'HIT');
+    date_default_timezone_set(drupal_get_user_timezone());
 
-    drupal_serve_page_from_cache($response, $request);
+    drupal_serve_page_from_cache($cache, $response, $request);
 
     $response->prepare($request);
     $response->send();
@@ -133,6 +135,9 @@ function _toolbar_initialize_page_cache() {
     exit;
   }
 
+  // Otherwise, create a new page response (that will be cached).
+  drupal_add_http_header('X-Drupal-Cache', 'MISS');
+
   // The Expires HTTP header is the heart of the client-side HTTP caching. The
   // additional server-side page cache only takes effect when the client
   // accesses the callback URL again (e.g., after clearing the browser cache or
diff --git a/core/modules/tour/tests/Drupal/tour/Tests/Entity/TourTest.php b/core/modules/tour/tests/Drupal/tour/Tests/Entity/TourTest.php
index 5335fc8..6693cec 100644
--- a/core/modules/tour/tests/Drupal/tour/Tests/Entity/TourTest.php
+++ b/core/modules/tour/tests/Drupal/tour/Tests/Entity/TourTest.php
@@ -4,7 +4,7 @@
  * Contains \Drupal\tour\Tests\Entity\TourTest.
  */
 
-namespace Drupal\tour\Tests\Entity;
+namespace Drupal\tour\Tests\Entity\TourTest;
 
 use Drupal\Tests\UnitTestCase;
 
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleUnformattedTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleUnformattedTest.php
index 0c367d2..b8a6735 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleUnformattedTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleUnformattedTest.php
@@ -45,6 +45,19 @@ function testDefaultRowClasses() {
       $count++;
       $attributes = $row->attributes();
       $class = (string) $attributes['class'][0];
+      // Make sure that each row has a row css class.
+      $this->assertTrue(strpos($class, "views-row-$count") !== FALSE, 'Make sure that each row has a row css class.');
+      // Make sure that the odd/even classes are set right.
+      $odd_even = $count % 2 == 0 ? 'even' : 'odd';
+      $this->assertTrue(strpos($class, "views-row-$odd_even") !== FALSE, 'Make sure that the odd/even classes are set right.');
+
+      if ($count == 1) {
+        $this->assertTrue(strpos($class, "views-row-first") !== FALSE, 'Make sure that the first class is set right.');
+      }
+      elseif ($count == $count_result) {
+        $this->assertTrue(strpos($class, "views-row-last") !== FALSE, 'Make sure that the last class is set right.');
+
+      }
       $this->assertTrue(strpos($class, 'views-row') !== FALSE, 'Make sure that the views row class is set right.');
     }
   }
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php b/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php
index b8a614d..9b677ee 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php
@@ -33,12 +33,6 @@
   protected function setUp() {
     parent::setUp();
 
-    // Views' Page displays put menu links in the 'navigation' menu by default.
-    entity_create('menu', array(
-      'id' => 'navigation',
-      'label' => 'Navigation',
-    ))->save();
-
     // Ensure that the plugin definitions are cleared.
     foreach (ViewExecutable::getPluginTypes() as $plugin_type) {
       $this->container->get("plugin.manager.views.$plugin_type")->clearCachedDefinitions();
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index cfcc162..7308da8 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -679,6 +679,15 @@ function template_preprocess_views_view_table(&$variables) {
   $count = 0;
   foreach ($variables['rows'] as $num => $row) {
     $variables['rows'][$num]['attributes'] = array();
+    if ($row_class_special) {
+      $variables['rows'][$num]['attributes']['class'][] = ($count++ % 2 == 0) ? 'odd' : 'even';
+      if ($num === 0) {
+        $variables['rows'][$num]['attributes']['class'][] = 'views-row-first';
+      }
+      elseif ($num === (count($variables['rows']) - 1)) {
+        $variables['rows'][$num]['attributes']['class'][] = 'views-row-last';
+      }
+    }
     if ($row_class = $handler->getRowClass($num)) {
       $variables['rows'][$num]['attributes']['class'][] = $row_class;
     }
@@ -880,6 +889,16 @@ function template_preprocess_views_view_unformatted(&$variables) {
     $count++;
     if ($default_row_class) {
       $variables['rows'][$id]['attributes']['class'][] = 'views-row';
+      $variables['rows'][$id]['attributes']['class'][] = 'views-row-' . $count;
+    }
+    if ($row_class_special) {
+      $variables['rows'][$id]['attributes']['class'][] = 'views-row-' . ($count % 2 ? 'odd' : 'even');
+      if ($count == 1) {
+        $variables['rows'][$id]['attributes']['class'][] = 'views-row-first';
+      }
+      if ($count == $max) {
+        $variables['rows'][$id]['attributes']['class'][] = 'views-row-last';
+      }
     }
     if ($row_class = $view->style_plugin->getRowClass($id)) {
       $variables['rows'][$id]['attributes']['class'][] = $row_class;
diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
index 5fe2570..81ac83d 100644
--- a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
@@ -5,9 +5,8 @@
  * Contains \Drupal\Tests\Core\Access\CsrfTokenGeneratorTest.
  */
 
-namespace Drupal\Tests\Core\Access;
+namespace Drupal\Tests\Core\Access {
 
-use Drupal\Core\Site\Settings;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Access\CsrfTokenGenerator;
 use Drupal\Component\Utility\Crypt;
@@ -25,13 +24,6 @@ class CsrfTokenGeneratorTest extends UnitTestCase {
    */
   protected $generator;
 
-  /**
-   * The mock private key instance.
-   *
-   * @var \Drupal\Core\PrivateKey|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $privateKey;
-
   public static function getInfo() {
     return array(
       'name' => 'CsrfTokenGenerator test',
@@ -47,22 +39,16 @@ function setUp() {
     parent::setUp();
     $this->key = Crypt::randomBytesBase64(55);
 
-    $this->privateKey = $this->getMockBuilder('Drupal\Core\PrivateKey')
+    $private_key = $this->getMockBuilder('Drupal\Core\PrivateKey')
       ->disableOriginalConstructor()
       ->setMethods(array('get'))
       ->getMock();
 
-    $this->privateKey->expects($this->any())
+    $private_key->expects($this->any())
       ->method('get')
       ->will($this->returnValue($this->key));
 
-    $settings = array(
-      'hash_salt' => $this->randomName(),
-    );
-
-    new Settings($settings);
-
-    $this->generator = new CsrfTokenGenerator($this->privateKey);
+    $this->generator = new CsrfTokenGenerator($private_key);
   }
 
   /**
@@ -155,16 +141,17 @@ public function providerTestInvalidParameterTypes() {
     );
   }
 
-  /**
-   * Tests the exception thrown when no 'hash_salt' is provided in settings.
-   *
-   * @expectedException \RuntimeException
-   */
-  public function testGetWithNoHashSalt() {
-    // Update settings with no hash salt.
-    new Settings(array());
-    $generator = new CsrfTokenGenerator($this->privateKey);
-    $generator->get();
-  }
+}
+
+}
 
+/**
+ * @todo Remove this when https://drupal.org/node/2036259 is resolved.
+ */
+namespace {
+  if (!function_exists('drupal_get_hash_salt')) {
+    function drupal_get_hash_salt() {
+      return hash('sha256', 'test_hash_salt');
+    }
+  }
 }
diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityDatabaseStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityDatabaseStorageTest.php
index 162b937..ef9bd2e 100644
--- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityDatabaseStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityDatabaseStorageTest.php
@@ -142,8 +142,10 @@ public function testCreate() {
       ->method('getKeys')
       ->will($this->returnValue(array('id' => 'id')));
     $entity_type->expects($this->atLeastOnce())
-      ->method('isRevisionable')
-      ->will($this->returnValue(FALSE));
+      ->method('hasKey')
+      ->will($this->returnCallback(function ($key) {
+        return $key == 'id';
+      }));
     $entity_manager->expects($this->atLeastOnce())
       ->method('getDefinition')
       ->with('test_entity_type')
diff --git a/core/tests/Drupal/Tests/Core/Entity/Controller/EntityViewControllerTest.php b/core/tests/Drupal/Tests/Core/Entity/Controller/EntityViewControllerTest.php
index ac6c886..0bc6353 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Controller/EntityViewControllerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Controller/EntityViewControllerTest.php
@@ -49,34 +49,10 @@ public function testView() {
       ->method('getViewBuilder')
       ->will($this->returnValue($render_controller));
 
-    // Mock the 'entity_test' entity type.
-    $entity_type = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityType')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $entity_type->expects($this->once())
-      ->method('getKey')
-      ->with('label')
-      ->will($this->returnValue('name'));
-
-    // Mock the 'name' field's definition.
-    $field_definition = $this->getMock('Drupal\Core\Field\FieldDefinition');
-    $field_definition->expects($this->any())
-      ->method('getDisplayOptions')
-      ->with('view')
-      ->will($this->returnValue(NULL));
-
     // Mock an 'entity_test' entity.
     $entity = $this->getMockBuilder('Drupal\entity_test\Entity\EntityTest')
       ->disableOriginalConstructor()
       ->getMock();
-    $entity->expects($this->once())
-      ->method('getEntityType')
-      ->will($this->returnValue($entity_type));
-    $entity->expects($this->any())
-      ->method('getFieldDefinition')
-      ->with('name')
-      ->will($this->returnValue($field_definition));
-
 
     // Initialize the controller to test.
     $controller = new EntityViewController($entity_manager);
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
index ac29654..1cb561c 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
@@ -89,18 +89,6 @@ public function providerTestGetKeys() {
   }
 
   /**
-   * Tests the isRevisionable() method.
-   */
-  public function testIsRevisionable() {
-    $entity_type = $this->setUpEntityType(array('entity_keys' => array('id' => 'id')));
-    $this->assertFalse($entity_type->isRevisionable());
-    $entity_type = $this->setUpEntityType(array('entity_keys' => array('id' => 'id', 'revision' => FALSE)));
-    $this->assertFalse($entity_type->isRevisionable());
-    $entity_type = $this->setUpEntityType(array('entity_keys' => array('id' => 'id', 'revision' => TRUE)));
-    $this->assertTrue($entity_type->isRevisionable());
-  }
-
-  /**
    * Tests the getController() method.
    */
   public function testGetController() {
diff --git a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
index 6038899..541cbe8 100644
--- a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
+++ b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
@@ -13,8 +13,6 @@
 /**
  * Tests read-only settings.
  *
- * @group Drupal
- *
  * @coversDefaultClass \Drupal\Core\Site\Settings
  */
 class SettingsTest extends UnitTestCase {
@@ -51,7 +49,6 @@ public function setUp(){
     $this->config = array(
       'one' => '1',
       'two' => '2',
-      'hash_salt' => $this->randomName(),
     );
     $this->settings = new Settings($this->config);
   }
@@ -61,7 +58,7 @@ public function setUp(){
    */
   public function testGet() {
     // Test stored settings.
-    $this->assertEquals($this->config['one'], Settings::get('one'), 'The correct setting was not returned.');
+    $this->assertEquals($this->config['one'], Settings::get('one'), 'The correect setting was not returned.');
     $this->assertEquals($this->config['two'], Settings::get('two'), 'The correct setting was not returned.');
 
     // Test setting that isn't stored with default.
@@ -84,41 +81,4 @@ public function testGetInstance() {
     $this->assertEquals($singleton, $this->settings);
   }
 
-  /**
-   * Tests Settings::getHashSalt();
-   *
-   * @covers ::getHashSalt
-   */
-  public function testGetHashSalt() {
-    $this->assertSame($this->config['hash_salt'], $this->settings->getHashSalt());
-  }
-
-  /**
-   * Tests Settings::getHashSalt() with no hash salt value.
-   *
-   * @covers ::getHashSalt
-   *
-   * @dataProvider providerTestGetHashSaltEmpty
-   *
-   * @expectedException \RuntimeException
-   */
-  public function testGetHashSaltEmpty(array $config) {
-    // Re-create settings with no 'hash_salt' key.
-    $settings = new Settings($config);
-    $settings->getHashSalt();
-  }
-
-  /**
-   * Data provider for testGetHashSaltEmpty.
-   *
-   * @return array
-   */
-  public function providerTestGetHashSaltEmpty() {
-   return array(
-     array(array()),
-     array(array('hash_salt' => '')),
-     array(array('hash_salt' => NULL)),
-   );
-  }
-
 }
diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index d8dff1a..80ddc82 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -440,7 +440,7 @@ h1.site-name {
   background: #fff;
   background: rgba(255, 255, 255, 0.8);
 }
-.region-header .form-required:after {
+.region-header .form-required {
   color: #eee;
   color: rgba(255, 255, 255, 0.7);
 }
