diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index 3d5fcef..5a2f6ac 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -199,8 +199,6 @@ drupal.dropbutton:
   css:
     component:
       misc/dropbutton/dropbutton.css: {}
-    theme:
-      misc/dropbutton/dropbutton.theme.css: {}
   dependencies:
     - core/jquery
     - core/drupal
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 4ce12c5..06ba271 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -12,12 +12,10 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Component\Utility\SafeStringInterface;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Config\Config;
 use Drupal\Core\Config\StorageException;
-use Drupal\Core\Render\RenderableInterface;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Theme\ThemeSettings;
 use Drupal\Component\Utility\NestedArray;
@@ -360,75 +358,6 @@ function theme_get_setting($setting_name, $theme = NULL) {
 }
 
 /**
- * Escapes and renders variables for theme functions.
- *
- * This method is used in theme functions to ensure that the result is safe for
- * output inside HTML fragments. This mimics the behavior of the auto-escape
- * functionality in Twig.
- *
- * Note: This function should be kept in sync with
- * \Drupal\Core\Template\TwigExtension::escapeFilter().
- *
- * @param mixed $arg
- *   The string, object, or render array to escape if needed.
- *
- * @return string
- *   The rendered string, safe for use in HTML. The string is not safe when used
- *   as any part of an HTML attribute name or value.
- *
- * @throws \Exception
- *   Thrown when an object is passed in which cannot be printed.
- *
- * @see \Drupal\Core\Template\TwigExtension::escapeFilter()
- *
- * @todo Discuss deprecating this in https://www.drupal.org/node/2575081.
- * @todo Refactor this to keep it in sync with Twig filtering in
- *   https://www.drupal.org/node/2575065
- */
-function theme_render_and_autoescape($arg) {
-  if ($arg instanceOf SafeStringInterface) {
-    return (string) $arg;
-  }
-  $return = NULL;
-
-  if (is_scalar($arg)) {
-    $return = (string) $arg;
-  }
-  elseif (is_object($arg)) {
-    if ($arg instanceof RenderableInterface) {
-      $arg = $arg->toRenderable();
-    }
-    elseif (method_exists($arg, '__toString')) {
-      $return = (string) $arg;
-    }
-    // You can't throw exceptions in the magic PHP __toString methods, see
-    // http://php.net/manual/en/language.oop5.magic.php#object.tostring so
-    // we also support a toString method.
-    elseif (method_exists($arg, 'toString')) {
-      $return = $arg->toString();
-    }
-    else {
-      throw new \Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg))));
-    }
-  }
-
-  // We have a string or an object converted to a string: Escape it!
-  if (isset($return)) {
-    return SafeMarkup::isSafe($return, 'html') ? $return : Html::escape($return);
-  }
-
-  // This is a normal render array, which is safe by definition, with special
-  // simple cases already handled.
-
-  // Early return if this element was pre-rendered (no need to re-render).
-  if (isset($arg['#printed']) && $arg['#printed'] == TRUE && isset($arg['#markup']) && strlen($arg['#markup']) > 0) {
-    return (string) $arg['#markup'];
-  }
-  $arg['#printed'] = FALSE;
-  return (string) \Drupal::service('renderer')->render($arg);
-}
-
-/**
  * Converts theme settings to configuration.
  *
  * @see system_theme_settings_submit()
diff --git a/core/lib/Drupal/Component/Utility/FormattableString.php b/core/lib/Drupal/Component/Utility/FormattableString.php
deleted file mode 100644
index ea7861c..0000000
--- a/core/lib/Drupal/Component/Utility/FormattableString.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\Component\Utility\FormattableString.
- */
-
-namespace Drupal\Component\Utility;
-
-/**
- * Formats a string for HTML display by replacing variable placeholders.
- *
- * When cast to a string it replaces variable placeholders in the string with
- * the arguments passed in during construction and escapes the values so they
- * can be safely displayed as HTML. It should be used on any unknown text that
- * is intended to be printed to an HTML page (especially text that may have come
- * from untrusted users, since in that case it prevents cross-site scripting and
- * other security problems).
- *
- * This class is not intended for passing arbitrary user input into any HTML
- * attribute value, as only URL attributes such as "src" and "href" are
- * supported (using ":variable"). Never use this method on unsafe HTML
- * attributes such as "on*" and "style" and take care when using this with
- * unsupported attributes such as "title" or "alt" as this can lead to
- * unexpected output.
- *
- * In most cases, you should use TranslatableString or PluralTranslatableString
- * rather than this object, since they will translate the text (on
- * non-English-only sites) in addition to formatting it.
- *
- * @ingroup sanitization
- *
- * @see \Drupal\Core\StringTranslation\TranslatableString
- * @see \Drupal\Core\StringTranslation\PluralTranslatableString
- */
-class FormattableString implements SafeStringInterface {
-
-  use PlaceholderTrait;
-
-  /**
-   * The arguments to replace placeholders with.
-   *
-   * @var array
-   */
-  protected $arguments = [];
-
-  /**
-   * Constructs a new class instance.
-   *
-   * @param string $string
-   *   A string containing placeholders. The string itself will not be escaped,
-   *   any unsafe content must be in $args and inserted via placeholders.
-   * @param array $args
-   *   An array with placeholder replacements, keyed by placeholder. See
-   *   \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat() for
-   *   additional information about placeholders.
-   *
-   * @see \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat()
-   */
-  public function __construct($string, array $arguments) {
-    $this->string = (string) $string;
-    $this->arguments = $arguments;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __toString() {
-    return static::placeholderFormat($this->string, $this->arguments);
-  }
-
-  /**
-   * Returns the string length.
-   *
-   * @return int
-   *   The length of the string.
-   */
-  public function count() {
-    return Unicode::strlen($this->string);
-  }
-
-  /**
-   * Returns a representation of the object for use in JSON serialization.
-   *
-   * @return string
-   *   The safe string content.
-   */
-  public function jsonSerialize() {
-    return $this->__toString();
-  }
-
-}
diff --git a/core/lib/Drupal/Component/Utility/PlaceholderTrait.php b/core/lib/Drupal/Component/Utility/PlaceholderTrait.php
index f5bcb39..5922b3f 100644
--- a/core/lib/Drupal/Component/Utility/PlaceholderTrait.php
+++ b/core/lib/Drupal/Component/Utility/PlaceholderTrait.php
@@ -15,62 +15,18 @@
   /**
    * Formats a string by replacing variable placeholders.
    *
-   * This trait is not intended for passing arbitrary user input into any HTML
-   * attribute value, as only URL attributes such as "src" and "href" are
-   * supported (using ":variable"). Never use this method on unsafe HTML
-   * attributes such as "on*" and "style" and take care when using this with
-   * unsupported attributes such as "title" or "alt" as this can lead to
-   * unexpected and unsafe output.
-   *
    * @param string $string
    *   A string containing placeholders.
    * @param array $args
-   *   An associative array of replacements to make. Occurrences in $string of
-   *   any key in $args are replaced with the corresponding value, after
-   *   optional sanitization and formatting. The type of sanitization and
-   *   formatting depends on the first character of the key:
-   *   - @variable: Escaped to HTML using Html::escape() unless the value is
-   *     already HTML-safe. Use this as the default choice for anything
-   *     displayed on a page on the site, but not within HTML attributes.
-   *   - %variable: Escaped to HTML just like @variable, but also wrapped in
-   *     <em> tags, which makes the following HTML code:
-   *     @code
-   *       <em class="placeholder">text output here.</em>
-   *     @endcode
-   *     As with @variable, do not use this within HTML attributes.
-   *   - :variable: Escaped to HTML using Html::escape() and filtered for
-   *     dangerous protocols using UrlHelper::stripDangerousProtocols(). Use
-   *     this when passing in a URL, such as when using the "src" or "href"
-   *     attributes, ensuring the value is always wrapped in quotes:
-   *     - Secure: <a href=":variable">@variable</a>
-   *     - Insecure: <a href=:variable>@variable</a>
-   *     When ":variable" comes from arbitrary user input, the result is secure,
-   *     but not guaranteed to be a valid URL (which means the resulting output
-   *     could fail HTML validation). To guarantee a valid URL, use
-   *     Url::fromUri($user_input)->toString() (which either throws an exception
-   *     or returns a well-formed URL) before passing the result into a
-   *     ":variable" placeholder.
-   *   - !variable: Inserted as is, with no sanitization or formatting. Only
-   *     use this when the resulting string is being generated for one of:
-   *     - Non-HTML usage, such as a plain-text email.
-   *     - Non-direct HTML output, such as a plain-text variable that will be
-   *       printed as an HTML attribute value and therefore formatted with
-   *       self::checkPlain() as part of that.
-   *     - Some other special reason for suppressing sanitization.
+   *   An associative array of replacements to make.
    * @param bool &$safe
    *   A boolean indicating whether the string is safe or not (optional).
    *
    * @return string
    *   The string with the placeholders replaced.
    *
-   * @ingroup sanitization
-   *
-   * @see \Drupal\Component\Utility\FormattableString
-   * @see \Drupal\Core\StringTranslation\TranslatableString
-   * @see \Drupal\Core\StringTranslation\PluralTranslatableString
-   * @see \Drupal\Component\Utility\Html::escape()
-   * @see \Drupal\Component\Utility\UrlHelper::stripDangerousProtocols()
-   * @see \Drupal\Core\Url::fromUri()
+   * @see \Drupal\Component\Utility\SafeMarkup::format()
+   * @see \Drupal\Core\StringTranslation\TranslatableString::render()
    */
   protected static function placeholderFormat($string, array $args, &$safe = TRUE) {
     // Transform arguments before inserting them.
diff --git a/core/lib/Drupal/Component/Utility/SafeMarkup.php b/core/lib/Drupal/Component/Utility/SafeMarkup.php
index a8c9576..c1c86f5 100644
--- a/core/lib/Drupal/Component/Utility/SafeMarkup.php
+++ b/core/lib/Drupal/Component/Utility/SafeMarkup.php
@@ -162,41 +162,79 @@ public static function checkPlain($text) {
   /**
    * Formats a string for HTML display by replacing variable placeholders.
    *
+   * This method replaces variable placeholders in a string with the requested
+   * values and escapes the values so they can be safely displayed as HTML. It
+   * should be used on any unknown text that is intended to be printed to an
+   * HTML page (especially text that may have come from untrusted users, since
+   * in that case it prevents cross-site scripting and other security problems).
+   *
+   * This method is not intended for passing arbitrary user input into any
+   * HTML attribute value, as only URL attributes such as "src" and "href" are
+   * supported (using ":variable"). Never use this method on unsafe HTML
+   * attributes such as "on*" and "style" and take care when using this with
+   * unsupported attributes such as "title" or "alt" as this can lead to
+   * unexpected output.
+   *
+   * In most cases, you should use t() rather than calling this function
+   * directly, since it will translate the text (on non-English-only sites) in
+   * addition to formatting it.
+   *
    * @param string $string
-   *   A string containing placeholders. The string itself will not be escaped,
-   *   any unsafe content must be in $args and inserted via placeholders.
+   *   A string containing placeholders. The string itself is not escaped, any
+   *   unsafe content must be in $args and inserted via placeholders.
    * @param array $args
-   *   An array with placeholder replacements, keyed by placeholder. See
-   *   \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat() for
-   *   additional information about placeholders.
+   *   An associative array of replacements to make. Occurrences in $string of
+   *   any key in $args are replaced with the corresponding value, after
+   *   optional sanitization and formatting. The type of sanitization and
+   *   formatting depends on the first character of the key:
+   *   - @variable: Escaped to HTML using Html::escape() unless the value is
+   *     already HTML-safe. Use this as the default choice for anything
+   *     displayed on a page on the site, but not within HTML attributes.
+   *   - %variable: Escaped to HTML just like @variable, but also wrapped in
+   *     <em> tags, which makes the following HTML code:
+   *     @code
+   *       <em class="placeholder">text output here.</em>
+   *     @endcode
+   *     As with @variable, do not use this within HTML attributes.
+   *   - :variable: Escaped to HTML using Html::escape() and filtered for
+   *     dangerous protocols using UrlHelper::stripDangerousProtocols(). Use
+   *     this when passing in a URL, such as when using the "src" or "href"
+   *     attributes, ensuring the value is always wrapped in quotes:
+   *     - Secure: <a href=":variable">@variable</a>
+   *     - Insecure: <a href=:variable>@variable</a>
+   *     When ":variable" comes from arbitrary user input, the result is secure,
+   *     but not guaranteed to be a valid URL (which means the resulting output
+   *     could fail HTML validation). To guarantee a valid URL, use
+   *     Url::fromUri($user_input)->toString() (which either throws an exception
+   *     or returns a well-formed URL) before passing the result into a
+   *     ":variable" placeholder.
+   *   - !variable: Inserted as is, with no sanitization or formatting. Only
+   *     use this when the resulting string is being generated for one of:
+   *     - Non-HTML usage, such as a plain-text email.
+   *     - Non-direct HTML output, such as a plain-text variable that will be
+   *       printed as an HTML attribute value and therefore formatted with
+   *       self::checkPlain() as part of that.
+   *     - Some other special reason for suppressing sanitization.
    *
-   * @return string|\Drupal\Component\Utility\SafeStringInterface
-   *   The formatted string, which is an instance of SafeStringInterface unless
-   *   sanitization of an unsafe argument was suppressed (see above).
+   * @return string
+   *   The formatted string, which is marked as safe unless sanitization of an
+   *   unsafe argument was suppressed (see above).
    *
    * @ingroup sanitization
    *
-   * @see \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat()
-   * @see \Drupal\Component\Utility\FormattableString
-   *
-   * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
-   *   Use \Drupal\Component\Utility\FormattableString.
+   * @see t()
+   * @see \Drupal\Component\Utility\Html::escape()
+   * @see \Drupal\Component\Utility\UrlHelper::stripDangerousProtocols()
+   * @see \Drupal\Core\Url::fromUri()
    */
   public static function format($string, array $args) {
-    // If the string has arguments that start with '!' we consider it unsafe
-    // and return a string instead of an object for backward compatibility
-    // purposes.
-    // @todo https://www.drupal.org/node/2571695 remove this temporary
-    //   workaround.
     $safe = TRUE;
-    foreach ($args as $key => $value) {
-      if ($key[0] == '!' && !static::isSafe($value)) {
-        $safe = FALSE;
-      }
+    $output = static::placeholderFormat($string, $args, $safe);
+    if ($safe) {
+      static::$safeStrings[$output]['html'] = TRUE;
     }
-    $safe_string = new FormattableString($string, $args);
+    return $output;
 
-    return $safe ? $safe_string : (string) $safe_string;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index a723087..f1dd106 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -252,6 +252,7 @@ public function rebuildThemeData() {
     // Set defaults for theme info.
     $defaults = array(
       'engine' => 'twig',
+      'base theme' => 'stable',
       'regions' => array(
         'sidebar_first' => 'Left sidebar',
         'sidebar_second' => 'Right sidebar',
@@ -282,6 +283,10 @@ public function rebuildThemeData() {
       $theme->status = (int) isset($installed[$key]);
 
       $theme->info = $this->infoParser->parse($theme->getPathname()) + $defaults;
+      // Handle when 'base theme: false' is set in a theme .info.yml file.
+      if (empty($theme->info['base theme'])) {
+        unset($theme->info['base theme']);
+      }
 
       // Add the info file modification time, so it becomes available for
       // contributed modules to use for ordering theme lists.
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
index 79eff67..d660c89 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
@@ -120,7 +120,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) {
-    return isset($element['target_id']) ? $element['target_id'] : FALSE;
+    return $element['target_id'];
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Render/theme.api.php b/core/lib/Drupal/Core/Render/theme.api.php
index bf95672..3139224 100644
--- a/core/lib/Drupal/Core/Render/theme.api.php
+++ b/core/lib/Drupal/Core/Render/theme.api.php
@@ -70,10 +70,7 @@
  * hook_theme() implementations can also specify that a theme hook
  * implementation is a theme function, but that is uncommon. It is only used for
  * special cases, for performance reasons, because rendering using theme
- * functions is somewhat faster than theme templates. Note that while Twig
- * templates will auto-escape variables, theme functions must explicitly escape
- * any variables by using theme_render_and_autoescape(). Failure to do so is
- * likely to result in security vulnerabilities.
+ * functions is somewhat faster than theme templates.
  *
  * @section sec_overriding_theme_hooks Overriding Theme Hooks
  * Themes may register new theme hooks within a hook_theme() implementation, but
@@ -96,9 +93,6 @@
  * bartik_search_result() in the bartik.theme file, if the search_result hook
  * implementation was a function instead of a template). Normally, copying the
  * default function is again a good starting point for overriding its behavior.
- * Again, note that theme functions (unlike templates) must explicitly escape
- * variables using theme_render_and_autoescape() or risk security
- * vulnerabilities.
  *
  * @section sec_preprocess_templates Preprocessing for Template Files
  * If the theme implementation is a template file, several functions are called
diff --git a/core/lib/Drupal/Core/StringTranslation/PluralTranslatableString.php b/core/lib/Drupal/Core/StringTranslation/PluralTranslatableString.php
index b9e79e5..f29d6e7 100644
--- a/core/lib/Drupal/Core/StringTranslation/PluralTranslatableString.php
+++ b/core/lib/Drupal/Core/StringTranslation/PluralTranslatableString.php
@@ -63,18 +63,18 @@ class PluralTranslatableString extends TranslatableString {
    *   ease translation. Use @count in place of the item count, as in
    *   "@count new comments".
    * @param array $args
-   *   (optional) An array with placeholder replacements, keyed by placeholder.
-   *   See \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat() for
-   *   additional information about placeholders. Note that you do not need to
-   *   include @count in this array; this replacement is done automatically
+   *   (optional) An associative array of replacements to make after
+   *   translation. Instances of any key in this array are replaced with the
+   *   corresponding value. Based on the first character of the key, the value
+   *   is escaped and/or themed. See
+   *   \Drupal\Component\Utility\SafeMarkup::format(). Note that you do not need
+   *   to include @count in this array; this replacement is done automatically
    *   for the plural cases.
    * @param array $options
    *   (optional) An associative array of additional options. See t() for
    *   allowed keys.
    * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
    *   (optional) The string translation service.
-   *
-   * @see \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat()
    */
   public function __construct($count, $singular, $plural, array $args = [], array $options = [], TranslationInterface $string_translation = NULL) {
     $this->count = $count;
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslatableString.php b/core/lib/Drupal/Core/StringTranslation/TranslatableString.php
index 0dbb3a6..92345b7 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslatableString.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslatableString.php
@@ -73,14 +73,10 @@ class TranslatableString implements SafeStringInterface {
    *   The string that is to be translated.
    * @param array $arguments
    *   (optional) An array with placeholder replacements, keyed by placeholder.
-   *   See \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat() for
-   *   additional information about placeholders.
    * @param array $options
    *   (optional) An array of additional options.
    * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
    *   (optional) The string translation service.
-   *
-   * @see \Drupal\Component\Utility\PlaceholderTrait::placeholderFormat()
    */
   public function __construct($string, array $arguments = array(), array $options = array(), TranslationInterface $string_translation = NULL) {
     $this->string = $string;
diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php
index a2f324d..3629cda 100644
--- a/core/lib/Drupal/Core/Template/Attribute.php
+++ b/core/lib/Drupal/Core/Template/Attribute.php
@@ -111,15 +111,11 @@ protected function createAttributeValue($name, $value) {
     }
     // An array value or 'class' attribute name are forced to always be an
     // AttributeArray value for consistency.
-    if ($name == 'class' && !is_array($value)) {
-      // Cast the value to string in case it implements SafeStringInterface.
-      $value = [(string) $value];
-    }
-    if (is_array($value)) {
+    if (is_array($value) || $name == 'class') {
       // Cast the value to an array if the value was passed in as a string.
       // @todo Decide to fix all the broken instances of class as a string
       // in core or cast them.
-      $value = new AttributeArray($name, $value);
+      $value = new AttributeArray($name, (array) $value);
     }
     elseif (is_bool($value)) {
       $value = new AttributeBoolean($name, $value);
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 13a7d16..735a434 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -350,9 +350,6 @@ public function escapePlaceholder($env, $string) {
    *
    * Replacement function for Twig's escape filter.
    *
-   * Note: This function should be kept in sync with
-   * theme_render_and_autoescape().
-   *
    * @param \Twig_Environment $env
    *   A Twig_Environment instance.
    * @param mixed $arg
@@ -367,9 +364,6 @@ public function escapePlaceholder($env, $string) {
    *
    * @return string|null
    *   The escaped, rendered output, or NULL if there is no valid output.
-   *
-   * @todo Refactor this to keep it in sync with theme_render_and_autoescape()
-   *   in https://www.drupal.org/node/2575065
    */
   public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $charset = NULL, $autoescape = FALSE) {
     // Check for a numeric zero int or float.
diff --git a/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php b/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
index afbffcc..641ac89 100644
--- a/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
+++ b/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
@@ -135,7 +135,7 @@ public function challengeException(Request $request, \Exception $previous) {
     $challenge = SafeMarkup::format('Basic realm="@realm"', array(
       '@realm' => !empty($site_name) ? $site_name : 'Access restricted',
     ));
-    return new UnauthorizedHttpException((string) $challenge, 'No authentication credentials provided.', $previous);
+    return new UnauthorizedHttpException($challenge, 'No authentication credentials provided.', $previous);
   }
 
 }
diff --git a/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig b/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig
index 672f567..777514f 100644
--- a/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig
+++ b/core/modules/config_translation/templates/config_translation_manage_form_element.html.twig
@@ -15,10 +15,10 @@
  */
 #}
 <div class="translation-set clearfix">
-  <div class="layout-column half translation-set__source">
+  <div class="layout-column layout-column--half translation-set__source">
     {{ element.source }}
   </div>
-  <div class="layout-column half translation-set__translated">
+  <div class="layout-column layout-column--half translation-set__translated">
     {{ element.translation }}
   </div>
 </div>
diff --git a/core/modules/editor/js/editor.js b/core/modules/editor/js/editor.js
index 20731b4..706673c 100644
--- a/core/modules/editor/js/editor.js
+++ b/core/modules/editor/js/editor.js
@@ -238,6 +238,15 @@
    */
   Drupal.editorAttach = function (field, format) {
     if (format.editor) {
+      // HTML5 validation cannot ever work for WYSIWYG editors, because WYSIWYG
+      // editors always hide the underlying textarea element, which prevents
+      // browsers from putting the error message bubble in the right location.
+      // Hence: disable HTML5 validation for this element.
+      if ('required' in field.attributes) {
+        field.setAttribute('data-editor-required', true);
+        field.removeAttribute('required');
+      }
+
       // Attach the text editor.
       Drupal.editors[format.editor].attach(field, format);
 
@@ -266,6 +275,13 @@
    */
   Drupal.editorDetach = function (field, format, trigger) {
     if (format.editor) {
+      // Restore the HTML5 validation "required" attribute if it was removed in
+      // Drupal.editorAttach().
+      if ('data-editor-required' in field.attributes) {
+        field.setAttribute('required', 'required');
+        field.removeAttribute('data-editor-required');
+      }
+
       Drupal.editors[format.editor].detach(field, format, trigger);
 
       // Restore the original value if the user didn't make any changes yet.
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceFileUploadTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceFileUploadTest.php
deleted file mode 100644
index 0368bf0..0000000
--- a/core/modules/entity_reference/src/Tests/EntityReferenceFileUploadTest.php
+++ /dev/null
@@ -1,131 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\entity_reference\Tests\EntityReferenceFileUploadTest.
- */
-
-namespace Drupal\entity_reference\Tests;
-
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests an autocomplete widget with file upload.
- *
- * @group entity_reference
- */
-class EntityReferenceFileUploadTest extends WebTestBase {
-
-  public static $modules = array('entity_reference', 'node', 'file');
-
-  /**
-   * The name of a content type that will reference $referencedType.
-   *
-   * @var string
-   */
-  protected $referencingType;
-
-  /**
-   * The name of a content type that will be referenced by $referencingType.
-   *
-   * @var string
-   */
-  protected $referencedType;
-
-  /**
-   * Node id.
-   *
-   * @var integer
-   */
-  protected $nodeId;
-
-  protected function setUp() {
-    parent::setUp();
-
-    // Create "referencing" and "referenced" node types.
-    $referencing = $this->drupalCreateContentType();
-    $this->referencingType = $referencing->id();
-
-    $referenced = $this->drupalCreateContentType();
-    $this->referencedType = $referenced->id();
-    $this->nodeId = $this->drupalCreateNode(array('type' => $referenced->id()))->id();
-
-    entity_create('field_storage_config', array(
-      'field_name' => 'test_field',
-      'entity_type' => 'node',
-      'translatable' => FALSE,
-      'entity_types' => array(),
-      'settings' => array(
-        'target_type' => 'node',
-      ),
-      'type' => 'entity_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-    ))->save();
-
-    entity_create('field_config', array(
-      'label' => 'Entity reference field',
-      'field_name' => 'test_field',
-      'entity_type' => 'node',
-      'required' => TRUE,
-      'bundle' => $referencing->id(),
-      'settings' => array(
-        'handler' => 'default',
-        'handler_settings' => array(
-          // Reference a single vocabulary.
-          'target_bundles' => array(
-            $referenced->id(),
-          ),
-        ),
-      ),
-    ))->save();
-
-
-    // Create a file field.
-    $file_field_name = 'file_field';
-    $field_storage = entity_create('field_storage_config', array(
-      'field_name' => $file_field_name,
-      'entity_type' => 'node',
-      'type' => 'file'
-    ));
-    $field_storage->save();
-    entity_create('field_config', array(
-      'entity_type' => 'node',
-      'field_storage' => $field_storage,
-      'bundle' => $referencing->id(),
-      'label' => $this->randomMachineName() . '_label',
-    ))->save();
-
-    entity_get_display('node', $referencing->id(), 'default')
-      ->setComponent('test_field')
-      ->setComponent($file_field_name)
-      ->save();
-    entity_get_form_display('node', $referencing->id(), 'default')
-      ->setComponent('test_field', array(
-        'type' => 'entity_reference_autocomplete',
-      ))
-      ->setComponent($file_field_name, array(
-         'type' => 'file_generic',
-      ))
-      ->save();
-  }
-
-  /**
-   * Tests that the autocomplete input element does not cause ajax fatal.
-   */
-  public function testFileUpload() {
-    $user1 = $this->drupalCreateUser(array('access content', "create $this->referencingType content"));
-    $this->drupalLogin($user1);
-
-    $test_file = current($this->drupalGetTestFiles('text'));
-    $edit['files[file_field_0]'] = drupal_realpath($test_file->uri);
-    $this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Upload');
-    $this->assertResponse(200);
-    $edit = array(
-      'title[0][value]' => $this->randomMachineName(),
-      'test_field[0][target_id]' => $this->nodeId,
-    );
-    $this->drupalPostForm(NULL, $edit, 'Save');
-    $this->assertResponse(200);
-  }
-}
diff --git a/core/modules/field/src/Tests/String/StringFieldTest.php b/core/modules/field/src/Tests/String/StringFieldTest.php
index 3114490..f59d507 100644
--- a/core/modules/field/src/Tests/String/StringFieldTest.php
+++ b/core/modules/field/src/Tests/String/StringFieldTest.php
@@ -22,7 +22,7 @@ class StringFieldTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('entity_test', 'file');
+  public static $modules = array('entity_test');
 
   /**
    * A user without any special permissions.
diff --git a/core/modules/help/src/Controller/HelpController.php b/core/modules/help/src/Controller/HelpController.php
index 4ebd4c8..dcb50bd 100644
--- a/core/modules/help/src/Controller/HelpController.php
+++ b/core/modules/help/src/Controller/HelpController.php
@@ -77,7 +77,7 @@ protected function helpLinksAsList() {
     $column = array(
       '#type' => 'container',
       'links' => array('#theme' => 'item_list'),
-      '#attributes' => array('class' => array('layout-column', 'quarter')),
+      '#attributes' => array('class' => array('layout-column', 'layout-column--quarter')),
     );
     $output = array(
       '#prefix' => '<div class="clearfix">',
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index 9373672..3f860de 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -201,5 +201,5 @@ function template_preprocess_language_content_settings_table(&$variables) {
  * @ingroup themeable
  */
 function theme_language_content_settings_table($variables) {
-  return '<h4>' . theme_render_and_autoescape($variables['build']['#title']) . '</h4>' . theme_render_and_autoescape($variables['build']);
+  return '<h4>' . $variables['build']['#title'] . '</h4>' . drupal_render($variables['build']);
 }
diff --git a/core/modules/responsive_image/src/Entity/ResponsiveImageStyle.php b/core/modules/responsive_image/src/Entity/ResponsiveImageStyle.php
index f585bc2..f3a2084 100644
--- a/core/modules/responsive_image/src/Entity/ResponsiveImageStyle.php
+++ b/core/modules/responsive_image/src/Entity/ResponsiveImageStyle.php
@@ -112,7 +112,6 @@ public function addImageStyleMapping($breakpoint_id, $multiplier, array $image_s
           'breakpoint_id' => $breakpoint_id,
           'multiplier' => $multiplier,
         ) + $image_style_mapping;
-        $this->keyedImageStyleMappings = NULL;
         return $this;
       }
     }
diff --git a/core/modules/responsive_image/tests/src/Unit/ResponsiveImageStyleConfigEntityUnitTest.php b/core/modules/responsive_image/tests/src/Unit/ResponsiveImageStyleConfigEntityUnitTest.php
index 71e81ed..63580a8 100644
--- a/core/modules/responsive_image/tests/src/Unit/ResponsiveImageStyleConfigEntityUnitTest.php
+++ b/core/modules/responsive_image/tests/src/Unit/ResponsiveImageStyleConfigEntityUnitTest.php
@@ -252,19 +252,6 @@ public function testGetKeyedImageStyleMappings() {
       'image_mapping' => 'medium',
     );
     $this->assertEquals($expected, $entity->getKeyedImageStyleMappings());
-
-    // Overwrite a mapping to ensure keyed mapping static cache is rebuilt.
-    $entity->addImageStyleMapping('test_breakpoint2', '2x', array(
-      'image_mapping_type' => 'image_style',
-      'image_mapping' => 'large',
-    ));
-    $expected['test_breakpoint2']['2x'] = array(
-      'breakpoint_id' => 'test_breakpoint2',
-      'multiplier' => '2x',
-      'image_mapping_type' => 'image_style',
-      'image_mapping' => 'large',
-    );
-    $this->assertEquals($expected, $entity->getKeyedImageStyleMappings());
   }
 
   /**
diff --git a/core/modules/system/css/system.admin.css b/core/modules/system/css/system.admin.css
index b01e405..1d9a51c 100644
--- a/core/modules/system/css/system.admin.css
+++ b/core/modules/system/css/system.admin.css
@@ -33,13 +33,13 @@
     padding-right: 10px;
     padding-left: 0;
   }
-  .layout-column.half {
+  .layout-column--half {
     width: 50%;
   }
-  .layout-column.quarter {
+  .layout-column--quarter {
     width: 25%;
   }
-  .layout-column.three-quarter {
+  .layout-column--three-quarter {
     width: 75%;
   }
 }
diff --git a/core/modules/system/src/Tests/Theme/EngineNyanCatTest.php b/core/modules/system/src/Tests/Theme/EnginePhpTemplateTest.php
similarity index 62%
rename from core/modules/system/src/Tests/Theme/EngineNyanCatTest.php
rename to core/modules/system/src/Tests/Theme/EnginePhpTemplateTest.php
index bfaa1bb..37ab343 100644
--- a/core/modules/system/src/Tests/Theme/EngineNyanCatTest.php
+++ b/core/modules/system/src/Tests/Theme/EnginePhpTemplateTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\system\Tests\Theme\EngineNyanCatTest.
+ * Contains \Drupal\system\Tests\Theme\EnginePhpTemplateTest.
  */
 
 namespace Drupal\system\Tests\Theme;
@@ -10,11 +10,11 @@
 use Drupal\simpletest\WebTestBase;
 
 /**
- * Tests the multi theme engine support.
+ * Tests theme functions with PHPTemplate.
  *
  * @group Theme
  */
-class EngineNyanCatTest extends WebTestBase {
+class EnginePhpTemplateTest extends WebTestBase {
 
   /**
    * Modules to enable.
@@ -25,7 +25,7 @@ class EngineNyanCatTest extends WebTestBase {
 
   protected function setUp() {
     parent::setUp();
-    \Drupal::service('theme_handler')->install(array('test_theme_nyan_cat_engine'));
+    \Drupal::service('theme_handler')->install(array('test_theme_phptemplate'));
   }
 
   /**
@@ -33,10 +33,10 @@ protected function setUp() {
    */
   function testTemplateOverride() {
     $this->config('system.theme')
-      ->set('default', 'test_theme_nyan_cat_engine')
+      ->set('default', 'test_theme_phptemplate')
       ->save();
     $this->drupalGet('theme-test/template-test');
-    $this->assertText('Success: Template overridden with Nyan Cat theme. All of them', 'Template overridden by Nyan Cat file.');
+    $this->assertText('Success: Template overridden with PHPTemplate theme.', 'Template overridden by PHPTemplate file.');
   }
 
 }
diff --git a/core/modules/system/src/Tests/Theme/StableThemeTest.php b/core/modules/system/src/Tests/Theme/StableThemeTest.php
new file mode 100644
index 0000000..3e03731
--- /dev/null
+++ b/core/modules/system/src/Tests/Theme/StableThemeTest.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Theme\StableThemeTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests the behavior of Stable theme.
+ *
+ * @group Theme
+ */
+class StableThemeTest extends KernelTestBase {
+
+  public static $modules = ['system'];
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface.
+   */
+  protected $themeHandler;
+
+  /**
+   * The theme manager.
+   *
+   * @var \Drupal\Core\Theme\ThemeManagerInterface.
+   */
+  protected $themeManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $this->themeHandler = $this->container->get('theme_handler');
+    $this->themeManager = $this->container->get('theme.manager');
+  }
+
+  /**
+   * Ensure Stable is used by default when no base theme has been defined.
+   */
+  public function testStableIsDefault() {
+    $this->themeHandler->install(['test_basetheme']);
+    $this->config('system.theme')->set('default', 'test_basetheme')->save();
+    $theme = $this->themeManager->getActiveTheme();
+    /** @var \Drupal\Core\Theme\ActiveTheme $base_theme */
+    $base_themes = $theme->getBaseThemes();
+    $base_theme = reset($base_themes);
+    $this->assertTrue($base_theme->getName() == 'stable', "Stable theme has been set on if theme haven't decided to opt-out.");
+  }
+
+  /**
+   * Ensure that its possible to disable Stable by setting base theme to false.
+   */
+  public function testWildWest() {
+    $this->themeHandler->install(['test_wild_west']);
+    $this->config('system.theme')->set('default', 'test_wild_west')->save();
+    $theme = $this->themeManager->getActiveTheme();
+    /** @var \Drupal\Core\Theme\ActiveTheme $base_theme */
+    $base_themes = $theme->getBaseThemes();
+    $this->assertTrue(empty($base_themes), 'No base theme has been set.');
+  }
+
+}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index a8477d3..5972da0 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -905,6 +905,10 @@ function system_get_info($type, $name = NULL) {
     foreach ($list as $shortname => $item) {
       if (!empty($item->status)) {
         $info[$shortname] = $item->info;
+        // Handle when 'base theme: false' is set in a theme .info.yml file.
+        if ($type == 'theme' && empty($info[$shortname]['base theme'])) {
+          unset($info[$shortname]['base theme']);
+        }
       }
     }
   }
diff --git a/core/modules/system/templates/admin-page.html.twig b/core/modules/system/templates/admin-page.html.twig
index 038b1af..b3808e4 100644
--- a/core/modules/system/templates/admin-page.html.twig
+++ b/core/modules/system/templates/admin-page.html.twig
@@ -17,7 +17,7 @@
 <div class="clearfix">
   {{ system_compact_link }}
   {% for container in containers %}
-    <div class="layout-column half">
+    <div class="layout-column--half">
       {% for block in container.blocks %}
         {{ block }}
       {% endfor %}
diff --git a/core/modules/system/tests/modules/module_test/module_test.implementations.inc b/core/modules/system/tests/modules/module_test/module_test.implementations.inc
index a21f7ca..63c866e 100644
--- a/core/modules/system/tests/modules/module_test/module_test.implementations.inc
+++ b/core/modules/system/tests/modules/module_test/module_test.implementations.inc
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * Implements hook_altered_test_hook().
+ * Implements hook_altered_test_hook()
  *
  * @see module_test_module_implements_alter()
  */
diff --git a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine b/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
deleted file mode 100644
index a1da728..0000000
--- a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-/**
- * @file
- * Handles integration of Nyan cat templates because we love kittens.
- */
-
-use Drupal\Core\Extension\Extension;
-
-/**
- * Implements hook_init().
- */
-function nyan_cat_init(Extension $theme) {
-  $theme->load();
-}
-
-/**
- * Implements hook_theme().
- */
-function nyan_cat_theme($existing, $type, $theme, $path) {
-  $templates = drupal_find_theme_functions($existing, array($theme));
-  $templates += drupal_find_theme_templates($existing, '.nyan-cat.html', $path);
-  return $templates;
-}
-
-/**
- * Implements hook_extension().
- */
-function nyan_cat_extension() {
-  return '.nyan-cat.html';
-}
-
-/**
- * Implements hook_render_template().
- *
- * @param string $template_file
- *   The filename of the template to render.
- * @param mixed[] $variables
- *   A keyed array of variables that will appear in the output.
- *
- * @return string
- *   The output generated by the template.
- */
-function nyan_cat_render_template($template_file, $variables) {
-  $output = str_replace('div', 'nyancat', file_get_contents(\Drupal::root() . '/' . $template_file));
-  foreach ($variables as $key => $variable) {
-    if (strpos($output, '9' . $key) !== FALSE) {
-      $output = str_replace('9' . $key, theme_render_and_autoescape($variable), $output);
-    }
-  }
-  return $output;
-}
diff --git a/core/modules/system/tests/themes/test_theme_nyan_cat_engine/test_theme_nyan_cat_engine.info.yml b/core/modules/system/tests/themes/test_theme_nyan_cat_engine/test_theme_nyan_cat_engine.info.yml
deleted file mode 100644
index a911bd0..0000000
--- a/core/modules/system/tests/themes/test_theme_nyan_cat_engine/test_theme_nyan_cat_engine.info.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-name: 'Test theme for Nyan Cat engine'
-type: theme
-description: 'Theme for testing the theme system with the Nyan Cat theme engine'
-version: VERSION
-core: 8.x
-engine: nyan_cat
diff --git a/core/modules/system/tests/themes/test_theme_nyan_cat_engine/test_theme_nyan_cat_engine.theme b/core/modules/system/tests/themes/test_theme_nyan_cat_engine/test_theme_nyan_cat_engine.theme
deleted file mode 100644
index 5b69a12..0000000
--- a/core/modules/system/tests/themes/test_theme_nyan_cat_engine/test_theme_nyan_cat_engine.theme
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-/**
- * Implements hook_preprocess_theme_test_template_test().
- */
-function test_theme_nyan_cat_engine_preprocess_theme_test_template_test(&$variables) {
-  $variables['kittens'] = 'All of them';
-}
diff --git a/core/modules/system/tests/themes/test_theme_nyan_cat_engine/theme_test.template_test.nyan-cat.html b/core/modules/system/tests/themes/test_theme_nyan_cat_engine/theme_test.template_test.nyan-cat.html
deleted file mode 100644
index cb21cb5..0000000
--- a/core/modules/system/tests/themes/test_theme_nyan_cat_engine/theme_test.template_test.nyan-cat.html
+++ /dev/null
@@ -1 +0,0 @@
-Success: Template overridden with Nyan Cat theme. 9kittens
diff --git a/core/modules/system/tests/themes/test_theme_phptemplate/node--1.tpl.php b/core/modules/system/tests/themes/test_theme_phptemplate/node--1.tpl.php
new file mode 100644
index 0000000..81974ce
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_phptemplate/node--1.tpl.php
@@ -0,0 +1,4 @@
+<?php
+  // node--1.tpl.php - Dummy file for finding the template
+?>
+Node Content Dummy
diff --git a/core/modules/system/tests/themes/test_theme_phptemplate/test_theme_phptemplate.info.yml b/core/modules/system/tests/themes/test_theme_phptemplate/test_theme_phptemplate.info.yml
new file mode 100644
index 0000000..da076b1
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_phptemplate/test_theme_phptemplate.info.yml
@@ -0,0 +1,6 @@
+name: 'Test theme PHPTemplate'
+type: theme
+description: 'Theme for testing the theme system with the PHPTemplate engine'
+version: VERSION
+core: 8.x
+engine: phptemplate
diff --git a/core/modules/system/tests/themes/test_theme_phptemplate/test_theme_phptemplate.theme b/core/modules/system/tests/themes/test_theme_phptemplate/test_theme_phptemplate.theme
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_phptemplate/test_theme_phptemplate.theme
@@ -0,0 +1 @@
+<?php
diff --git a/core/modules/system/tests/themes/test_theme_phptemplate/theme_test.template_test.tpl.php b/core/modules/system/tests/themes/test_theme_phptemplate/theme_test.template_test.tpl.php
new file mode 100644
index 0000000..86ef138
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_phptemplate/theme_test.template_test.tpl.php
@@ -0,0 +1,2 @@
+<!-- Output for Theme API test -->
+<?php print 'Success: Template overridden with PHPTemplate theme.'; ?>
diff --git a/core/modules/system/tests/themes/test_wild_west/test_wild_west.info.yml b/core/modules/system/tests/themes/test_wild_west/test_wild_west.info.yml
new file mode 100644
index 0000000..d1fcb82
--- /dev/null
+++ b/core/modules/system/tests/themes/test_wild_west/test_wild_west.info.yml
@@ -0,0 +1,6 @@
+name: Test Wild West
+type: theme
+description: A theme that doesn't use Stable as its base. It tests the wild west instead.
+version: VERSION
+base theme: false
+core: 8.x
diff --git a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php
index d3c9cd3..8349f7a 100644
--- a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php
+++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php
@@ -92,15 +92,7 @@ function formElement(FieldItemListInterface $items, $delta, array $element, arra
    */
   public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
     $element = parent::errorElement($element, $violation, $form, $form_state);
-    if ($element === FALSE) {
-      return FALSE;
-    }
-    elseif (isset($violation->arrayPropertyPath[0])) {
-      return $element[$violation->arrayPropertyPath[0]];
-    }
-    else {
-      return $element;
-    }
+    return ($element === FALSE) ? FALSE : $element[$violation->arrayPropertyPath[0]];
   }
 
 }
diff --git a/core/modules/text/src/Tests/TextFieldTest.php b/core/modules/text/src/Tests/TextFieldTest.php
index a1c9ec3..a22bc5b 100644
--- a/core/modules/text/src/Tests/TextFieldTest.php
+++ b/core/modules/text/src/Tests/TextFieldTest.php
@@ -68,65 +68,6 @@ function testTextFieldValidation() {
   }
 
   /**
-   * Test required long text with file upload.
-   */
-  function testRequiredLongTextWithFileUpload() {
-    // Create a text field.
-    $text_field_name = 'text_long';
-    $field_storage = entity_create('field_storage_config', array(
-      'field_name' => $text_field_name,
-      'entity_type' => 'entity_test',
-      'type' => 'text_with_summary',
-    ));
-    $field_storage->save();
-    entity_create('field_config', array(
-      'field_storage' => $field_storage,
-      'bundle' => 'entity_test',
-      'label' => $this->randomMachineName() . '_label',
-      'required' => TRUE,
-    ))->save();
-
-    // Create a file field.
-    $file_field_name = 'file_field';
-    $field_storage = entity_create('field_storage_config', array(
-      'field_name' => $file_field_name,
-      'entity_type' => 'entity_test',
-      'type' => 'file'
-    ));
-    $field_storage->save();
-    entity_create('field_config', array(
-      'field_storage' => $field_storage,
-      'bundle' => 'entity_test',
-      'label' => $this->randomMachineName() . '_label',
-    ))->save();
-
-    entity_get_form_display('entity_test', 'entity_test', 'default')
-      ->setComponent($text_field_name, array(
-        'type' => 'text_textarea_with_summary',
-      ))
-      ->setComponent($file_field_name, array(
-        'type' => 'file_generic',
-      ))
-      ->save();
-    entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($text_field_name)
-      ->setComponent($file_field_name)
-      ->save();
-
-    $test_file = current($this->drupalGetTestFiles('text'));
-    $edit['files[file_field_0]'] = drupal_realpath($test_file->uri);
-    $this->drupalPostForm('entity_test/add', $edit, 'Upload');
-    $this->assertResponse(200);
-    $edit = array(
-      'text_long[0][value]' => 'Long text'
-    );
-    $this->drupalPostForm(NULL, $edit, 'Save');
-    $this->assertResponse(200);
-    $this->drupalGet('entity_test/1');
-    $this->assertText('Long text');
-  }
-
-  /**
    * Test widgets.
    */
   function testTextfieldWidgets() {
diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js
index 9a19205..53bd135 100644
--- a/core/modules/toolbar/js/toolbar.js
+++ b/core/modules/toolbar/js/toolbar.js
@@ -235,7 +235,7 @@
    *   A string representing a DOM fragment.
    */
   Drupal.theme.toolbarOrientationToggle = function () {
-    return '<div class="toolbar-toggle-orientation"><div class="toolbar-lining">' +
+    return '<div class="toolbar-toggle-orientation-test"><div class="toolbar-lining">' +
       '<button class="toolbar-icon" type="button"></button>' +
       '</div></div>';
   };
diff --git a/core/modules/update/templates/update-version.html.twig b/core/modules/update/templates/update-version.html.twig
index 612f5d4..2d5520f 100644
--- a/core/modules/update/templates/update-version.html.twig
+++ b/core/modules/update/templates/update-version.html.twig
@@ -19,12 +19,12 @@
 #}
 <div class="{{ attributes.class }} project-update__version"{{ attributes|without('class') }}>
   <div class="clearfix">
-    <div class="project-update__version-title layout-column quarter">{{ title }}</div>
-    <div class="project-update__version-details layout-column quarter">
+    <div class="project-update__version-title layout-column layout-column--quarter">{{ title }}</div>
+    <div class="project-update__version-details layout-column layout-column--quarter">
       <a href="{{ version.release_link }}">{{ version.version }}</a>
       <span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span>
     </div>
-    <div class="layout-column half">
+    <div class="layout-column layout-column--half">
       <ul class="project-update__version-links">
         <li class="project-update__download-link">
           <a href="{{ version.download_link }}">{{ 'Download'|t }}</a>
diff --git a/core/modules/views/src/Element/View.php b/core/modules/views/src/Element/View.php
index e12037e..62fc24c 100644
--- a/core/modules/views/src/Element/View.php
+++ b/core/modules/views/src/Element/View.php
@@ -51,7 +51,6 @@ public static function preRenderViewElement($element) {
       $view = $element['#view'];
     }
 
-    $element += $view->element;
     $view->element = &$element;
     // Mark the element as being prerendered, so other code like
     // \Drupal\views\ViewExecutable::setCurrentPage knows that its no longer
diff --git a/core/modules/views/src/Plugin/views/field/Boolean.php b/core/modules/views/src/Plugin/views/field/Boolean.php
index 3a0740d..28a40fd 100644
--- a/core/modules/views/src/Plugin/views/field/Boolean.php
+++ b/core/modules/views/src/Plugin/views/field/Boolean.php
@@ -9,7 +9,6 @@
 
 use Drupal\Component\Utility\Xss as UtilityXss;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\Render\ViewsRenderPipelineSafeString;
 use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
@@ -119,8 +118,7 @@ public function render(ResultRow $values) {
     }
 
     if ($this->options['type'] == 'custom') {
-      $custom_value = $value ? $this->options['type_custom_true'] : $this->options['type_custom_false'];
-      return ViewsRenderPipelineSafeString::create(UtilityXss::filterAdmin($custom_value));
+      return $value ? UtilityXss::filterAdmin($this->options['type_custom_true']) : UtilityXss::filterAdmin($this->options['type_custom_false']);
     }
     elseif (isset($this->formats[$this->options['type']])) {
       return $value ? $this->formats[$this->options['type']][0] : $this->formats[$this->options['type']][1];
diff --git a/core/modules/views/src/Tests/Plugin/StyleGridTest.php b/core/modules/views/src/Tests/Plugin/StyleGridTest.php
index ea212dd..d5d7e60 100644
--- a/core/modules/views/src/Tests/Plugin/StyleGridTest.php
+++ b/core/modules/views/src/Tests/Plugin/StyleGridTest.php
@@ -51,10 +51,6 @@ public function testGrid() {
       $this->assertGrid($view, $alignment, 2);
       $this->assertGrid($view, $alignment, 1);
     }
-
-    // Ensure styles are properly added for grid views.
-    $this->drupalGet('test-grid');
-    $this->assertRaw('views/css/views.module.css');
   }
 
   /**
diff --git a/core/modules/views/src/Tests/Plugin/StyleUnformattedTest.php b/core/modules/views/src/Tests/Plugin/StyleUnformattedTest.php
index af45c3c..ae0ef10 100644
--- a/core/modules/views/src/Tests/Plugin/StyleUnformattedTest.php
+++ b/core/modules/views/src/Tests/Plugin/StyleUnformattedTest.php
@@ -41,7 +41,6 @@ function testDefaultRowClasses() {
       $class = (string) $attributes['class'][0];
       $this->assertTrue(strpos($class, 'views-row') !== FALSE, 'Make sure that the views row class is set right.');
     }
-    $this->assertIdentical($count, $count_result);
   }
 
 }
diff --git a/core/modules/views/src/Tests/ViewAjaxTest.php b/core/modules/views/src/Tests/ViewAjaxTest.php
index 541b6ef..35b5518 100644
--- a/core/modules/views/src/Tests/ViewAjaxTest.php
+++ b/core/modules/views/src/Tests/ViewAjaxTest.php
@@ -55,12 +55,13 @@ public function testAjaxView() {
     $data = Json::decode($response);
 
     $this->assertTrue(isset($data[0]['settings']['views']['ajaxViews']));
+    $this->assertEqual($data[1]['command'], 'add_css');
 
     // Ensure that the view insert command is part of the result.
-    $this->assertEqual($data[1]['command'], 'insert');
-    $this->assertTrue(strpos($data[1]['selector'], '.js-view-dom-id-') === 0);
+    $this->assertEqual($data[2]['command'], 'insert');
+    $this->assertTrue(strpos($data[2]['selector'], '.js-view-dom-id-') === 0);
 
-    $this->setRawContent($data[1]['data']);
+    $this->setRawContent($data[2]['data']);
     $result = $this->xpath('//div[contains(@class, "views-row")]');
     $this->assertEqual(count($result), 2, 'Ensure that two items are rendered in the HTML.');
   }
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index 0fe630c..3638c9c 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -403,7 +403,7 @@ class ViewExecutable implements \Serializable {
    */
   public $element = [
     '#attached' => [
-      'library' => ['views/views.module'],
+      'library' => [],
       'drupalSettings' => [],
     ],
     '#cache' => [],
@@ -456,6 +456,9 @@ public function __construct(ViewEntityInterface $storage, AccountInterface $user
     $this->user = $user;
     $this->viewsData = $views_data;
     $this->routeProvider = $route_provider;
+
+    // Add the default css for a view.
+    $this->element['#attached']['library'][] = 'views/views.module';
   }
 
   /**
diff --git a/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php b/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php
index f9d3add..d5c0054 100644
--- a/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php
+++ b/core/modules/views/tests/src/Unit/EventSubscriber/RouteSubscriberTest.php
@@ -64,7 +64,7 @@ protected function setUp() {
    * @covers ::routeRebuildFinished
    */
   public function testRouteRebuildFinished() {
-    list($display_1, $display_2) = $this->setupMocks();
+    list($view, $executable, $display_1, $display_2) = $this->setupMocks();
 
     $display_1->expects($this->once())
       ->method('collectRoutes')
@@ -95,7 +95,7 @@ public function testOnAlterRoutes() {
 
     $route_event = new RouteBuildEvent($collection, 'views');
 
-    list($display_1, $display_2) = $this->setupMocks();
+    list($view, $executable, $display_1, $display_2) = $this->setupMocks();
 
     // The page_1 display overrides an existing route, so the dynamicRoutes
     // should only call the second display.
@@ -139,8 +139,9 @@ public function testOnAlterRoutes() {
   /**
    * Sets up mocks of Views objects needed for testing.
    *
-   * @return array \Drupal\views\Plugin\views\display\DisplayRouterInterface[]|\PHPUnit_Framework_MockObject_MockObject[]
-   *   An array of two mocked view displays
+   * @return array
+   *   An array of Views mocks, including the executable, the view entity, and
+   *   two display plugins.
    */
   protected function setupMocks() {
     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
@@ -189,7 +190,7 @@ protected function setupMocks() {
     $this->routeSubscriber->applicableViews[] = array('test_id', 'page_2');
     $this->routeSubscriber->applicableViews[] = array('test_id', 'page_3');
 
-    return array($display_1, $display_2);
+    return array($executable, $view, $display_1, $display_2);
   }
 
 }
diff --git a/core/modules/views/tests/themes/views_test_theme/templates/views-view-field.html.twig b/core/modules/views/tests/themes/views_test_theme/templates/views-view-field.html.twig
deleted file mode 100644
index 3360128..0000000
--- a/core/modules/views/tests/themes/views_test_theme/templates/views-view-field.html.twig
+++ /dev/null
@@ -1,11 +0,0 @@
-{#
-/**
- * @file
- * Theme override to display all the fields in a views row.
- *
- * The reason for this template is to override the theme function provided by
- * views to allow tests to run against the twig template.
- */
-#}
-{% include '@views/views-view-field.html.twig' %}
-Use posts instead of twigs to protect your llamas from escaping the field.
diff --git a/core/modules/views_ui/src/Tests/CustomBooleanTest.php b/core/modules/views_ui/src/Tests/CustomBooleanTest.php
index b0ba60a..08fbda8 100644
--- a/core/modules/views_ui/src/Tests/CustomBooleanTest.php
+++ b/core/modules/views_ui/src/Tests/CustomBooleanTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\views_ui\Tests;
 
-use Drupal\Component\Utility\SafeMarkup;
 use Drupal\views\Views;
 
 /**
@@ -102,85 +101,12 @@ public function testCustomOption() {
       $view = Views::getView('test_view');
       $output = $view->preview();
       $output = \Drupal::service('renderer')->renderRoot($output);
-      $this->{$values['test']}(strpos($output, $values['true']), SafeMarkup::format('Expected custom boolean TRUE value %value in output for %type', ['%value' => $values['true'], '%type' => $type]));
-      $this->{$values['test']}(strpos($output, $values['false']), SafeMarkup::format('Expected custom boolean FALSE value %value in output for %type', ['%value' => $values['false'], '%type' => $type]));
-    }
-  }
-
-  /**
-   * Tests the setting and output of custom labels for boolean values.
-   */
-  public function testCustomOptionTemplate() {
-    // Install theme to test with template system.
-    \Drupal::service('theme_handler')->install(['views_test_theme']);
-
-    // Set the default theme for Views preview.
-    $this->config('system.theme')
-      ->set('default', 'views_test_theme')
-      ->save();
-    $this->assertEqual($this->config('system.theme')->get('default'), 'views_test_theme');
-
-   // Add the boolean field handler to the test view.
-    $view = Views::getView('test_view');
-    $view->setDisplay();
-
-    $view->displayHandlers->get('default')->overrideOption('fields', [
-      'age' => [
-        'id' => 'age',
-        'table' => 'views_test_data',
-        'field' => 'age',
-        'relationship' => 'none',
-        'plugin_id' => 'boolean',
-      ],
-    ]);
-    $view->save();
-
-    $this->executeView($view);
-
-    $custom_true = 'Yay';
-    $custom_false = 'Nay';
-
-    // Set up some custom value mappings for different types.
-    $custom_values = array(
-      'plain' => array(
-        'true' => $custom_true,
-        'false' => $custom_false,
-        'test' => 'assertTrue',
-      ),
-      'allowed tag' => array(
-        'true' => '<p>' . $custom_true . '</p>',
-        'false' => '<p>' . $custom_false . '</p>',
-        'test' => 'assertTrue',
-      ),
-      'disallowed tag' => array(
-        'true' => '<script>' . $custom_true . '</script>',
-        'false' => '<script>' . $custom_false . '</script>',
-        'test' => 'assertFalse',
-      ),
-    );
 
-    // Run the same tests on each type.
-    foreach ($custom_values as $type => $values) {
-      $options = array(
-        'options[type]' => 'custom',
-        'options[type_custom_true]' => $values['true'],
-        'options[type_custom_false]' => $values['false'],
-      );
-      $this->drupalPostForm('admin/structure/views/nojs/handler/test_view/default/field/age', $options, 'Apply');
-
-      // Save the view.
-      $this->drupalPostForm('admin/structure/views/view/test_view', array(), 'Save');
-
-      $view = Views::getView('test_view');
-      $output = $view->preview();
-      $output = \Drupal::service('renderer')->renderRoot($output);
-      $this->{$values['test']}(strpos($output, $values['true']), SafeMarkup::format('Expected custom boolean TRUE value %value in output for %type', ['%value' => $values['true'], '%type' => $type]));
-      $this->{$values['test']}(strpos($output, $values['false']), SafeMarkup::format('Expected custom boolean FALSE value %value in output for %type', ['%value' => $values['false'], '%type' => $type]));
-
-      // Assert that we are using the correct template.
-      $this->setRawContent($output);
-      $this->assertText('llama', 'Loaded the correct views-view-field.html.twig template');
+      $replacements = array('%type' => $type);
+      $this->{$values['test']}(strpos($output, $values['true']), format_string('Expected custom boolean TRUE value in output for %type.', $replacements));
+      $this->{$values['test']}(strpos($output, $values['false']), format_string('Expected custom boolean FALSE value in output for %type', $replacements));
     }
   }
 
 }
+
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
deleted file mode 100644
index f43ea13..0000000
--- a/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\KernelTests\Core\Theme\ThemeRenderAndAutoescapeTest.
- */
-
-namespace Drupal\KernelTests\Core\Theme;
-
-use Drupal\Component\Utility\Html;
-use Drupal\Core\Link;
-use Drupal\Core\Render\RenderContext;
-use Drupal\Core\Render\SafeString;
-use Drupal\KernelTests\KernelTestBase;
-
-/**
- * Tests the theme_render_and_autoescape() function.
- *
- * @group Theme
- */
-class ThemeRenderAndAutoescapeTest extends KernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['system'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->installSchema('system', 'router');
-    \Drupal::service('router.builder')->rebuild();
-  }
-
-  /**
-   * @dataProvider providerTestThemeRenderAndAutoescape
-   */
-  public function testThemeRenderAndAutoescape($arg, $expected) {
-    if (is_array($arg) && isset($arg['#type']) && $arg['#type'] === 'link') {
-      $arg = Link::createFromRoute($arg['#title'], $arg['#url']);
-    }
-
-    $context = new RenderContext();
-    // Use a closure here since we need to render with a render context.
-    $theme_render_and_autoescape = function () use ($arg) {
-      return theme_render_and_autoescape($arg);
-    };
-    /** @var \Drupal\Core\Render\RendererInterface $renderer */
-    $renderer = \Drupal::service('renderer');
-    $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape);
-    $this->assertEquals($expected, $output);
-    $this-> assertInternalType('string', $output);
-  }
-
-  /**
-   * Provide test examples.
-   */
-  public function providerTestThemeRenderAndAutoescape() {
-    return [
-      'empty string unchanged' => ['', ''],
-      'simple string unchanged' => ['ab', 'ab'],
-      'int (scalar) cast to string' => [111, '111'],
-      'float (scalar) cast to string' => [2.10, '2.10'],
-      '> is escaped' => ['>', '&gt;'],
-      'SafeString EM tag is unchanged' => [SafeString::create('<em>hi</em>'), '<em>hi</em>'],
-      'SafeString SCRIPT tag is unchanged' => [SafeString::create('<script>alert("hi");</script>'), '<script>alert("hi");</script>'],
-      'EM tag in string is escaped' => ['<em>hi</em>', Html::escape('<em>hi</em>')],
-      'type link render array is rendered' => [['#type' => 'link', '#title' => 'Text', '#url' => '<none>'], '<a href="">Text</a>'],
-      'type markup with EM tags is rendered' => [['#markup' => '<em>hi</em>'], '<em>hi</em>'],
-      'SCRIPT tag in string is escaped' => [
-        '<script>alert(123)</script>',
-        Html::escape('<script>alert(123)</script>')
-      ],
-      'type plain_text render array EM tag is escaped' => [['#plain_text' => '<em>hi</em>'], Html::escape('<em>hi</em>')],
-      'type hidden render array is rendered' => [['#type' => 'hidden', '#name' => 'foo', '#value' => 'bar'], "<input type=\"hidden\" name=\"foo\" value=\"bar\" />\n"],
-    ];
-  }
-
-  /**
-   * Ensures invalid content is handled correctly.
-   *
-   * @expectedException \Exception
-   */
-  public function testThemeEscapeAndRenderNotPrintable() {
-    theme_render_and_autoescape(new NonPrintable());
-  }
-
-}
-
-class NonPrintable { }
diff --git a/core/tests/Drupal/Tests/Component/Utility/FormattableStringTest.php b/core/tests/Drupal/Tests/Component/Utility/FormattableStringTest.php
deleted file mode 100644
index 670b6e5..0000000
--- a/core/tests/Drupal/Tests/Component/Utility/FormattableStringTest.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\Component\Utility\FormattableStringTest.
- */
-
-namespace Drupal\Tests\Component\Utility;
-
-use Drupal\Component\Utility\FormattableString;
-use Drupal\Tests\UnitTestCase;
-
-/**
- * Tests the TranslatableString class.
- *
- * @coversDefaultClass \Drupal\Component\Utility\FormattableString
- * @group utility
- */
-class FormattableStringTest extends UnitTestCase {
-
-  /**
-   * @covers ::__toString
-   * @covers ::jsonSerialize
-   */
-  public function testToString() {
-    $string = 'Can I please have a @replacement';
-    $formattable_string = new FormattableString($string, ['@replacement' => 'kitten']);
-    $text = (string) $formattable_string;
-    $this->assertEquals('Can I please have a kitten', $text);
-    $text = $formattable_string->jsonSerialize();
-    $this->assertEquals('Can I please have a kitten', $text);
-  }
-
-  /**
-   * @covers ::count
-   */
-  public function testCount() {
-    $string = 'Can I please have a @replacement';
-    $formattable_string = new FormattableString($string, ['@replacement' => 'kitten']);
-    $this->assertEquals(strlen($string), $formattable_string->count());
-  }
-
-}
diff --git a/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php b/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
index 156a125..1cef375 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
@@ -427,9 +427,9 @@ public function testSetCacheAuthUser() {
    * @covers ::setCache
    */
   public function testSetCacheWithSafeStrings() {
-    SafeMarkup::setMultiple([
-      'a_safe_string' => ['html' => TRUE],
-    ]);
+    // A call to SafeMarkup::format() is appropriate in this test as a way to
+    // add a string to the safe list in the simplest way possible.
+    SafeMarkup::format('@value', ['@value' => 'a_safe_string']);
     $form_build_id = 'the_form_build_id';
     $form = [
       '#form_id' => 'the_form_id'
diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
index 9ad792e..b4a192d 100644
--- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
@@ -11,7 +11,6 @@
 use Drupal\Core\Template\AttributeArray;
 use Drupal\Core\Template\AttributeString;
 use Drupal\Tests\UnitTestCase;
-use Drupal\Component\Utility\SafeStringInterface;
 
 /**
  * @coversDefaultClass \Drupal\Core\Template\Attribute
@@ -31,18 +30,6 @@ public function testConstructor() {
     $attribute = new Attribute(['selected' => TRUE, 'checked' => FALSE]);
     $this->assertTrue($attribute['selected']->value());
     $this->assertFalse($attribute['checked']->value());
-
-    // Test that non-array values with name "class" are cast to array.
-    $attribute = new Attribute(array('class' => 'example-class'));
-    $this->assertTrue(isset($attribute['class']));
-    $this->assertEquals(new AttributeArray('class', array('example-class')), $attribute['class']);
-
-    // Test that safe string objects work correctly.
-    $safe_string = $this->prophesize(SafeStringInterface::class);
-    $safe_string->__toString()->willReturn('example-class');
-    $attribute = new Attribute(array('class' => $safe_string->reveal()));
-    $this->assertTrue(isset($attribute['class']));
-    $this->assertEquals(new AttributeArray('class', array('example-class')), $attribute['class']);
   }
 
   /**
diff --git a/core/themes/classy/classy.info.yml b/core/themes/classy/classy.info.yml
index bd61ce0..8a1e69d 100644
--- a/core/themes/classy/classy.info.yml
+++ b/core/themes/classy/classy.info.yml
@@ -4,6 +4,7 @@ description: 'A base theme with sensible default CSS classes added. Learn how to
 package: Core
 version: VERSION
 core: 8.x
+base theme: false
 
 libraries:
   - classy/base
diff --git a/core/themes/classy/classy.theme b/core/themes/classy/classy.theme
new file mode 100644
index 0000000..724c9c4
--- /dev/null
+++ b/core/themes/classy/classy.theme
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Classy theme stuff, temporary for testing BC layer.
+ */
+
+/**
+ * Implements hook_library_info_alter().
+ */
+function classy_library_info_alter(&$libraries, $extension) {
+  switch ($extension) {
+    case 'core':
+      if (isset($libraries['drupal.dropbutton'])) {
+        $libraries['drupal.dropbutton']['css']['theme'][base_path() . drupal_get_path('theme', 'classy') . '/css/system/dropbutton.theme.css'] = [];
+      }
+      break;
+    case 'toolbar':
+      if (isset($libraries['toolbar']['js']['js/toolbar.js'])) {
+        unset($libraries['toolbar']['js']['js/toolbar.js']);
+        // @todo Make less ugly. Use weight instead?
+        $libraries['toolbar']['js'] = array_reverse($libraries['toolbar']['js'], TRUE);
+        $libraries['toolbar']['js'][base_path() . drupal_get_path('theme', 'classy') . '/js/toolbar/toolbar.js'] = [];
+        $libraries['toolbar']['js'] = array_reverse($libraries['toolbar']['js'], TRUE);
+      }
+      break;
+  }
+}
diff --git a/core/misc/dropbutton/dropbutton.theme.css b/core/themes/classy/css/system/dropbutton.theme.css
similarity index 100%
copy from core/misc/dropbutton/dropbutton.theme.css
copy to core/themes/classy/css/system/dropbutton.theme.css
diff --git a/core/modules/toolbar/js/toolbar.js b/core/themes/classy/js/toolbar/toolbar.js
similarity index 100%
copy from core/modules/toolbar/js/toolbar.js
copy to core/themes/classy/js/toolbar/toolbar.js
diff --git a/core/themes/engines/phptemplate/phptemplate.engine b/core/themes/engines/phptemplate/phptemplate.engine
new file mode 100644
index 0000000..232f78d
--- /dev/null
+++ b/core/themes/engines/phptemplate/phptemplate.engine
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Handles integration of PHP templates with the Drupal theme system.
+ */
+
+use Drupal\Core\Extension\Extension;
+
+/**
+ * Implements hook_init().
+ */
+function phptemplate_init(Extension $theme) {
+  $theme->load();
+}
+
+/**
+ * Implements hook_theme().
+ */
+function phptemplate_theme($existing, $type, $theme, $path) {
+  $templates = drupal_find_theme_functions($existing, array($theme));
+  $templates += drupal_find_theme_templates($existing, '.tpl.php', $path);
+  return $templates;
+}
+
+/**
+ * Implements hook_extension().
+ */
+function phptemplate_extension() {
+  return '.tpl.php';
+}
+
+/**
+ * Implements hook_render_template().
+ *
+ * Renders a system default template, which is essentially a PHP template.
+ *
+ * @param $template_file
+ *   The filename of the template to render.
+ * @param $variables
+ *   A keyed array of variables that will appear in the output.
+ *
+ * @return
+ *   The output generated by the template.
+ */
+function phptemplate_render_template($template_file, $variables) {
+  // Extract the variables to a local namespace
+  extract($variables, EXTR_SKIP);
+
+  // Start output buffering
+  ob_start();
+
+  // Include the template file
+  include \Drupal::root() . '/' . $template_file;
+
+  // End buffering and return its contents
+  return ob_get_clean();
+}
diff --git a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.info.yml b/core/themes/engines/phptemplate/phptemplate.info.yml
similarity index 76%
rename from core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.info.yml
rename to core/themes/engines/phptemplate/phptemplate.info.yml
index 342191c..2bea7a0 100644
--- a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.info.yml
+++ b/core/themes/engines/phptemplate/phptemplate.info.yml
@@ -1,5 +1,5 @@
 type: theme_engine
-name: Nyan cat
+name: PHPTemplate
 core: 8.x
 version: VERSION
 package: Core
diff --git a/core/misc/dropbutton/dropbutton.theme.css b/core/themes/stable/css/system/dropbutton.theme.css
similarity index 100%
rename from core/misc/dropbutton/dropbutton.theme.css
rename to core/themes/stable/css/system/dropbutton.theme.css
diff --git a/core/modules/toolbar/js/toolbar.js b/core/themes/stable/js/toolbar/toolbar.js
similarity index 100%
copy from core/modules/toolbar/js/toolbar.js
copy to core/themes/stable/js/toolbar/toolbar.js
diff --git a/core/themes/stable/stable.info.yml b/core/themes/stable/stable.info.yml
new file mode 100644
index 0000000..50e7e3a
--- /dev/null
+++ b/core/themes/stable/stable.info.yml
@@ -0,0 +1,7 @@
+name: Stable
+type: theme
+description: 'Shelter from the Wild Wild West.'
+package: Core
+version: VERSION
+core: 8.x
+base theme: false
diff --git a/core/themes/stable/stable.theme b/core/themes/stable/stable.theme
new file mode 100644
index 0000000..b9effc2
--- /dev/null
+++ b/core/themes/stable/stable.theme
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Functions to provide backwards compatibility for themes.
+ */
+
+/**
+ * Implements hook_library_info_alter().
+ */
+function stable_library_info_alter(&$libraries, $extension) {
+  switch ($extension) {
+    case 'core':
+      if (isset($libraries['drupal.dropbutton'])) {
+        $libraries['drupal.dropbutton']['css']['theme'][base_path() . drupal_get_path('theme', 'stable') . '/css/system/dropbutton.theme.css'] = [];
+      }
+      break;
+    case 'toolbar':
+      if (isset($libraries['toolbar']['js']['js/toolbar.js'])) {
+        unset($libraries['toolbar']['js']['js/toolbar.js']);
+        // @todo Make less ugly. Use weight instead?
+        $libraries['toolbar']['js'] = array_reverse($libraries['toolbar']['js'], TRUE);
+        $libraries['toolbar']['js'][base_path() . drupal_get_path('theme', 'stable') . '/js/toolbar/toolbar.js'] = [];
+        $libraries['toolbar']['js'] = array_reverse($libraries['toolbar']['js'], TRUE);
+      }
+      break;
+  }
+}
+
+/**
+ * Implements hook_theme().
+ */
+function stable_theme($existing, $type, $theme, $path) {
+  return [];
+}
+
+/**
+ * Implements hook_theme_registry_alter().
+ */
+function stable_theme_registry_alter(&$theme_registry) {
+}
diff --git a/core/themes/stark/stark.info.yml b/core/themes/stark/stark.info.yml
index 70609c1..f6c9ba5 100644
--- a/core/themes/stark/stark.info.yml
+++ b/core/themes/stark/stark.info.yml
@@ -4,3 +4,4 @@ description: 'An intentionally plain theme with no styling to demonstrate defaul
 package: Core
 version: VERSION
 core: 8.x
+base theme: false
