Index: src/wp-includes/default-filters.php
===================================================================
--- src/wp-includes/default-filters.php	(revision 29885)
+++ src/wp-includes/default-filters.php	(working copy)
@@ -196,6 +196,7 @@
 add_filter( 'http_request_host_is_external', 'allowed_http_request_hosts', 10, 2 );
 
 // Actions
+add_action( 'wp_head',             '_wp_render_title_tag',            1     );
 add_action( 'wp_head',             'wp_enqueue_scripts',              1     );
 add_action( 'wp_head',             'feed_links',                      2     );
 add_action( 'wp_head',             'feed_links_extra',                3     );
Index: src/wp-includes/general-template.php
===================================================================
--- src/wp-includes/general-template.php	(revision 29885)
+++ src/wp-includes/general-template.php	(working copy)
@@ -731,6 +731,111 @@
 }
 
 /**
+ * Display <title> tag with contents.
+ *
+ * @since 4.1.0
+ * @access private
+ */
+function _wp_render_title_tag() {
+	if ( ! current_theme_supports( 'title-tag' ) ) {
+		return;
+	}
+
+	// This can only work internally on wp_head.
+	if ( ! did_action( 'wp_head' ) && ( ! function_exists( 'doing_action' ) || ! doing_action( 'wp_head' ) ) ) {
+		return;
+	}
+
+	// If wp_title() has fired, don't do anything.
+	if ( did_action( 'wp_title' ) ) {
+		return;
+	}
+
+	// Allow early filtering, if this returns a title skip all the logic below and print it.
+	if ( null !== $pre = apply_filters( 'pre_wp_title_tag', null ) ) {
+		echo "<title>$pre<title>\n";
+
+		return;
+	}
+
+	global $page, $paged, $wp_locale;
+
+	$title = array();
+
+	if ( is_home() && is_front_page() ) {
+		$title[] = get_bloginfo( 'name', 'display' );
+
+		$description = get_bloginfo( 'description', 'display' );
+		if ( ! empty( $description ) ) {
+			$title[] = $description;
+		}
+
+	// If we're on the blog page and that page is not the homepage, use the container page's title
+	} elseif ( is_home() && ! is_front_page() ) {
+		$title[] = get_post( get_option( 'page_for_posts' ) )->post_title;
+
+	} elseif ( ! is_home() && is_front_page() ) {
+		$title[] = single_post_title( '', false );
+
+	// If we're on a post / page
+	} elseif ( is_singular() ) {
+		$title[] = single_post_title( '', false );
+
+	// If we're on a category or tag or taxonomy archive
+	} elseif ( is_category() || is_tag() || is_tax() ) {
+		$title[] = single_term_title( '', false );
+
+		// If it's a search
+	} elseif ( is_search() ) {
+		/* translators: 1: search phrase */
+		$title[] = sprintf( esc_html__( 'Search Results for "%1$s"' ), strip_tags( get_query_var( 's' ) ) );
+
+	// If we're on an author archive
+	} elseif ( is_author() ) {
+		if ( $author = get_queried_object() ) {
+			$title[] = $author->display_name;
+		}
+
+	// If we're on a post type archive
+	} elseif ( is_post_type_archive() ) {
+		$title[] = post_type_archive_title( '', false );
+
+	} elseif ( is_year() ) {
+		$title[] = get_the_date( _x( 'Y', 'yearly archives date format' ) );
+
+	} elseif ( is_month() ) {
+		$title[] = get_the_date( _x( 'F Y', 'monthly archives date format' ) );
+
+	// If it's a date archive
+	} elseif ( is_day() ) {
+		$title[] = get_the_date();
+
+	// If it's a 404 page
+	} elseif ( is_404() ) {
+		$title[] = esc_html__( 'Page not found' );
+	}
+
+	// Add a page number if necessary:
+	if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() ) {
+		$title[] = sprintf( esc_html__( 'Page %s' ), max( $paged, $page ) );
+	}
+
+	if ( ! is_home() && ! is_front_page() ) {
+		$title[] = get_bloginfo( 'name', 'display' );
+	}
+
+	$title = apply_filters( 'wp_title_tag_array', $title );
+
+	// sep, defaults to - as the separator between two parts of the title
+	$sep = '|';
+
+	$title = implode( " $sep ", $title );
+	$title = apply_filters( 'wp_title_tag', $title, $sep );
+
+	echo "<title>$title</title>\n";
+}
+
+/**
  * Display or retrieve page title for all areas of blog.
  *
  * By default, the page title will display the separator before the page title,
Index: src/wp-includes/theme.php
===================================================================
--- src/wp-includes/theme.php	(revision 29885)
+++ src/wp-includes/theme.php	(working copy)
@@ -1607,6 +1607,17 @@
 				define( 'BACKGROUND_IMAGE', $args[0]['default-image'] );
 
 			break;
+			// ensure that 'title-tag' is accessible in the admin.
+
+		case 'title-tag' :
+			if ( function_exists( 'doing_action' )
+			   && ! doing_action( 'after_setup_theme' ) // can be called here
+			   && ! doing_action( 'init' ) // can also be called here
+			   && ( doing_action() || did_action( 'wp_loaded' ) ) // can be called in functions.php but must happen before wp_loaded, i.e. not in header.php
+			) {
+				_doing_it_wrong( "add_theme_support( 'title-tag' )", __( "You need to add support before 'wp_loaded'." ), '4.1.0' );
+			}
+			break;
 	}
 
 	$_wp_theme_features[ $feature ] = $args;
