From a05777bbfdb6813bdd59c99da35822162928a9bc Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 4 Oct 2025 01:51:29 +0000 Subject: [PATCH] Emoji: Convert the emoji loader from an inline blocking script to a (deferred) script module. This modernizes the emoji loader script by converting it from a blocking inline script with an IIFE to a script module. Using a script module improves the performance of the FCP and LCP metrics since it does not block the HTML parser. Since script modules are deferred and run immediately before `DOMContentLoaded`, the logic to wait until that event is also now removed. Additionally, since the script is loaded as a module, it has been modernized to use `const`, `let`, and arrow functions. The `sourceURL` comment is also added. See #63887. The emoji settings are now passed via a separate `script` tag with a `type` of `application/json`, following the new "pull" paradigm introduced for exporting data from PHP to script modules. See #58873. The JSON data is also now encoded in a more resilient way according to #63851. When the `wp-emoji-loader.js` script module executes, it continues to populate the `window._wpemojiSettings` global for backwards-compatibility for any extensions that may be using it. A new `uglify:emoji-loader` grunt task is added which ensures `wp-includes/js/wp-emoji-loader.js` is processed as a module and that top-level symbols are minified. Follow-up to [60681]. Props westonruter, jonsurrell, adamsilverstein, peterwilsoncc. See #63851, #63887. Fixes #63842. Built from https://develop.svn.wordpress.org/trunk@60899 git-svn-id: http://core.svn.wordpress.org/trunk@60235 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/formatting.php | 16 +- wp-includes/js/wp-emoji-loader.js | 824 +++++++++++++------------- wp-includes/js/wp-emoji-loader.min.js | 2 +- wp-includes/version.php | 2 +- 4 files changed, 421 insertions(+), 423 deletions(-) diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index d12ade786a..44a7e6b085 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -5978,8 +5978,20 @@ function _print_emoji_detection_script() { } wp_print_inline_script_tag( - sprintf( 'window._wpemojiSettings = %s;', wp_json_encode( $settings ) ) . "\n" . - file_get_contents( ABSPATH . WPINC . '/js/wp-emoji-loader' . wp_scripts_get_suffix() . '.js' ) + wp_json_encode( $settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), + array( + 'id' => 'wp-emoji-settings', + 'type' => 'application/json', + ) + ); + + $emoji_loader_script_path = '/js/wp-emoji-loader' . wp_scripts_get_suffix() . '.js'; + wp_print_inline_script_tag( + rtrim( file_get_contents( ABSPATH . WPINC . $emoji_loader_script_path ) ) . "\n" . + '//# sourceURL=' . includes_url( $emoji_loader_script_path ), + array( + 'type' => 'module', + ) ); } diff --git a/wp-includes/js/wp-emoji-loader.js b/wp-includes/js/wp-emoji-loader.js index 1cee787aca..dfd5cd3543 100644 --- a/wp-includes/js/wp-emoji-loader.js +++ b/wp-includes/js/wp-emoji-loader.js @@ -2,6 +2,8 @@ * @output wp-includes/js/wp-emoji-loader.js */ +// Note: This is loaded as a script module, so there is no need for an IIFE to prevent pollution of the global scope. + /** * Emoji Settings as exported in PHP via _print_emoji_detection_script(). * @typedef WPEmojiSettings @@ -14,6 +16,13 @@ * @property {?Function} readyCallback */ +const settings = /** @type {WPEmojiSettings} */ ( + JSON.parse( document.getElementById( 'wp-emoji-settings' ).textContent ) +); + +// For compatibility with other scripts that read from this global. +window._wpemojiSettings = settings; + /** * Support tests. * @typedef SupportTests @@ -22,438 +31,415 @@ * @property {?boolean} emoji */ +const sessionStorageKey = 'wpEmojiSettingsSupports'; +const tests = [ 'flag', 'emoji' ]; + /** - * IIFE to detect emoji support and load Twemoji if needed. + * Checks whether the browser supports offloading to a Worker. * - * @param {Window} window - * @param {Document} document - * @param {WPEmojiSettings} settings + * @since 6.3.0 + * + * @private + * + * @returns {boolean} */ -( function wpEmojiLoader( window, document, settings ) { - if ( typeof Promise === 'undefined' ) { +function supportsWorkerOffloading() { + return ( + typeof Worker !== 'undefined' && + typeof OffscreenCanvas !== 'undefined' && + typeof URL !== 'undefined' && + URL.createObjectURL && + typeof Blob !== 'undefined' + ); +} + +/** + * @typedef SessionSupportTests + * @type {object} + * @property {number} timestamp + * @property {SupportTests} supportTests + */ + +/** + * Get support tests from session. + * + * @since 6.3.0 + * + * @private + * + * @returns {?SupportTests} Support tests, or null if not set or older than 1 week. + */ +function getSessionSupportTests() { + try { + /** @type {SessionSupportTests} */ + const item = JSON.parse( + sessionStorage.getItem( sessionStorageKey ) + ); + if ( + typeof item === 'object' && + typeof item.timestamp === 'number' && + new Date().valueOf() < item.timestamp + 604800 && // Note: Number is a week in seconds. + typeof item.supportTests === 'object' + ) { + return item.supportTests; + } + } catch ( e ) {} + return null; +} + +/** + * Persist the supports in session storage. + * + * @since 6.3.0 + * + * @private + * + * @param {SupportTests} supportTests Support tests. + */ +function setSessionSupportTests( supportTests ) { + try { + /** @type {SessionSupportTests} */ + const item = { + supportTests: supportTests, + timestamp: new Date().valueOf() + }; + + sessionStorage.setItem( + sessionStorageKey, + JSON.stringify( item ) + ); + } catch ( e ) {} +} + +/** + * Checks if two sets of Emoji characters render the same visually. + * + * This is used to determine if the browser is rendering an emoji with multiple data points + * correctly. set1 is the emoji in the correct form, using a zero-width joiner. set2 is the emoji + * in the incorrect form, using a zero-width space. If the two sets render the same, then the browser + * does not support the emoji correctly. + * + * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing + * scope. Everything must be passed by parameters. + * + * @since 4.9.0 + * + * @private + * + * @param {CanvasRenderingContext2D} context 2D Context. + * @param {string} set1 Set of Emoji to test. + * @param {string} set2 Set of Emoji to test. + * + * @return {boolean} True if the two sets render the same. + */ +function emojiSetsRenderIdentically( context, set1, set2 ) { + // Cleanup from previous test. + context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); + context.fillText( set1, 0, 0 ); + const rendered1 = new Uint32Array( + context.getImageData( + 0, + 0, + context.canvas.width, + context.canvas.height + ).data + ); + + // Cleanup from previous test. + context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); + context.fillText( set2, 0, 0 ); + const rendered2 = new Uint32Array( + context.getImageData( + 0, + 0, + context.canvas.width, + context.canvas.height + ).data + ); + + return rendered1.every( ( rendered2Data, index ) => { + return rendered2Data === rendered2[ index ]; + } ); +} + +/** + * Checks if the center point of a single emoji is empty. + * + * This is used to determine if the browser is rendering an emoji with a single data point + * correctly. The center point of an incorrectly rendered emoji will be empty. A correctly + * rendered emoji will have a non-zero value at the center point. + * + * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing + * scope. Everything must be passed by parameters. + * + * @since 6.8.2 + * + * @private + * + * @param {CanvasRenderingContext2D} context 2D Context. + * @param {string} emoji Emoji to test. + * + * @return {boolean} True if the center point is empty. + */ +function emojiRendersEmptyCenterPoint( context, emoji ) { + // Cleanup from previous test. + context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); + context.fillText( emoji, 0, 0 ); + + // Test if the center point (16, 16) is empty (0,0,0,0). + const centerPoint = context.getImageData(16, 16, 1, 1); + for ( let i = 0; i < centerPoint.data.length; i++ ) { + if ( centerPoint.data[ i ] !== 0 ) { + // Stop checking the moment it's known not to be empty. + return false; + } + } + + return true; +} + +/** + * Determines if the browser properly renders Emoji that Twemoji can supplement. + * + * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing + * scope. Everything must be passed by parameters. + * + * @since 4.2.0 + * + * @private + * + * @param {CanvasRenderingContext2D} context 2D Context. + * @param {string} type Whether to test for support of "flag" or "emoji". + * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. + * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. + * + * @return {boolean} True if the browser can render emoji, false if it cannot. + */ +function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { + let isIdentical; + + switch ( type ) { + case 'flag': + /* + * Test for Transgender flag compatibility. Added in Unicode 13. + * + * To test for support, we try to render it, and compare the rendering to how it would look if + * the browser doesn't render it correctly (white flag emoji + transgender symbol). + */ + isIdentical = emojiSetsRenderIdentically( + context, + '\uD83C\uDFF3\uFE0F\u200D\u26A7\uFE0F', // as a zero-width joiner sequence + '\uD83C\uDFF3\uFE0F\u200B\u26A7\uFE0F' // separated by a zero-width space + ); + + if ( isIdentical ) { + return false; + } + + /* + * Test for Sark flag compatibility. This is the least supported of the letter locale flags, + * so gives us an easy test for full support. + * + * To test for support, we try to render it, and compare the rendering to how it would look if + * the browser doesn't render it correctly ([C] + [Q]). + */ + isIdentical = emojiSetsRenderIdentically( + context, + '\uD83C\uDDE8\uD83C\uDDF6', // as the sequence of two code points + '\uD83C\uDDE8\u200B\uD83C\uDDF6' // as the two code points separated by a zero-width space + ); + + if ( isIdentical ) { + return false; + } + + /* + * Test for English flag compatibility. England is a country in the United Kingdom, it + * does not have a two letter locale code but rather a five letter sub-division code. + * + * To test for support, we try to render it, and compare the rendering to how it would look if + * the browser doesn't render it correctly (black flag emoji + [G] + [B] + [E] + [N] + [G]). + */ + isIdentical = emojiSetsRenderIdentically( + context, + // as the flag sequence + '\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F', + // with each code point separated by a zero-width space + '\uD83C\uDFF4\u200B\uDB40\uDC67\u200B\uDB40\uDC62\u200B\uDB40\uDC65\u200B\uDB40\uDC6E\u200B\uDB40\uDC67\u200B\uDB40\uDC7F' + ); + + return ! isIdentical; + case 'emoji': + /* + * Does Emoji 16.0 cause the browser to go splat? + * + * To test for Emoji 16.0 support, try to render a new emoji: Splatter. + * + * The splatter emoji is a single code point emoji. Testing for browser support + * required testing the center point of the emoji to see if it is empty. + * + * 0xD83E 0xDEDF (\uD83E\uDEDF) == 🫟 Splatter. + * + * When updating this test, please ensure that the emoji is either a single code point + * or switch to using the emojiSetsRenderIdentically function and testing with a zero-width + * joiner vs a zero-width space. + */ + const notSupported = emojiRendersEmptyCenterPoint( context, '\uD83E\uDEDF' ); + return ! notSupported; + } + + return false; +} + +/** + * Checks emoji support tests. + * + * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing + * scope. Everything must be passed by parameters. + * + * @since 6.3.0 + * + * @private + * + * @param {string[]} tests Tests. + * @param {Function} browserSupportsEmoji Reference to browserSupportsEmoji function, needed due to minification. + * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. + * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. + * + * @return {SupportTests} Support tests. + */ +function testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { + let canvas; + if ( + typeof WorkerGlobalScope !== 'undefined' && + self instanceof WorkerGlobalScope + ) { + canvas = new OffscreenCanvas( 300, 150 ); // Dimensions are default for HTMLCanvasElement. + } else { + canvas = document.createElement( 'canvas' ); + } + + const context = canvas.getContext( '2d', { willReadFrequently: true } ); + + /* + * Chrome on OS X added native emoji rendering in M41. Unfortunately, + * it doesn't work when the font is bolder than 500 weight. So, we + * check for bold rendering support to avoid invisible emoji in Chrome. + */ + context.textBaseline = 'top'; + context.font = '600 32px Arial'; + + const supports = {}; + tests.forEach( ( test ) => { + supports[ test ] = browserSupportsEmoji( context, test, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); + } ); + return supports; +} + +/** + * Adds a script to the head of the document. + * + * @ignore + * + * @since 4.2.0 + * + * @param {string} src The url where the script is located. + * + * @return {void} + */ +function addScript( src ) { + const script = document.createElement( 'script' ); + script.src = src; + script.defer = true; + document.head.appendChild( script ); +} + +settings.supports = { + everything: true, + everythingExceptFlag: true +}; + +// Obtain the emoji support from the browser, asynchronously when possible. +new Promise( ( resolve ) => { + let supportTests = getSessionSupportTests(); + if ( supportTests ) { + resolve( supportTests ); return; } - var sessionStorageKey = 'wpEmojiSettingsSupports'; - var tests = [ 'flag', 'emoji' ]; - - /** - * Checks whether the browser supports offloading to a Worker. - * - * @since 6.3.0 - * - * @private - * - * @returns {boolean} - */ - function supportsWorkerOffloading() { - return ( - typeof Worker !== 'undefined' && - typeof OffscreenCanvas !== 'undefined' && - typeof URL !== 'undefined' && - URL.createObjectURL && - typeof Blob !== 'undefined' - ); - } - - /** - * @typedef SessionSupportTests - * @type {object} - * @property {number} timestamp - * @property {SupportTests} supportTests - */ - - /** - * Get support tests from session. - * - * @since 6.3.0 - * - * @private - * - * @returns {?SupportTests} Support tests, or null if not set or older than 1 week. - */ - function getSessionSupportTests() { + if ( supportsWorkerOffloading() ) { try { - /** @type {SessionSupportTests} */ - var item = JSON.parse( - sessionStorage.getItem( sessionStorageKey ) - ); - if ( - typeof item === 'object' && - typeof item.timestamp === 'number' && - new Date().valueOf() < item.timestamp + 604800 && // Note: Number is a week in seconds. - typeof item.supportTests === 'object' - ) { - return item.supportTests; - } - } catch ( e ) {} - return null; - } - - /** - * Persist the supports in session storage. - * - * @since 6.3.0 - * - * @private - * - * @param {SupportTests} supportTests Support tests. - */ - function setSessionSupportTests( supportTests ) { - try { - /** @type {SessionSupportTests} */ - var item = { - supportTests: supportTests, - timestamp: new Date().valueOf() + // Note that the functions are being passed as arguments due to minification. + const workerScript = + 'postMessage(' + + testEmojiSupports.toString() + + '(' + + [ + JSON.stringify( tests ), + browserSupportsEmoji.toString(), + emojiSetsRenderIdentically.toString(), + emojiRendersEmptyCenterPoint.toString() + ].join( ',' ) + + '));'; + const blob = new Blob( [ workerScript ], { + type: 'text/javascript' + } ); + const worker = new Worker( URL.createObjectURL( blob ), { name: 'wpTestEmojiSupports' } ); + worker.onmessage = ( event ) => { + supportTests = event.data; + setSessionSupportTests( supportTests ); + worker.terminate(); + resolve( supportTests ); }; - - sessionStorage.setItem( - sessionStorageKey, - JSON.stringify( item ) - ); - } catch ( e ) {} - } - - /** - * Checks if two sets of Emoji characters render the same visually. - * - * This is used to determine if the browser is rendering an emoji with multiple data points - * correctly. set1 is the emoji in the correct form, using a zero-width joiner. set2 is the emoji - * in the incorrect form, using a zero-width space. If the two sets render the same, then the browser - * does not support the emoji correctly. - * - * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing - * scope. Everything must be passed by parameters. - * - * @since 4.9.0 - * - * @private - * - * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} set1 Set of Emoji to test. - * @param {string} set2 Set of Emoji to test. - * - * @return {boolean} True if the two sets render the same. - */ - function emojiSetsRenderIdentically( context, set1, set2 ) { - // Cleanup from previous test. - context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); - context.fillText( set1, 0, 0 ); - var rendered1 = new Uint32Array( - context.getImageData( - 0, - 0, - context.canvas.width, - context.canvas.height - ).data - ); - - // Cleanup from previous test. - context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); - context.fillText( set2, 0, 0 ); - var rendered2 = new Uint32Array( - context.getImageData( - 0, - 0, - context.canvas.width, - context.canvas.height - ).data - ); - - return rendered1.every( function ( rendered2Data, index ) { - return rendered2Data === rendered2[ index ]; - } ); - } - - /** - * Checks if the center point of a single emoji is empty. - * - * This is used to determine if the browser is rendering an emoji with a single data point - * correctly. The center point of an incorrectly rendered emoji will be empty. A correctly - * rendered emoji will have a non-zero value at the center point. - * - * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing - * scope. Everything must be passed by parameters. - * - * @since 6.8.2 - * - * @private - * - * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} emoji Emoji to test. - * - * @return {boolean} True if the center point is empty. - */ - function emojiRendersEmptyCenterPoint( context, emoji ) { - // Cleanup from previous test. - context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); - context.fillText( emoji, 0, 0 ); - - // Test if the center point (16, 16) is empty (0,0,0,0). - var centerPoint = context.getImageData(16, 16, 1, 1); - for ( var i = 0; i < centerPoint.data.length; i++ ) { - if ( centerPoint.data[ i ] !== 0 ) { - // Stop checking the moment it's known not to be empty. - return false; - } - } - - return true; - } - - /** - * Determines if the browser properly renders Emoji that Twemoji can supplement. - * - * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing - * scope. Everything must be passed by parameters. - * - * @since 4.2.0 - * - * @private - * - * @param {CanvasRenderingContext2D} context 2D Context. - * @param {string} type Whether to test for support of "flag" or "emoji". - * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. - * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. - * - * @return {boolean} True if the browser can render emoji, false if it cannot. - */ - function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { - var isIdentical; - - switch ( type ) { - case 'flag': - /* - * Test for Transgender flag compatibility. Added in Unicode 13. - * - * To test for support, we try to render it, and compare the rendering to how it would look if - * the browser doesn't render it correctly (white flag emoji + transgender symbol). - */ - isIdentical = emojiSetsRenderIdentically( - context, - '\uD83C\uDFF3\uFE0F\u200D\u26A7\uFE0F', // as a zero-width joiner sequence - '\uD83C\uDFF3\uFE0F\u200B\u26A7\uFE0F' // separated by a zero-width space - ); - - if ( isIdentical ) { - return false; - } - - /* - * Test for Sark flag compatibility. This is the least supported of the letter locale flags, - * so gives us an easy test for full support. - * - * To test for support, we try to render it, and compare the rendering to how it would look if - * the browser doesn't render it correctly ([C] + [Q]). - */ - isIdentical = emojiSetsRenderIdentically( - context, - '\uD83C\uDDE8\uD83C\uDDF6', // as the sequence of two code points - '\uD83C\uDDE8\u200B\uD83C\uDDF6' // as the two code points separated by a zero-width space - ); - - if ( isIdentical ) { - return false; - } - - /* - * Test for English flag compatibility. England is a country in the United Kingdom, it - * does not have a two letter locale code but rather a five letter sub-division code. - * - * To test for support, we try to render it, and compare the rendering to how it would look if - * the browser doesn't render it correctly (black flag emoji + [G] + [B] + [E] + [N] + [G]). - */ - isIdentical = emojiSetsRenderIdentically( - context, - // as the flag sequence - '\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F', - // with each code point separated by a zero-width space - '\uD83C\uDFF4\u200B\uDB40\uDC67\u200B\uDB40\uDC62\u200B\uDB40\uDC65\u200B\uDB40\uDC6E\u200B\uDB40\uDC67\u200B\uDB40\uDC7F' - ); - - return ! isIdentical; - case 'emoji': - /* - * Does Emoji 16.0 cause the browser to go splat? - * - * To test for Emoji 16.0 support, try to render a new emoji: Splatter. - * - * The splatter emoji is a single code point emoji. Testing for browser support - * required testing the center point of the emoji to see if it is empty. - * - * 0xD83E 0xDEDF (\uD83E\uDEDF) == 🫟 Splatter. - * - * When updating this test, please ensure that the emoji is either a single code point - * or switch to using the emojiSetsRenderIdentically function and testing with a zero-width - * joiner vs a zero-width space. - */ - var notSupported = emojiRendersEmptyCenterPoint( context, '\uD83E\uDEDF' ); - return ! notSupported; - } - - return false; - } - - /** - * Checks emoji support tests. - * - * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing - * scope. Everything must be passed by parameters. - * - * @since 6.3.0 - * - * @private - * - * @param {string[]} tests Tests. - * @param {Function} browserSupportsEmoji Reference to browserSupportsEmoji function, needed due to minification. - * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. - * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. - * - * @return {SupportTests} Support tests. - */ - function testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { - var canvas; - if ( - typeof WorkerGlobalScope !== 'undefined' && - self instanceof WorkerGlobalScope - ) { - canvas = new OffscreenCanvas( 300, 150 ); // Dimensions are default for HTMLCanvasElement. - } else { - canvas = document.createElement( 'canvas' ); - } - - var context = canvas.getContext( '2d', { willReadFrequently: true } ); - - /* - * Chrome on OS X added native emoji rendering in M41. Unfortunately, - * it doesn't work when the font is bolder than 500 weight. So, we - * check for bold rendering support to avoid invisible emoji in Chrome. - */ - context.textBaseline = 'top'; - context.font = '600 32px Arial'; - - var supports = {}; - tests.forEach( function ( test ) { - supports[ test ] = browserSupportsEmoji( context, test, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); - } ); - return supports; - } - - /** - * Adds a script to the head of the document. - * - * @ignore - * - * @since 4.2.0 - * - * @param {string} src The url where the script is located. - * - * @return {void} - */ - function addScript( src ) { - var script = document.createElement( 'script' ); - script.src = src; - script.defer = true; - document.head.appendChild( script ); - } - - settings.supports = { - everything: true, - everythingExceptFlag: true - }; - - // Create a promise for DOMContentLoaded since the worker logic may finish after the event has fired. - var domReadyPromise = new Promise( function ( resolve ) { - document.addEventListener( 'DOMContentLoaded', resolve, { - once: true - } ); - } ); - - // Obtain the emoji support from the browser, asynchronously when possible. - new Promise( function ( resolve ) { - var supportTests = getSessionSupportTests(); - if ( supportTests ) { - resolve( supportTests ); return; + } catch ( e ) {} + } + + supportTests = testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); + setSessionSupportTests( supportTests ); + resolve( supportTests ); +} ) + // Once the browser emoji support has been obtained from the session, finalize the settings. + .then( ( supportTests ) => { + /* + * Tests the browser support for flag emojis and other emojis, and adjusts the + * support settings accordingly. + */ + for ( const test in supportTests ) { + settings.supports[ test ] = supportTests[ test ]; + + settings.supports.everything = + settings.supports.everything && settings.supports[ test ]; + + if ( 'flag' !== test ) { + settings.supports.everythingExceptFlag = + settings.supports.everythingExceptFlag && + settings.supports[ test ]; + } } - if ( supportsWorkerOffloading() ) { - try { - // Note that the functions are being passed as arguments due to minification. - var workerScript = - 'postMessage(' + - testEmojiSupports.toString() + - '(' + - [ - JSON.stringify( tests ), - browserSupportsEmoji.toString(), - emojiSetsRenderIdentically.toString(), - emojiRendersEmptyCenterPoint.toString() - ].join( ',' ) + - '));'; - var blob = new Blob( [ workerScript ], { - type: 'text/javascript' - } ); - var worker = new Worker( URL.createObjectURL( blob ), { name: 'wpTestEmojiSupports' } ); - worker.onmessage = function ( event ) { - supportTests = event.data; - setSessionSupportTests( supportTests ); - worker.terminate(); - resolve( supportTests ); - }; - return; - } catch ( e ) {} - } + settings.supports.everythingExceptFlag = + settings.supports.everythingExceptFlag && + ! settings.supports.flag; - supportTests = testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); - setSessionSupportTests( supportTests ); - resolve( supportTests ); + // Sets DOMReady to false and assigns a ready function to settings. + settings.DOMReady = false; + settings.readyCallback = () => { + settings.DOMReady = true; + }; } ) - // Once the browser emoji support has been obtained from the session, finalize the settings. - .then( function ( supportTests ) { - /* - * Tests the browser support for flag emojis and other emojis, and adjusts the - * support settings accordingly. - */ - for ( var test in supportTests ) { - settings.supports[ test ] = supportTests[ test ]; + .then( () => { + // When the browser can not render everything we need to load a polyfill. + if ( ! settings.supports.everything ) { + settings.readyCallback(); - settings.supports.everything = - settings.supports.everything && settings.supports[ test ]; + const src = settings.source || {}; - if ( 'flag' !== test ) { - settings.supports.everythingExceptFlag = - settings.supports.everythingExceptFlag && - settings.supports[ test ]; - } + if ( src.concatemoji ) { + addScript( src.concatemoji ); + } else if ( src.wpemoji && src.twemoji ) { + addScript( src.twemoji ); + addScript( src.wpemoji ); } - - settings.supports.everythingExceptFlag = - settings.supports.everythingExceptFlag && - ! settings.supports.flag; - - // Sets DOMReady to false and assigns a ready function to settings. - settings.DOMReady = false; - settings.readyCallback = function () { - settings.DOMReady = true; - }; - } ) - .then( function () { - return domReadyPromise; - } ) - .then( function () { - // When the browser can not render everything we need to load a polyfill. - if ( ! settings.supports.everything ) { - settings.readyCallback(); - - var src = settings.source || {}; - - if ( src.concatemoji ) { - addScript( src.concatemoji ); - } else if ( src.wpemoji && src.twemoji ) { - addScript( src.twemoji ); - addScript( src.wpemoji ); - } - } - } ); -} )( window, document, window._wpemojiSettings ); + } + } ); diff --git a/wp-includes/js/wp-emoji-loader.min.js b/wp-includes/js/wp-emoji-loader.min.js index 5c7a2db264..bf9b0fb60f 100644 --- a/wp-includes/js/wp-emoji-loader.min.js +++ b/wp-includes/js/wp-emoji-loader.min.js @@ -1,2 +1,2 @@ /*! This file is auto-generated */ -!function(s,n){var o,i,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),a=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===a[t]})}function u(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);for(var n=e.getImageData(16,16,1,1),a=0;ae===a[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e{s[e]=t(o,e,n,a)}),s}function t(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}n.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf(){i(n=e.data),r.terminate(),t(n)})}catch(e){}i(n=f(s,u,c,p))}t(n)}).then(e=>{for(const t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=()=>{n.DOMReady=!0}}).then(()=>{var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}); \ No newline at end of file diff --git a/wp-includes/version.php b/wp-includes/version.php index dfc1e75140..f04633d6db 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.9-alpha-60898'; +$wp_version = '6.9-alpha-60899'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.