diff --git a/composer.lock b/composer.lock
index ddaa66ee82..7e7e24daf3 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4194,23 +4194,23 @@
         },
         {
             "name": "symfony/phpunit-bridge",
-            "version": "v3.2.8",
+            "version": "dev-master",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/phpunit-bridge.git",
-                "reference": "00916603c524b8048906de460b7ea0dfa1651281"
+                "reference": "04fea34617fcf1c069088f134fb018cd348845c6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/00916603c524b8048906de460b7ea0dfa1651281",
-                "reference": "00916603c524b8048906de460b7ea0dfa1651281",
+                "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/04fea34617fcf1c069088f134fb018cd348845c6",
+                "reference": "04fea34617fcf1c069088f134fb018cd348845c6",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "conflict": {
-                "phpunit/phpunit": ">=6.0"
+                "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
             },
             "suggest": {
                 "ext-zip": "Zip support is required when using bin/simple-phpunit",
@@ -4222,7 +4222,7 @@
             "type": "symfony-bridge",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.2-dev"
+                    "dev-master": "4.0-dev"
                 }
             },
             "autoload": {
@@ -4252,13 +4252,14 @@
             ],
             "description": "Symfony PHPUnit Bridge",
             "homepage": "https://symfony.com",
-            "time": "2017-04-12T14:13:17+00:00"
+            "time": "2017-10-13T16:56:12+00:00"
         }
     ],
     "aliases": [],
     "minimum-stability": "dev",
     "stability-flags": {
-        "behat/mink": 20
+        "behat/mink": 20,
+        "symfony/phpunit-bridge": 20
     },
     "prefer-stable": true,
     "prefer-lowest": false,
diff --git a/core/composer.json b/core/composer.json
index c802e5d6ee..a7f20eac65 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -47,7 +47,7 @@
         "phpunit/phpunit": ">=4.8.35 <5",
         "phpspec/prophecy": "^1.4",
         "symfony/css-selector": "~3.2.8",
-        "symfony/phpunit-bridge": "~3.2.8"
+        "symfony/phpunit-bridge": "dev-master"
     },
     "replace": {
         "drupal/action": "self.version",
diff --git a/core/core.services.yml b/core/core.services.yml
index bcf528b10b..6a67b6e9ae 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -709,7 +709,7 @@ services:
     class: Stack\StackedHttpKernel
   http_kernel.basic:
     class: Symfony\Component\HttpKernel\HttpKernel
-    arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']
+    arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack', '@controller_resolver']
   http_middleware.negotiation:
     class: Drupal\Core\StackMiddleware\NegotiationMiddleware
     tags:
diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index 284d1835e9..19676be9f7 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -58,7 +58,9 @@ function drupal_error_levels() {
  *   occurred.
  */
 function _drupal_error_handler_real($error_level, $message, $filename, $line, $context) {
-  if ($error_level & error_reporting()) {
+  // If the site is a test site then fail for user deprecations so they can be
+  // caught by the deprecation error handler.
+  if (($error_level & error_reporting()) || (DRUPAL_TEST_IN_CHILD_SITE && $error_level === E_USER_DEPRECATED)) {
     $types = drupal_error_levels();
     list($severity_msg, $severity_level) = $types[$error_level];
     $backtrace = debug_backtrace();
diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php
index c16a087449..1ab78d037c 100644
--- a/core/lib/Drupal/Core/Controller/ControllerResolver.php
+++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php
@@ -168,4 +168,24 @@ protected function doGetArguments(Request $request, $controller, array $paramete
     return $arguments;
   }
 
+  /**
+   * {@inheritdoc}
+   *
+   * @todo Consider using \Symfony\Component\HttpKernel\Controller\ArgumentResolver instead.
+   */
+  public function getArguments(Request $request, $controller) {
+    if (is_array($controller)) {
+      $r = new \ReflectionMethod($controller[0], $controller[1]);
+    }
+    elseif (is_object($controller) && !$controller instanceof \Closure) {
+      $r = new \ReflectionObject($controller);
+      $r = $r->getMethod('__invoke');
+    }
+    else {
+      $r = new \ReflectionFunction($controller);
+    }
+
+    return $this->doGetArguments($request, $controller, $r->getParameters());
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
index 51a29d860b..5b6a22874e 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
@@ -120,4 +120,20 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
     return $values;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setValue($values, $notify = TRUE) {
+    $keys = array_keys($this->definition->getPropertyDefinitions());
+    // Treat the values as property value of the main property, if no array is
+    // given.
+    if (isset($values) && !is_array($values)) {
+      $values = [$keys[0] => $values];
+    }
+    // Since Boolean values are stored as 0 or 1 cast to an integer so that the
+    // value matches the stored value.
+    $values[$keys[0]] = (int) $values[$keys[0]];
+    parent::setValue($values, $notify);
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 48341492bd..c72bf8948a 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -46,6 +46,11 @@ public function register(ContainerBuilder $container) {
     $container
       ->register('router.dumper', 'Drupal\Core\Routing\NullMatcherDumper');
 
+    // In the super early installer schema are meaningless because schema
+    // storage only looks at installed modules and no modules are installed.
+    $container
+      ->register('config.storage.schema', 'Drupal\Core\Config\NullStorage');
+
     // Remove the cache tags invalidator tag from the cache tags storage, so
     // that we don't call it when cache tags are invalidated very early in the
     // installer.
diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
index 264a511172..06fc8dd652 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
@@ -17,13 +17,21 @@ class TwigNodeTrans extends \Twig_Node {
   /**
    * {@inheritdoc}
    */
-  public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) {
-    parent::__construct([
-      'count' => $count,
-      'body' => $body,
-      'plural' => $plural,
-      'options' => $options,
-    ], [], $lineno, $tag);
+  public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node $options = NULL, $lineno, $tag = NULL) {
+    $nodes = [];
+    if (NULL !== $body) {
+      $nodes['body'] = $body;
+    }
+    if (NULL !== $count) {
+      $nodes['count'] = $count;
+    }
+    if (NULL !== $plural) {
+      $nodes['plural'] = $plural;
+    }
+    if (NULL !== $options) {
+      $nodes['options'] = $options;
+    }
+    parent::__construct($nodes, [], $lineno, $tag);
   }
 
   /**
@@ -32,29 +40,27 @@ public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_N
   public function compile(\Twig_Compiler $compiler) {
     $compiler->addDebugInfo($this);
 
-    $options = $this->getNode('options');
-
     list($singular, $tokens) = $this->compileString($this->getNode('body'));
     $plural = NULL;
 
-    if (NULL !== $this->getNode('plural')) {
+    if ($this->hasNode('plural')) {
       list($plural, $pluralTokens) = $this->compileString($this->getNode('plural'));
       $tokens = array_merge($tokens, $pluralTokens);
     }
 
     // Start writing with the function to be called.
-    $compiler->write('echo ' . (empty($plural) ? 't' : '\Drupal::translation()->formatPlural') . '(');
+    $compiler->write('echo ' . ($this->hasNode('plural') ? '\Drupal::translation()->formatPlural' : 't') . '(');
 
     // Move the count to the beginning of the parameters list.
-    if (!empty($plural)) {
-      $compiler->raw('abs(')->subcompile($this->getNode('count'))->raw('), ');
+    if ($this->hasNode('plural')) {
+      $compiler->raw('abs(')->subcompile($this->hasNode('count') ? $this->getNode('count') : NULL)->raw('), ');
     }
 
     // Write the singular text parameter.
     $compiler->subcompile($singular);
 
     // Write the plural text parameter, if necessary.
-    if (!empty($plural)) {
+    if ($this->hasNode('plural')) {
       $compiler->raw(', ')->subcompile($plural);
     }
 
@@ -67,8 +73,8 @@ public function compile(\Twig_Compiler $compiler) {
     $compiler->raw(')');
 
     // Write any options passed.
-    if (!empty($options)) {
-      $compiler->raw(', ')->subcompile($options);
+    if ($this->hasNode('options')) {
+      $compiler->raw(', ')->subcompile($this->getNode('options'));
     }
 
     // Write function closure.
@@ -103,7 +109,7 @@ protected function compileString(\Twig_Node $body) {
       $text = '';
 
       foreach ($body as $node) {
-        if (get_class($node) === 'Twig_Node' && $node->getNode(0) instanceof \Twig_Node_SetTemp) {
+        if (get_class($node) === 'Twig_Node') {
           $node = $node->getNode(1);
         }
 
@@ -157,7 +163,7 @@ protected function compileString(\Twig_Node $body) {
             if (!is_null($args)) {
               $argName = $args->getAttribute('name');
             }
-            $expr = new \Twig_Node_Expression_Name($argName, $n->getLine());
+            $expr = new \Twig_Node_Expression_Name($argName, $n->getTemplateLine());
           }
           $placeholder = sprintf('%s%s', $argPrefix, $argName);
           $text .= $placeholder;
@@ -176,7 +182,7 @@ protected function compileString(\Twig_Node $body) {
       $text = $body->getAttribute('data');
     }
 
-    return [new \Twig_Node([new \Twig_Node_Expression_Constant(trim($text), $body->getLine())]), $tokens];
+    return [new \Twig_Node([new \Twig_Node_Expression_Constant(trim($text), $body->getTemplateLine())]), $tokens];
   }
 
 }
diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
index 1ebfa57de9..f63edeeef7 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
@@ -33,7 +33,7 @@ protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) {
         return $node;
       }
       $class = get_class($node);
-      $line = $node->getLine();
+      $line = $node->getTemplateLine();
       return new $class(
         new \Twig_Node_Expression_Function('render_var', new \Twig_Node([$node->getNode('expr')]), $line),
         $line
diff --git a/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php b/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php
index 3c4d1427a8..86e9311d45 100644
--- a/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php
+++ b/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php
@@ -41,7 +41,14 @@ public function __invoke() {
                   // the header.
                   $parameters = unserialize(urldecode($header_value));
                   if (count($parameters) === 3) {
-                    throw new \Exception($parameters[1] . ': ' . $parameters[0] . "\n" . Error::formatBacktrace([$parameters[2]]));
+                    if ($parameters[1] === 'User deprecated function') {
+                      // Fire the same deprecation message to allow it to be
+                      // caught.
+                      @trigger_error((string) $parameters[0], E_USER_DEPRECATED);
+                    }
+                    else {
+                      throw new \Exception($parameters[1] . ': ' . $parameters[0] . "\n" . Error::formatBacktrace([$parameters[2]]));
+                    }
                   }
                   else {
                     throw new \Exception('Error thrown with the wrong amount of parameters.');
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraint.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraint.php
index d20f54a723..798805e7de 100644
--- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraint.php
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraint.php
@@ -16,6 +16,7 @@
  */
 class AllowedValuesConstraint extends Choice {
 
+  public $strict = TRUE;
   public $minMessage = 'You must select at least %limit choice.|You must select at least %limit choices.';
   public $maxMessage = 'You must select at most %limit choice.|You must select at most %limit choices.';
 
diff --git a/core/modules/system/tests/modules/deprecation_test/deprecation_test.module b/core/modules/system/tests/modules/deprecation_test/deprecation_test.module
new file mode 100644
index 0000000000..e255021d65
--- /dev/null
+++ b/core/modules/system/tests/modules/deprecation_test/deprecation_test.module
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Contains functions for testing calling deprecated functions in tests.
+ */
+
+/**
+ * A deprecated function.
+ *
+ * @return string
+ *   A known return value of 'known_return_value'.
+ *
+ * @deprecated in Drupal 8.4.x. Might be removed before Drupal 9.0.0. This is
+ *   the deprecation message for deprecated_test_function().
+ */
+function deprecation_test_function() {
+  @trigger_error('This is the deprecation message for deprecation_test_function().', E_USER_DEPRECATED);
+  return 'known_return_value';
+}
diff --git a/core/modules/system/tests/modules/deprecation_test/deprecation_test.routing.yml b/core/modules/system/tests/modules/deprecation_test/deprecation_test.routing.yml
new file mode 100644
index 0000000000..3ef71b806f
--- /dev/null
+++ b/core/modules/system/tests/modules/deprecation_test/deprecation_test.routing.yml
@@ -0,0 +1,6 @@
+deprecation_test.route:
+  path: '/this-calls-a-deprecated-method'
+  defaults:
+    _controller: \Drupal\deprecation_test\DeprecatedController::deprecatedMethod
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php b/core/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php
new file mode 100644
index 0000000000..44cf330cc8
--- /dev/null
+++ b/core/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\deprecation_test;
+
+/**
+ * Defines a controller that calls a deprecated method.
+ */
+class DeprecatedController {
+
+  /**
+   * Controller callback.
+   *
+   * @return array
+   *   Render array.
+   */
+  public function deprecatedMethod() {
+    return [
+      '#markup' => deprecation_test_function(),
+    ];
+  }
+
+}
diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml
index 579b5119cb..fb5da80448 100644
--- a/core/modules/system/tests/modules/system_test/system_test.routing.yml
+++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
@@ -194,5 +194,7 @@ system_test.echo_utf8:
   path: '/system-test/Ȅchȏ/meφΩ/{text}'
   defaults:
     _controller: '\Drupal\system_test\Controller\SystemTestController::simpleEcho'
+  options:
+    utf8: 'TRUE'
   requirements:
     _access: 'TRUE'
diff --git a/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php b/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php
new file mode 100644
index 0000000000..bc843c31a1
--- /dev/null
+++ b/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Drupal\FunctionalTests\Core\Test;
+
+use Drupal\Core\Url;
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests Drupal's integration with Symfony PHPUnit Bridge.
+ *
+ * @group Test
+ * @group legacy
+ */
+class PhpUnitBridgeTest extends BrowserTestBase {
+
+  protected static $modules = ['deprecation_test'];
+
+  /**
+   * @expectedDeprecation This is the deprecation message for deprecation_test_function().
+   */
+  public function testSilencedError() {
+    $this->assertEquals('known_return_value', deprecation_test_function());
+  }
+
+  /**
+   * @expectedDeprecation This is the deprecation message for deprecation_test_function().
+   */
+  public function testErrorOnSiteUnderTest() {
+    $this->drupalGet(Url::fromRoute('deprecation_test.route'));
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php
new file mode 100644
index 0000000000..d82a37b906
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Test;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass;
+
+/**
+ * Test how kernel tests interact with deprecation errors.
+ *
+ * @group Test
+ * @group legacy
+ */
+class PhpUnitBridgeTest extends KernelTestBase {
+
+  public static $modules = ['deprecation_test'];
+
+  /**
+   * @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated.
+   */
+  public function testDeprecatedClass() {
+    $deprecated = new FixtureDeprecatedClass();
+    $this->assertEquals('test', $deprecated->testFunction());
+  }
+
+  /**
+   * @expectedDeprecation This is the deprecation message for deprecation_test_function().
+   */
+  public function testDeprecatedFunction() {
+    $this->assertEquals('known_return_value', \deprecation_test_function());
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeIsolatedTest.php b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeIsolatedTest.php
new file mode 100644
index 0000000000..72806b44c3
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeIsolatedTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\Tests\Core\Test;
+
+use Drupal\Tests\UnitTestCase;
+use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass;
+
+/**
+ * Test how unit tests interact with deprecation errors in process isolation.
+ *
+ * @runTestsInSeparateProcesses
+ *
+ * @group Test
+ * @group legacy
+ */
+class PhpUnitBridgeIsolatedTest extends UnitTestCase {
+
+  /**
+   * @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated.
+   */
+  public function testDeprecatedClass() {
+    $deprecated = new FixtureDeprecatedClass();
+    $this->assertEquals('test', $deprecated->testFunction());
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeTest.php b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeTest.php
new file mode 100644
index 0000000000..73ba0de167
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeTest.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\Tests\Core\Test;
+
+use Drupal\Tests\UnitTestCase;
+use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass;
+
+/**
+ * Test how unit tests interact with deprecation errors.
+ *
+ * @group Test
+ * @group legacy
+ */
+class PhpUnitBridgeTest extends UnitTestCase {
+
+  /**
+   * @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated.
+   */
+  public function testDeprecatedClass() {
+    $deprecated = new FixtureDeprecatedClass();
+    $this->assertEquals('test', $deprecated->testFunction());
+  }
+
+  public function testDeprecatedFunction() {
+    $this->markTestIncomplete('Modules are not loaded for unit tests, so deprecated_test_function() will not be available.');
+    $this->assertEquals('known_return_value', \deprecation_test_function());
+  }
+
+}
