Media: Stop the shell breaking core's uploader button and grid refresh - #487
Merged
Conversation
The bridge's link interceptor runs in the capture phase, so it preventDefaults before the script that owns an in-page button gets the click. On the Media Library grid that opened a window for media-new.php (the anchor's no-JS fallback) while media-grid.js still expanded the inline uploader in the Media window behind it. Bail on anchors carrying core's aria-button-if-js class, which is core's own marker for "this href is only the no-JS fallback". Also restores the comment row actions and the plugin auto-update toggle, which the interceptor was hijacking the same way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mmtr
force-pushed
the
claude/media-screen-dialog-bug-77c3ca
branch
from
August 4, 2026 15:11
82b040e to
809a559
Compare
upload.php copies unknown $_GET keys into _wpMediaGridSettings.queryVars, so openstation_chromeless=1 ended up as a media query arg. Core's wp.media.model.Query only observes wp.Uploader.queue when every arg is one it can filter on, so the observer was never attached and a finished upload never entered the grid's collection: the file uploaded, the grid showed nothing, and the item only appeared after reopening the window. Re-localize _wpMediaGridSettings after upload.php with our key removed. Read back what core produced rather than recomputing it, so the shim doesn't drift if core changes the shape. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The aria-button-if-js bail swallowed the Media list table's Trash / Restore / Delete Permanently links, which core stamps with the class but binds no handler to. They used to reach the parent's destructive-action path and get _wp_http_referer added; yielding meant a raw navigation without it. Under a Referrer-Policy of strict-origin or tighter, post.php then sees a bare origin, matches neither post.php nor post-new.php, and redirects the window to the site front page. Stamp the hint in the iframe instead, where the source page is just window.location. Yielding stays correct for these links: the inline onclick confirm now runs before anything happens, so cancelling actually cancels, which it did not when we preventDefaulted ahead of it in capture. Adds a vitest harness that runs the emitted interceptor against a fixture DOM, since the PHP suite can only assert on source text and both regressions of this shape got through that. Also corrects the docblock reference to tags.js (there is no edit-tags.js), decodes the media-grid settings as objects so nested values can't collapse to [], and rewrites the screen-guard test, which passed with the guard removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two Media Library bugs, both from shell plumbing leaking into a core screen.
Proposed Changes
aria-button-if-jsclass. FixesAdd Media Fileopening a redundant window on top of core's inline uploader, and restores the comment row actions and the plugin auto-update toggle, which broke the same way._wp_http_refererstamped on the href before the interceptor yields.openstation_chromelessis stripped from the query varsupload.phphands the media grid. Fixes the grid not showing an upload until the window is reopened.Incidentally fixes cancelling the "are you sure" confirm on Delete Permanently. The interceptor used to
preventDefaultin capture and hand the URL to the shell before the inlineonclickran, so cancelling still deleted the file.Why are these changes being made?
aria-button-if-jsis core's marker for "this anchor is an in-page button, the href is only the no-JS fallback". Our interceptor is capture-phase, so it beat the script that owns the button and gave the user the fallback URL instead of the action they clicked. Skipping on the class covers every surface with that shape rather than just this one button.The class doesn't promise a handler, though. The Media list table stamps it and binds nothing, so those hrefs really are the navigation, and the parent used to add
_wp_http_refererto them on its destructive-action path. Yielding loses that, and under aReferrer-Policyofstrict-originor tighterpost.phpthen sees a bare origin, matches neitherpost.phpnorpost-new.php, and redirects the window to the site front page. Stamping it in the iframe is simpler than the parent round trip: the source page is justwindow.location.The interceptor is JS emitted from a PHP heredoc, so the PHP suite can only assert that source strings appear in the right order. Both bugs of this shape got through that, hence the DOM-level harness.
upload.phpcopies unknown$_GETkeys into_wpMediaGridSettings.queryVars, andwp.media.model.Queryonly watches the upload queue when every query arg is one it can filter on. Our flag riding along was enough to stop the grid from ever seeing a finished upload. Core has no filter on that array, so the shim re-localizes the settings with the key removed.Testing Instructions
Media grid, both fixes:
Add Media File. Make sure only the inline uploader expands. No second window opens.Select Filesand pick an image. Make sure the new item appears in the grid as soon as the upload finishes, without reopening the window.Add Media Fileagain. Make sure the uploader collapses.On trunk, step 2 also opens an
Add Media Filewindow (closing it leaves the drop zone stranded above the grid), and step 3 uploads the file but never shows it.Media list table, where core stamps the class but binds no handler:
upload.php?mode=list).Delete Permanently(orTrashifMEDIA_TRASHis on), then cancel the confirm. Make sure the file is still there.Referrer-Policy: strict-originon admin responses, then check the window still lands on the media list rather than the site front page.Comment row actions:
Unapprove. Make sure the row turns yellow andPendinggoes up in place, with no reload and no new window.Plugin auto-update toggle:
Enable auto-updateson any plugin.Disable auto-updatesin place, with no reload and no new window.Regression check on the existing skip list:
Add New Plugin, clickInstall Nowon any plugin.update.php.