Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Script Modules: Add data server->client data passing #6433

Closed
wants to merge 10 commits into from
7 changes: 7 additions & 0 deletions src/wp-includes/block-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,13 @@ function block_editor_rest_api_preload( array $preload_paths, $block_editor_cont
),
'after'
);
add_filter(
'scriptmoduledata_@wordpress/api-fetch',
function ( $data ) use ( $preload_data ) {
$data['preloadData'] = $preload_data;
return $data;
}
);
}

/**
Expand Down
73 changes: 73 additions & 0 deletions src/wp-includes/class-wp-script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ public function add_hooks() {
add_action( $position, array( $this, 'print_import_map' ) );
add_action( $position, array( $this, 'print_enqueued_script_modules' ) );
add_action( $position, array( $this, 'print_script_module_preloads' ) );

add_action( 'admin_print_footer_scripts', array( $this, 'print_import_map' ) );
add_action( 'admin_print_footer_scripts', array( $this, 'print_enqueued_script_modules' ) );
add_action( 'admin_print_footer_scripts', array( $this, 'print_script_module_preloads' ) );

add_action( 'wp_footer', array( $this, 'print_script_data' ) );
add_action( 'admin_print_footer_scripts', array( $this, 'print_script_data' ) );
}

/**
Expand Down Expand Up @@ -359,4 +366,70 @@ private function get_src( string $id ): string {

return $src;
}

public function print_script_data(): void {
$modules = array();
foreach ( array_keys( $this->get_marked_for_enqueue() ) as $id ) {
$modules[ $id ] = true;
}
foreach ( array_keys( $this->get_import_map()['imports'] ) as $id ) {
$modules[ $id ] = true;
}

foreach ( array_keys( $modules ) as $module_id ) {
$data = apply_filters( 'scriptmoduledata_' . $module_id, array() );
if ( ! empty( $data ) ) {
/*
* This data will be printed as JSON inside a script tag like this:
* <script type="application/json"></script>
*
* A script tag must be closed by a sequence beginning with `</`. It's impossible to
* close a script tag without using `<`. We ensure that `<` is escaped and `/` can
* remain unescaped, so `</script>` will be printed as `\u003C/script\u00E3`.
*
* - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E.
* - JSON_UNESCAPED_SLASHES: Don't escape /.
*
* @see https://www.php.net/manual/en/json.constants.php for details on these constants.
* @see https://html.spec.whatwg.org/#script-data-state for details on script
* tag parsing.
*/
$json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES;
if ( 'UTF-8' === get_option( 'blog_charset' ) ) {
/*
* If the page will use UTF-8 encoding, it's safe to print unescaped unicode in
* JSON. Set the following flags:
*
* - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally
* (default is to escape as \uXXXX).
* - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when
* JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was
* before PHP 7.1 without this constant. Available as of PHP 7.1.0.
*
* The JSON specification does not specify a character encoding, RFC-8259
* suggests that UTF-8 be used everywhere. It's risky to print unicode if the page
* uses any other encoding.
*
* > JSON text exchanged between systems that are not part of a closed ecosystem
* > MUST be encoded using UTF-8. Previous specifications of JSON have not required
* > the use of UTF-8 when transmitting JSON text. However, the vast majority of
* > JSON- based software implementations have chosen to use the UTF-8 encoding,
* > to the extent that it is the only encoding that achieves interoperability.
*
* @see https://www.rfc-editor.org/rfc/rfc8259.html
*
*/
$json_encode_flags |= JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS;
}

wp_print_inline_script_tag(
wp_json_encode( $data, $json_encode_flags ),
array(
'type' => 'application/json',
'id' => 'wp-scriptmodule-data_' . $module_id,
)
);
}
}
}
}
16 changes: 16 additions & 0 deletions src/wp-includes/script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,19 @@ function wp_dequeue_script_module( string $id ) {
function wp_deregister_script_module( string $id ) {
wp_script_modules()->deregister( $id );
}


function wp_register_default_script_modules(): void {
add_filter(
'scriptmoduledata_@wordpress/api-fetch',
function ( $data ) {
$data['rootURL'] = sanitize_url( get_rest_url() );
$data['nonce'] = wp_installing() ? '' : wp_create_nonce( 'wp_rest' );
$data['shouldRegisterMediaUploadMiddleware'] = true;
$data['nonceEndpoint'] = admin_url( 'admin-ajax.php?action=rest-nonce' );
return $data;
}
);
wp_enqueue_script_module( '__DEV__/noop', includes_url( '/noop.js' ), array( '@wordpress/api-fetch' ) );
}
add_action( 'init', 'wp_register_default_script_modules', 0 );
8 changes: 8 additions & 0 deletions src/wp-includes/theme-previews.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ function wp_attach_theme_preview_middleware() {
),
'after'
);

add_filter(
'scriptmoduledata_@wordpress/api-fetch',
function ( $data ) {
$data['themePreviewPath'] = sanitize_text_field( wp_unslash( $_GET['wp_theme_preview'] ) );
return $data;
}
);
}

/**
Expand Down