From 513992357989158359c4075894bfcb5e5073636b Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Jan 2024 17:54:25 +0000 Subject: [PATCH] Script Loader: Only emit CDATA wrapper comments in `wp_get_inline_script_tag()` for JavaScript. This avoids erroneously adding CDATA wrapper comments for non-JavaScript scripts, including those for JSON such as the `importmap` for script modules in #56313. Props westonruter, flixos90, mukesh27, dmsnell. See #56313. Fixes #60320. git-svn-id: https://develop.svn.wordpress.org/trunk@57341 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/script-loader.php | 12 ++- .../tests/dependencies/wpInlineScriptTag.php | 84 +++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 6425afe874..a04c580274 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -2879,7 +2879,17 @@ function wp_get_inline_script_tag( $javascript, $attributes = array() ) { * * @see https://www.w3.org/TR/xhtml1/#h-4.8 */ - if ( ! $is_html5 ) { + if ( + ! $is_html5 && + ( + ! isset( $attributes['type'] ) || + 'module' === $attributes['type'] || + str_contains( $attributes['type'], 'javascript' ) || + str_contains( $attributes['type'], 'ecmascript' ) || + str_contains( $attributes['type'], 'jscript' ) || + str_contains( $attributes['type'], 'livescript' ) + ) + ) { /* * If the string `]]>` exists within the JavaScript it would break * out of any wrapping CDATA section added here, so to start, it's diff --git a/tests/phpunit/tests/dependencies/wpInlineScriptTag.php b/tests/phpunit/tests/dependencies/wpInlineScriptTag.php index 2bbb665d39..7192570838 100644 --- a/tests/phpunit/tests/dependencies/wpInlineScriptTag.php +++ b/tests/phpunit/tests/dependencies/wpInlineScriptTag.php @@ -10,6 +10,20 @@ */ class Tests_Functions_wpInlineScriptTag extends WP_UnitTestCase { + private $original_theme_features = array(); + + public function set_up() { + global $_wp_theme_features; + parent::set_up(); + $this->original_theme_features = $_wp_theme_features; + } + + public function tear_down() { + global $_wp_theme_features; + $_wp_theme_features = $this->original_theme_features; + parent::tear_down(); + } + private $event_handler = <<<'JS' document.addEventListener( 'DOMContentLoaded', function () { document.getElementById( 'elementID' ) @@ -133,4 +147,74 @@ JS; wp_get_inline_script_tag( "/* */" ) ); } + + public function data_provider_to_test_cdata_wrapper_omitted_for_non_javascript_scripts() { + return array( + 'no-type' => array( + 'type' => null, + 'data' => 'alert("hello")', + 'expected_cdata' => true, + ), + 'js-type' => array( + 'type' => 'text/javascript', + 'data' => 'alert("hello")', + 'expected_cdata' => true, + ), + 'js-alt-type' => array( + 'type' => 'application/javascript', + 'data' => 'alert("hello")', + 'expected_cdata' => true, + ), + 'module' => array( + 'type' => 'module', + 'data' => 'alert("hello")', + 'expected_cdata' => true, + ), + 'importmap' => array( + 'type' => 'importmap', + 'data' => '{"imports":{"bar":"http:\/\/localhost:10023\/bar.js?ver=6.5-alpha-57321"}}', + 'expected_cdata' => false, + ), + 'html' => array( + 'type' => 'text/html', + 'data' => '
template code
', + 'expected_cdata' => false, + ), + 'json' => array( + 'type' => 'application/json', + 'data' => '{}', + 'expected_cdata' => false, + ), + 'ld' => array( + 'type' => 'application/ld+json', + 'data' => '{}', + 'expected_cdata' => false, + ), + 'specrules' => array( + 'type' => 'speculationrules', + 'data' => '{}', + 'expected_cdata' => false, + ), + ); + } + + /** + * Tests that CDATA wrapper is not added for non-JavaScript scripts. + * + * @ticket 60320 + * + * @dataProvider data_provider_to_test_cdata_wrapper_omitted_for_non_javascript_scripts + */ + public function test_cdata_wrapper_omitted_for_non_javascript_scripts( $type, $data, $expected_cdata ) { + remove_theme_support( 'html5' ); + + $attrs = array(); + if ( $type ) { + $attrs['type'] = $type; + } + $script = wp_get_inline_script_tag( $data, $attrs ); + $this->assertSame( $expected_cdata, str_contains( $script, '/* assertSame( $expected_cdata, str_contains( $script, '/* ]]> */' ) ); + $this->assertStringContainsString( $data, $script ); + } }