Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 13 additions & 19 deletions lib/media/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
*
Expand Down
4 changes: 4 additions & 0 deletions packages/block-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Inspector controls in the standard block-supports panels (Typography, Dimensions, Border, Color, Background, Filters) now reflect the value a block inherits from Global Styles when no local override is set. Inherited controls show that value at rest (as a placeholder, preselected option, or resolved value) and mark the label with a dotted underline; setting a local override reveals a reset affordance that clears the override back to the inherited value ([#77894](https://github.com/WordPress/gutenberg/pull/77894)).

### 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
Expand Down
4 changes: 2 additions & 2 deletions packages/block-editor/src/components/provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -118,7 +118,7 @@ function shouldEnableHeicCanvasProcessing() {
return false;
}

if ( ! window.__heicUploadSupport ) {
if ( ! window.__clientSideMediaProcessing ) {
isHeicCanvasEnabledCache = false;
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 1 addition & 5 deletions packages/block-library/src/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
18 changes: 18 additions & 0 deletions packages/e2e-tests/plugins/disable-cross-origin-isolation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
/**
* Plugin Name: Gutenberg Test Plugin: Disable Cross-Origin Isolation
* Plugin URI: https://github.com/WordPress/gutenberg
* Author: Gutenberg Team
*
* @package gutenberg-test-disable-cross-origin-isolation
*/

/*
* Skip the Document-Isolation-Policy header while leaving client-side media
* processing enabled. Without cross-origin isolation, SharedArrayBuffer is
* unavailable, so the full VIPS/WASM pipeline fails feature detection and the
* editor falls back to the HEIC canvas conversion mode — mirroring Safari,
* where full client-side processing is unsupported but HEIC files are still
* converted to JPEG via createImageBitmap + OffscreenCanvas before upload.
*/
add_filter( 'gutenberg_use_document_isolation_policy', '__return_false' );
4 changes: 4 additions & 0 deletions packages/media-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Internal

- Remove the `window.__heicUploadSupport` type declaration, following the removal of the redundant flag ([#80452](https://github.com/WordPress/gutenberg/pull/80452)).

## 5.51.0 (2026-07-14)

### Enhancements
Expand Down
1 change: 0 additions & 1 deletion packages/media-utils/src/utils/upload-media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { UploadError } from './upload-error';
declare global {
interface Window {
__clientSideMediaProcessing?: boolean;
__heicUploadSupport?: boolean;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );

test.describe( 'Upload progress snackbar (HEIC-only canvas mode) (@webkit)', () => {
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'
);
} );

Expand All @@ -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'
);
} );

Expand Down Expand Up @@ -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( {
Expand All @@ -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
Expand Down
Loading