Index: src/wp-content/plugins/hello.php
===================================================================
--- src/wp-content/plugins/hello.php	(revision 44583)
+++ src/wp-content/plugins/hello.php	(working copy)
@@ -80,5 +80,3 @@
 }
 
 add_action( 'admin_head', 'dolly_css' );
-
-
Index: src/wp-includes/class-wp-shutdown-handler.php
===================================================================
--- src/wp-includes/class-wp-shutdown-handler.php	(revision 44583)
+++ src/wp-includes/class-wp-shutdown-handler.php	(working copy)
@@ -122,14 +122,23 @@
 		}
 
 		// Otherwise, fail with a `wp_die()` message.
-		$message = $this->get_error_message_markup();
+		$message = $this->get_error_message();
+		$status  = 500;
+		$args    = array();
 
-		// `wp_die()` wraps the message in paragraph tags, so let's just try working around that.
-		if ( substr( $message, 0, 3 ) === '<p>' && substr( $message, -4 ) === '</p>' ) {
-			$message = substr( $message, 3, -4 );
+		if ( function_exists( 'admin_url' ) ) {
+			$args['back_link'] = admin_url();
+			$args['back_text'] = __( 'Log into the admin backend to fix this.' );
 		}
 
-		wp_die( $message, '', 500 );
+		if ( class_exists( 'WP_Error', false ) ) {
+			$error_code = 'php_fatal_error';
+			$message    = new WP_Error( $error_code, $message, array_merge( $args, array( 'status' => $status ) ) );
+		}
+		// Add response
+		$args['response'] = $status;
+
+		wp_die( $message, '', $args );
 	}
 
 	/**
@@ -139,7 +148,7 @@
 	 *
 	 * @return string Error message HTML output.
 	 */
-	protected function get_error_message_markup() {
+	protected function get_error_message() {
 		if ( ! function_exists( '__' ) ) {
 			function __( $text ) {
 				return $text;
@@ -146,19 +155,8 @@
 			}
 		}
 
-		$message = sprintf(
-			'<p>%s</p>',
-			__( 'The site is experiencing technical difficulties.' )
-		);
+		$message = 	__( 'The site is experiencing technical difficulties.' );
 
-		if ( function_exists( 'admin_url' ) ) {
-			$message .= sprintf(
-				'<hr><p><em>%s <a href="%s">%s</a></em></p>',
-				__( 'Are you the site owner?' ),
-				admin_url(),
-				__( 'Log into the admin backend to fix this.' )
-			);
-		}
 
 		if ( function_exists( 'apply_filters' ) ) {
 			/**
Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 44583)
+++ src/wp-includes/functions.php	(working copy)
@@ -2970,6 +2970,15 @@
 		 * @param callable $function Callback function name.
 		 */
 		$function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
+	} else if ( wp_is_json_request()  ) {
+		/**
+		 * Filters the callback for killing WordPress execution for JSON requests.
+		 *
+		 * @since 5.1.0
+		 *
+		 * @param callable $function Callback function name.
+		 */
+		$function = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' );
 	} elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
 		/**
 		 * Filters the callback for killing WordPress execution for XML-RPC requests.
@@ -3007,10 +3016,11 @@
  * @param string|array    $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
-	$defaults = array( 'response' => 500 );
-	$r        = wp_parse_args( $args, $defaults );
 
 	$have_gettext = function_exists( '__' );
+	$back_text    = $have_gettext ? __( '&laquo; Back' ) : '&laquo; Back';
+	$defaults     = array( 'response' => 500, 'back_text' => $back_text );
+	$r            = wp_parse_args( $args, $defaults );
 
 	if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
 		if ( empty( $title ) ) {
@@ -3036,8 +3046,8 @@
 	}
 
 	if ( isset( $r['back_link'] ) && $r['back_link'] ) {
-		$back_text = $have_gettext ? __( '&laquo; Back' ) : '&laquo; Back';
-		$message  .= "\n<p><a href='javascript:history.back()'>$back_text</a></p>";
+		$back_link = ( is_bool( $r['back_link'] ) ) ? "javascript:history.back()" : $r['back_link'];
+		$message   .= "\n<p><a href='" . $back_link . "'>" . $r['back_text'] . "</a></p>";
 	}
 
 	if ( ! did_action( 'admin_head' ) ) :
@@ -3229,6 +3239,77 @@
 }
 
 /**
+ * Kill WordPress execution and display JSON message with error message.
+ *
+ * This is the handler for wp_die when processing JSON requests.
+ *
+ * @since 5.1.0
+ * @access private
+ *
+ * @param string       $message Error message.
+ * @param string       $title   Optional. Error title. Default empty.
+ * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
+ */
+
+function _json_wp_die_handler( $message, $title = '', $args = array() ) {
+	$defaults = array( 'response' => 500, 'code' => '_json_wp_die_handler' );
+	$r = wp_parse_args( $args, $defaults );
+
+	$data = array();
+	if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
+		$errors = array();
+		foreach ( (array) $message->errors as $code => $messages ) {
+			foreach ( (array) $messages as $display_message ) {
+				$errors[] = array(
+					'code'    => $code,
+					'message' => $display_message,
+					'data'    => $message->get_error_data( $code ),
+				);
+			}
+		}
+
+		$data = $errors[0];
+		if ( count( $errors ) > 1 ) {
+			// Remove the primary error.
+			array_shift( $errors );
+			$data['additional_errors'] = $errors;
+		}
+	} else {
+		$data = array(
+			'code'    => $r['code'],
+			'message' => $message,
+		);
+	}
+
+	if ( ! isset( $data['data']['status'] ) ) {
+		$data['data']['status'] = $r['response'];
+	}
+
+	if ( isset( $_GET['_jsonp'] ) ) {
+		$jsonp_callback = $_GET['_jsonp'];
+		$content_type   = 'application/javascript';
+	} else {
+		$jsonp_callback = false;
+		$content_type   = 'application/json';
+	}
+
+	if ( ! headers_sent() ) {
+		$blog_charset = 'utf-8'; // Default charset.
+		header( 'Content-Type: ' . $content_type . '; charset=' . $blog_charset );
+		status_header( $data['data']['status'] );
+		nocache_headers();
+	}
+
+	$result         = wp_json_encode( $data );
+	if ( $jsonp_callback ) {
+		echo '/**/' . $jsonp_callback . '(' . $result . ')';
+	} else {
+		echo $result;
+	}
+	die();
+}
+
+/**
  * Kill WordPress ajax execution.
  *
  * This is the handler for wp_die when processing Ajax requests.
Index: src/wp-includes/load.php
===================================================================
--- src/wp-includes/load.php	(revision 44583)
+++ src/wp-includes/load.php	(working copy)
@@ -1473,15 +1473,21 @@
  *
  * @since 5.0.0
  *
- * @return bool True if Accepts or Content-Type headers contain application/json, false otherwise.
+ * @return bool True if Accepts or Content-Type headers contain application/json or 'application/javascript', false otherwise.
  */
 function wp_is_json_request() {
 
-	if ( isset( $_SERVER['HTTP_ACCEPT'] ) && false !== strpos( $_SERVER['HTTP_ACCEPT'], 'application/json' ) ) {
-		return true;
+	$accepted = array( 'application/json', 'application/javascript' );
+
+	if ( isset( $_SERVER['HTTP_ACCEPT'] ) ) {
+		foreach ( $accepted as $type ) {
+			if ( false !== strpos( $_SERVER['HTTP_ACCEPT'], $type ) ) {
+				return true;
+			}
+		}
 	}
 
-	if ( isset( $_SERVER['CONTENT_TYPE'] ) && 'application/json' === $_SERVER['CONTENT_TYPE'] ) {
+	if ( isset( $_SERVER['CONTENT_TYPE'] ) && in_array( $_SERVER['CONTENT_TYPE'], $accepted, true ) ) {
 		return true;
 	}
 
