From c6996c1e99d407d4bf138997a75b487048b10b79 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 20 Jul 2026 11:14:19 -0700 Subject: [PATCH] Media: Remove the redundant __heicUploadSupport flag (#80452) Co-authored-by: adamsilverstein Co-authored-by: andrewserong Co-authored-by: swissspidy Co-authored-by: ramonjd --- lib/media/load.php | 32 ++++++++----------- packages/block-editor/CHANGELOG.md | 4 +++ .../src/components/provider/index.js | 4 +-- packages/block-library/CHANGELOG.md | 4 +++ packages/block-library/src/image/edit.js | 6 +--- .../disable-cross-origin-isolation.php | 18 +++++++++++ packages/media-utils/CHANGELOG.md | 4 +++ .../media-utils/src/utils/upload-media.ts | 1 - .../heic-upload-progress-snackbar.spec.js | 31 ++++++++++++++---- 9 files changed, 70 insertions(+), 34 deletions(-) create mode 100644 packages/e2e-tests/plugins/disable-cross-origin-isolation.php diff --git a/lib/media/load.php b/lib/media/load.php index d53b460e17af1f..99b06a6273383d 100644 --- a/lib/media/load.php +++ b/lib/media/load.php @@ -199,17 +199,22 @@ function gutenberg_media_processing_filter_rest_index( WP_REST_Response $respons add_filter( 'rest_index', 'gutenberg_media_processing_filter_rest_index' ); /** - * Sets a global JS variable to indicate that HEIC canvas-based upload support is available. + * Sets a global JS variable to indicate that client-side media processing is enabled. * - * This flag is set whenever the media processing feature is enabled, - * regardless of whether the browser supports full VIPS-based processing. - * Browsers like Safari can use createImageBitmap() to decode HEIC images - * and convert them to JPEG for server-side sub-size generation. + * The flag gates both processing modes: the full VIPS/WASM pipeline (browsers + * that pass feature detection) and the HEIC canvas fallback used by browsers + * such as Safari that can decode HEIC via createImageBitmap() but lack + * SharedArrayBuffer support. The browser-capability check happens client-side. */ -function gutenberg_set_heic_upload_support_flag() { - wp_add_inline_script( 'wp-block-editor', 'window.__heicUploadSupport = true', 'before' ); +function gutenberg_set_client_side_media_processing_flag() { + // Re-check the filter at action time, since other plugins (loaded after Gutenberg) + // may have added a filter to disable client-side media processing. + if ( ! gutenberg_is_client_side_media_processing_enabled() ) { + return; + } + wp_add_inline_script( 'wp-block-editor', 'window.__clientSideMediaProcessing = true', 'before' ); } -add_action( 'admin_init', 'gutenberg_set_heic_upload_support_flag' ); +add_action( 'admin_init', 'gutenberg_set_client_side_media_processing_flag' ); /** * Deletes the source-format companion file when its attachment is deleted. @@ -258,17 +263,6 @@ function gutenberg_delete_heic_companion_file( int $post_id ): bool { // Everything below requires cross-origin isolation (Document-Isolation-Policy) // and SharedArrayBuffer support, which is only available in Chromium 137+. -/** - * Sets a global JS variable to indicate that client-side media processing is enabled. - */ -function gutenberg_set_client_side_media_processing_flag() { - if ( ! gutenberg_is_client_side_media_processing_enabled() ) { - return; - } - wp_add_inline_script( 'wp-block-editor', 'window.__clientSideMediaProcessing = true', 'before' ); -} -add_action( 'admin_init', 'gutenberg_set_client_side_media_processing_flag' ); - /** * Filters the list of rewrite rules formatted for output to an .htaccess file. * diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 03d11dc03d2743..0408a1e91c9587 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Gate the HEIC canvas conversion fallback on `window.__clientSideMediaProcessing` instead of the redundant `window.__heicUploadSupport` flag, fixing client-side HEIC conversion in Safari on core WordPress installs ([#80452](https://github.com/WordPress/gutenberg/pull/80452)). + ## 16.0.0 (2026-07-14) ### Internal diff --git a/packages/block-editor/src/components/provider/index.js b/packages/block-editor/src/components/provider/index.js index 379aad102606a9..410f83d5495c2f 100644 --- a/packages/block-editor/src/components/provider/index.js +++ b/packages/block-editor/src/components/provider/index.js @@ -102,7 +102,7 @@ function shouldEnableClientSideMediaProcessing() { * * Returns true when: * 1. Full client-side processing is NOT available (otherwise it handles HEIC already) - * 2. The server has set the __heicUploadSupport flag + * 2. The server has set the __clientSideMediaProcessing flag * 3. The browser supports createImageBitmap + OffscreenCanvas (e.g. Safari) * * @return {boolean} Whether HEIC-only canvas processing should be enabled. @@ -118,7 +118,7 @@ function shouldEnableHeicCanvasProcessing() { return false; } - if ( ! window.__heicUploadSupport ) { + if ( ! window.__clientSideMediaProcessing ) { isHeicCanvasEnabledCache = false; return false; } diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index d7375f064b4ae2..be8ae8d0638e28 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- Image: Check only `window.__clientSideMediaProcessing` for sideloading status, following the removal of the redundant `window.__heicUploadSupport` flag ([#80452](https://github.com/WordPress/gutenberg/pull/80452)). + ## 10.2.0 (2026-07-14) ### Enhancements diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index ff6cd3eddc3416..bf97311b99b0f5 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -353,11 +353,7 @@ export function ImageEdit( { const isSideloading = useSelect( ( select ) => { - if ( - ( ! window.__clientSideMediaProcessing && - ! window.__heicUploadSupport ) || - ! id - ) { + if ( ! window.__clientSideMediaProcessing || ! id ) { return false; } return select( uploadStore ).isUploadingById( id ); diff --git a/packages/e2e-tests/plugins/disable-cross-origin-isolation.php b/packages/e2e-tests/plugins/disable-cross-origin-isolation.php new file mode 100644 index 00000000000000..f697a369183fab --- /dev/null +++ b/packages/e2e-tests/plugins/disable-cross-origin-isolation.php @@ -0,0 +1,18 @@ + { test.beforeAll( async ( { requestUtils } ) => { - // Disable full client-side media processing while leaving the - // HEIC canvas-conversion mode active (`window.__heicUploadSupport` - // is set regardless). This mirrors Safari, where full client-side - // processing is unsupported but HEIC files are still converted to - // JPEG via createImageBitmap + OffscreenCanvas before upload. + // Disable cross-origin isolation while leaving client-side media + // processing enabled: without SharedArrayBuffer the full VIPS + // pipeline fails feature detection, so the editor falls back to the + // HEIC canvas-conversion mode. This mirrors Safari, where full + // client-side processing is unsupported but HEIC files are still + // converted to JPEG via createImageBitmap + OffscreenCanvas before + // upload. await requestUtils.activatePlugin( - 'gutenberg-test-plugin-disable-client-side-media-processing' + 'gutenberg-test-plugin-disable-cross-origin-isolation' ); } ); @@ -31,7 +33,7 @@ test.describe( 'Upload progress snackbar (HEIC-only canvas mode) (@webkit)', () test.afterAll( async ( { requestUtils } ) => { await requestUtils.deactivatePlugin( - 'gutenberg-test-plugin-disable-client-side-media-processing' + 'gutenberg-test-plugin-disable-cross-origin-isolation' ); } ); @@ -59,6 +61,19 @@ test.describe( 'Upload progress snackbar (HEIC-only canvas mode) (@webkit)', () const imageBlock = editor.canvas.locator( 'role=document[name="Block: Image"i]' ); + + // The canvas conversion mode sideloads the converted JPEG. A plain + // server-side upload never hits the sideload endpoint, so waiting for + // it proves the HEIC canvas path actually ran: the server also + // content-sniffs the fake HEIC's JPEG bytes and renames the file, so + // the src assertion below cannot tell the two paths apart on its own. + const sideloadRequest = page.waitForRequest( + ( request ) => + request.method() === 'POST' && + request.url().includes( 'sideload' ), + { timeout: 60_000 } + ); + await imageBlock .locator( 'data-testid=form-file-upload-input' ) .setInputFiles( { @@ -67,6 +82,8 @@ test.describe( 'Upload progress snackbar (HEIC-only canvas mode) (@webkit)', () buffer, } ); + await sideloadRequest; + const snackbarList = page.locator( '.components-snackbar-list' ); // A single file must use the single-file message throughout. The