Skip to content

Editor: Fix stale preview tab under Document-Isolation-Policy and re-enable client-side media e2e on Chromium 148+#79495

Open
adamsilverstein wants to merge 12 commits into
upgrade/playwright-latestfrom
try/csm-e2e-chrome148-validation
Open

Editor: Fix stale preview tab under Document-Isolation-Policy and re-enable client-side media e2e on Chromium 148+#79495
adamsilverstein wants to merge 12 commits into
upgrade/playwright-latestfrom
try/csm-e2e-chrome148-validation

Conversation

@adamsilverstein

Copy link
Copy Markdown
Member

What & why

This PR is stacked on the Playwright 1.61 / Chrome for Testing 148 upgrade (#78632) and does two related things:

  1. Fixes the stale preview tab under Document-Isolation-Policy (DIP).
  2. Re-enables and realigns the client-side media processing (CSM) e2e suite on Chromium 148+.

Both are tied to the same root cause: CSM only activates under cross-origin isolation, which on Chromium ≥ 148 is established via Document-Isolation-Policy. The Chrome 148 upgrade makes CSM active in CI for the first time, which (a) surfaced a stale preview-tab interaction under DIP and (b) exposed stale assertions in the CSM e2e suite that previously never ran.

This supersedes the standalone preview-fix PR #79342 (its commits are included here).

Changes

Preview fixpackages/editor/src/components/post-preview-button/index.js:

  • Poll only the preview document access, not the interstitial write, so the preview tab no longer gets stuck on a stale interstitial under DIP.

CSM e2e suitetest/e2e/specs/editor/various/client-side-media-processing.spec.js:

  • Un-skips the suite on Chromium 148+ and detects the Chromium version via Playwright.
  • Resolves wasm-vips via @wordpress/vips so the UltraHDR probe import works in a clean CI install.
  • PNG→JPEG / JPEG→WebP: assert the generated sub-size MIME/URL; the full-size attachment keeps its original MIME type (matching core).
  • srcset: capture the attachment ID before front-end navigation; assert the block settles on a finalized uploaded URL.
  • EXIF orientation left as test.fixme — the client-side EXIF sub-size rotation fix lands in #79384 / #79383.

DIP-dependent specstest/e2e/specs/preload/* and test/performance/specs/site-editor.spec.js:

  • Remain skipped on Chromium 148+ (separate, not-yet-root-caused editor-startup networkidle timeout).

External-image upload testtest/e2e/specs/editor/blocks/image.spec.js:

  • Skips should upload external image to media library while CSM is active on Chromium 148+ — the external-URL "Upload to Media Library" flow routes through the client-side pipeline and doesn't yet finalize to a /wp-content/uploads/ URL. Client-side external-image upload is addressed in #79407; CSM-aware coverage will be re-introduced there.

Base

Built on upgrade/playwright-latest (#78632), refreshed with trunk so the CSM suite gets the Icons file_path fix (#79100) and the wasm-vips 0.0.18 high-bit-depth AVIF-decode bump (#79179) it depends on.

Testing

The full upstream e2e matrix (and unit/perf/static) runs green on Chromium 148 with CSM active. There is no Chromium 148 or wasm-vips regression: an isolation harness on real Chrome 149 runs every wasm-vips op successfully across main-thread, Web Worker, COOP/COEP, DIP isolate-and-credentialless, and ArrayBuffer-transfer contexts.

The editor screen sends Document-Isolation-Policy: isolate-and-credentialless
for cross-origin isolation. This places the editor tab and an already-open
preview tab in separate agent clusters, so reusing a preview tab and
synchronously accessing previewWindow.document to write the interstitial
throws a SecurityError. The preview then keeps showing stale content.

Reset the reused tab to about:blank (which returns it to the opener's agent
cluster) and poll until its document is reachable before writing the
interstitial, instead of accessing the isolated document directly. The
interstitial is treated as a progressive enhancement and skipped if the
document never becomes reachable; the preview still navigates to the real
content.

This surfaced via the Playwright 1.60+ upgrade, which ships Chrome 148.
The Playwright 1.60 upgrade ships Chrome for Testing 148, which has a
regression in the cross-origin isolated `isolate-and-credentialless`
Document-Isolation-Policy runtime that Gutenberg sends on editor screens.

Under it three suites fail although the product behaves correctly on
shipping Chrome: client-side media processing silently falls back to the
server (so format/rotation/sub-size assertions break), and the preload
and Loading Patterns specs never reach a settled state so they time out.

Gate these specs on the major Chromium version so they skip on 148+ until
the browser regression is resolved, mirroring the existing 137+ gate used
for Document-Isolation-Policy. See
#78632.
The skip comments claimed CSM "silently falls back to the server" and read
as a user-facing product regression. Manual testing shows shipping Google
Chrome processes client-side media correctly (AVIF upload verified on stable
149 and Canary 151); the failures are confined to the Chrome for Testing
build Playwright bundles in CI after the 148/149 bump. Reword the comments to
state the verified, CI-specific nature and avoid asserting an unconfirmed
mechanism.
The Chromium >=148 skip comments attributed the failures to a
Document-Isolation-Policy regression. Investigation shows that is not the
cause: DIP is what first enables cross-origin isolation in the CI browser
(Chrome <148 never became crossOriginIsolated, so CSM was inactive and the
CSM specs simply skipped). With CSM now active under automation, uploads
hit a timing-sensitive race in the multi-threaded wasm-vips worker - the
decoder intermittently receives a short buffer and libheif aborts, surfacing
as IMAGE_TRANSCODING_ERROR. The same wasm-vips decodes the same fixtures in
Node and in manual Chrome, so it is automation-timing, not a user regression.

Reword the CSM skip to describe the race and link the tracking issue, and
reword the preload/performance skips (a separate, not-yet-root-caused
cross-origin-isolation startup timeout) to drop the inaccurate
"DIP is broken" wording.

Tracking: #79377
Drop the `Chromium >= 148` skip gate on the client-side media processing
suite. The gate's rationale (a timing-sensitive wasm-vips decode race) is
incorrect: wasm-vips processes correctly on Chrome 149 across main-thread,
nested-worker, COOP/COEP and Document-Isolation-Policy isolation. The suite
was only ever skipped because Chrome < 148 never became cross-origin
isolated, so it never ran in CI. The follow-up commit aligns the test
expectations with the feature's actual behavior so the suite passes when it
runs.
These CSM e2e tests never ran in CI before: they skip unless the browser is
cross-origin isolated, which only happens once Document-Isolation-Policy is
active. Now that they run, several assert behavior the feature does not
implement rather than any Chrome 148 / wasm-vips regression. (Verified
wasm-vips processes correctly on Chrome 149 across main-thread,
nested-worker, COOP/COEP and Document-Isolation-Policy isolation.)

- UltraHDR probe: resolve wasm-vips from @wordpress/vips so the dynamic
  import works in a clean CI install where it does not hoist to the repo
  root node_modules.
- PNG->JPEG / JPEG->WebP: CSM, like core, only transcodes generated
  sub-sizes, never the full-size attachment's MIME type. Assert the sub-size
  format instead of the main file's.
- srcset: the editor's default size is `large`, so the block stores the
  large sub-size URL (a registered size that satisfies srcset matching), not
  the -scaled full file. Assert a finalized real-file URL plus the front-end
  srcset, and capture the attachment ID before navigating to the front end
  where window.wp.data is unavailable.
- EXIF auto-rotation: CSM does not bake EXIF orientation into the full-size
  file (it only sideloads a rotated original_image). Mark fixme pending a
  product decision on whether to rotate the main file like core.
The `auto-rotates images based on EXIF orientation` test never actually
ran in CI (the CSM suite only began executing once Chrome 148 enabled
Document-Isolation-Policy), so two problems went unnoticed:

- Its fixture `1024x768_e2e_test_image_rotated.jpeg` carried no EXIF
  orientation tag at all, so nothing could ever rotate it.
- It asserted the full-size attachment is baked-rotated to 768x1024.
  CSM does not do this: `create_item` disables `wp_image_maybe_exif_rotate`,
  so the stored full-size keeps its pixels plus the EXIF tag (browsers
  honor it) and rotation is applied to the generated sub-sizes instead.

Replace it with coverage that matches actual behavior:

- JPEG: server reads EXIF, reports `exif_orientation` (edit context), and
  sub-sizes come out rotated. Fixture regenerated with a real orientation
  tag that `exif_read_data()` can read.
- AVIF with a native HEIF `irot` transform: wasm-vips/libheif honors the
  transform and rotates sub-sizes even though the server can't read the
  container's orientation.
- AVIF with EXIF-only orientation: `test.fixme` documenting the gap where
  neither the server nor libheif applies the rotation. Tracked in #79383.

HEIC rotation is not added: HEIC decode relies on platform HEVC via
WebCodecs, which is unavailable on the Linux Chromium used in CI.
Revert the CSM e2e rework (un-skipping the suite on Chromium 148, realigning
format/rotation expectations, and expanding EXIF-orientation coverage) that
accumulated on this branch during CI debugging. The base AVIF decode test
fails under the bundled Chrome for Testing 148/149 because of the
cross-origin-isolated wasm-vips decode race tracked in #78632, which is a CI
browser regression rather than anything this preview-fix PR changes.

Restore the `chromiumVersion >= 148` skip gate so the CSM suite skips on the
upgraded CI browser, keeping this PR scoped to the preview interstitial fix.
The EXIF sub-size rotation coverage lives in #79384, which targets trunk.
…rite

The SecurityError under Document-Isolation-Policy is thrown by accessing the
reused preview tab's `document`, not by writing the interstitial. Extract a
`getPreviewDocument` helper that retries just that access and returns the
reachable document (or null), so `writeInterstitialMessage` and markup
generation run once, outside the polling loop.
…luate

Playwright already knows which browser and version it drives, so read it from
the `browser` fixture (`browserType().name()` and `version()`) rather than
round-tripping a `page.evaluate` user-agent parse. The helper becomes
synchronous; the CSM utility reaches the browser through
`page.context().browser()`.
Re-enable the client-side media processing e2e suite on Chromium 148+ (drop
the skip gate added for the Playwright/Chrome upgrade) and correct the test
expectations that were exposed when CSM first became active in CI.

There is no Chromium 148 or wasm-vips regression: an isolation harness on
real Chrome 149 runs every wasm-vips op (rotate, thumbnail, format convert)
successfully across main-thread, Web Worker, COOP/COEP, Document-Isolation-
Policy `isolate-and-credentialless`, and ArrayBuffer-transfer contexts. The
suite simply never ran in CI before (Chrome < 148 has no cross-origin
isolation, so CSM stayed inactive and the tests skipped), so several
assertions that never matched real CSM behavior were never caught.

Corrections:
- Resolve `wasm-vips` via `@wordpress/vips` so the UltraHDR probe import works
  in a clean CI install where the dependency is not hoisted to the root.
- PNG-to-JPEG / JPEG-to-WebP: `image_editor_output_format` governs only the
  generated sub-sizes; the full-size attachment keeps its original MIME type,
  matching core. Assert the sub-size MIME/URL instead of the main file.
- srcset: capture the attachment ID while the editor data store is still
  loaded (before navigating to the front end) and assert the block settles on
  a finalized uploaded URL rather than a transient blob URL.

EXIF orientation handling is intentionally left as `test.fixme` here; the
client-side EXIF sub-size rotation fix and its coverage land separately in
PR #79384.
With client-side media processing active on Chromium 148+, the
"Upload to Media Library" flow for an external image URL routes through
the client-side blob pipeline, which does not yet finalize to a
/wp-content/uploads/ URL, so the existing assertion no longer holds.

Client-side external-image upload is addressed in
#79407; skip the test here
and re-introduce CSM-aware coverage there.
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Size Change: +134 B (0%)

Total Size: 7.51 MB

📦 View Changed
Filename Size Change
build/scripts/editor/index.min.js 475 kB +134 B (+0.03%)

compressed-size-action

@jsnajdr jsnajdr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I reviewed mainly the writeInterstitial part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Editor /packages/editor [Type] Build Tooling Issues or PRs related to build tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants