Replacing unload events handlers to use pagehide#5056
Replacing unload events handlers to use pagehide#5056spenserhale wants to merge 18 commits intoWordPress:trunkfrom
Conversation
Chrome has deprecated the unload event (https://developer.chrome.com/blog/deprecating-unload/) Fixes #55491
src/js/_enqueues/lib/gallery.js
Outdated
| }); | ||
|
|
||
| jQuery(window).on( 'unload', function () { window.tinymce = window.tinyMCE = window.wpgallery = null; } ); // Cleanup. | ||
| jQuery(window).on( 'pagehide', function () { window.tinymce = window.tinyMCE = window.wpgallery = null; } ); // Cleanup. |
There was a problem hiding this comment.
I think we should look into removing this instance entirely. Otherwise, if a tab is restored then it would be broken. And it wouldn't be possible to restore these variables with pageshow since they are gone.
There was a problem hiding this comment.
Having a hard time finding where this file is even used in core.
There was a problem hiding this comment.
It is enqueued in two functions: wp_media_upload_handler() and media_upload_gallery(). This latter function refers to the screen as the "legacy media uploader form".
There was a problem hiding this comment.
OK, I found out how to get there:
- Activate the Classic Editor plugin
- Create a new post
- Upload new photos in the post and create a gallery from them
- Save the post
- With the post ID in hand, go to
/wp-admin/media-upload.php?type=gallery&tab=type&post_id={POST_ID}
It looks like this:
I don't see any other way to get to that screen.
Given this, either we:
- Replace
unloadwithpagehideand add apageshowthat does the reload behavior below, or - We just remove the line of cleanup code altogether. It seems like it was put in place for an iOS Safari bug from over a decade ago, similar to https://github.com/WordPress/wordpress-develop/pull/5056/files#r1332289674, so it's probably obsolete.
@azaozz Since you introduced this line of code and are probably the most familiar with this codebase, what do you think we should do (also considering this is an inaccessible legacy screen)?
There was a problem hiding this comment.
See also how @spenserhale removed similar code in src/js/_enqueues/wp/mce-view.js: https://github.com/WordPress/wordpress-develop/pull/5056/files#r1332287807
There was a problem hiding this comment.
I'm just going to go ahead and remove this for consistency with src/js/_enqueues/wp/mce-view.js.
|
|
||
| // When a widget is moved in the DOM the dynamically-created TinyMCE iframe will be destroyed and has to be re-built. | ||
| $( editor.getWin() ).on( 'unload', function() { | ||
| $( editor.getWin() ).on( 'pagehide', function() { |
There was a problem hiding this comment.
The use of the unload event may not be a problem here for bfcache since it is added to the iframe and not the window as a whole. Still, if pagehide works the same we could still use it.
There was a problem hiding this comment.
Removing the handler altogether results in a breakage:
Screen.recording.2023-09-20.17.09.09.webm
Nevertheless, using pagehide instead of unload does work:
Screen.recording.2023-09-20.17.09.40.webm
There was a problem hiding this comment.
Nevertheless, bfcache remains disabled since TinyMCE is using unload. However, this doesn't seem like something we should remove per https://core.trac.wordpress.org/ticket/55491#comment:27
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Chrome has deprecated the unload event (https://developer.chrome.com/blog/deprecating-unload/) Fixes #55491
reload function was to fix #38511, but Firefox issue is no longer reproducible For Ticket #55491
was to fix #22552, but the iOS issue is no longer reproducible For Ticket #55491
…into 55491-replace-unload-events
| }, 3000 ); | ||
| } | ||
|
|
||
| function reload() { |
There was a problem hiding this comment.
Rationale for removal: https://core.trac.wordpress.org/ticket/55491#comment:15
There was a problem hiding this comment.
Introduced in r39282 to fix Core-38511 in 2016. It is to work-around a Firefox-specific bug. We should validate whether it is still an issue in Firefox. If not, we can remove this code.
There was a problem hiding this comment.
I tried reproducing the issue in Firefox according to the description of Core-38511 and I was unable.
There was a problem hiding this comment.
I've reported this to the 7-year old ticket: https://core.trac.wordpress.org/ticket/38511#comment:27
There was a problem hiding this comment.
@azaozz also please weigh in on whether we can remove this code.
There was a problem hiding this comment.
Given the age of this bug fix, it should be fine to remove. If we discover that this still creates an issue for Firefox users, we can always restore the fix.
There was a problem hiding this comment.
Yep, super old browser specific fix. LGTM to remove too.
| // Clean up. Prevents mobile browsers caching. | ||
| $(window).on('unload', function(){ | ||
| window.wp = null; | ||
| }); |
There was a problem hiding this comment.
Rationale for removal: https://core.trac.wordpress.org/ticket/55491#comment:17
However, if this depends on the server sending Cache-Control: no-store, then I'd like to further verify this.
@spenserhale What happens if no-store is not sent? Is there an issue then? I'd like to find a way to not have to send no-store in the admin so that we can benefit from bfcache, but if this depends on no-store then that would block enabling bfcache.
There was a problem hiding this comment.
Origin is d2d01ad to fix Core-22552: "Empty wp on unload to work around caching in iOS Safari."
This commit is 11 years old. Most likely this is no longer an issue in Safari. If so, we can most likely delete this entire event handler.
There was a problem hiding this comment.
+1 - fine to delete this super old bug fix/browser specific workaround. It is unlikely that the bug still exists, if it does we can always reintroduce a fix.
There was a problem hiding this comment.
Yep, same as above. Super old browser specific fix that seems okay to remove
|
|
||
| if ( window.addEventListener ) { | ||
| window.addEventListener( 'unload', function() { window.name = ''; }, false ); | ||
| window.addEventListener( 'pagehide', function() { window.name = ''; } ); |
There was a problem hiding this comment.
I was confused why the PageTransitionEvent being passed to this event handler has its persisted property set to false, both for the pagehide and the pageshow events. In looking at DevTools, I see:
So it is explained that the fact that window.open() was used to open the preview is another way that bfcache is disabled.
I think this is all good. I'm seeing that the window.name is being set to wp-preview-... when the tab is opened when clicking preview. When I navigate the preview window to another page, the window.name is set to an empty string. When I then re-preview a post I am opened in a new tab rather than the previous preview tab (which is now no longer a preview). If in that preview tab I go back to the previewed post, and then hit preview again, then it is that tab that gets updated with the latest preview content.
So I think we're good here.
| $(window).on( | ||
| 'pageshow.wp-heartbeat', | ||
| /** | ||
| * Handles pageshow event. | ||
| * | ||
| * @param {jQuery.Event} event | ||
| * @param {PageTransitionEvent} event.originalEvent | ||
| */ | ||
| function ( event ) { | ||
| if ( event.originalEvent.persisted ) { | ||
|
|
||
| // Continue connecting. | ||
| resume(); | ||
| } | ||
| } | ||
| ); |
There was a problem hiding this comment.
I'm not seeing this code firing.
There was a problem hiding this comment.
OK, I am seeing it fire. Apparently I have a browser extension which is disabling bfcache, but if I try in an incognito window then event.originalEvent.persisted is true.
…into 55491-replace-unload-events
| return __( 'The changes you made will be lost if you navigate away from this page.' ); | ||
| } | ||
| }).on( 'unload.edit-post', function( event ) { | ||
| }).on( 'pagehide.edit-post', function( event ) { |
There was a problem hiding this comment.
I don't see a single reference to the jQuery-namespaced unload.edit-post event name in WPdirectory, so I don't see any back-compat concerns here.
There was a problem hiding this comment.
Note that post lock is restored upon pageshow via heartbeat. See #5056 (comment)
| } | ||
|
|
||
| $(window).on( 'unload.wp-heartbeat', function() { | ||
| $(window).on( 'pagehide.wp-heartbeat', function() { |
There was a problem hiding this comment.
As with pagehide.edit-post, I don't see a single reference to the jQuery-namespaced unload.wp-heartbeat event name in WPdirectory, so I don't see any back-compat concerns here.
src/js/_enqueues/admin/post.js
Outdated
| */ | ||
| function ( event ) { | ||
| if ( event.originalEvent.persisted ) { | ||
| window.location.reload(); |
There was a problem hiding this comment.
In practice this code will never fire because this code is loaded on the Classic Editor and TinyMCE disables bfcache due to an unload event handler.
There was a problem hiding this comment.
Nevertheless, if that offending TinyMCE code is commented-out and Cache-Control: no-store is disabled (e.g. via plugin), then the experience is not great when you leave with a dirty editor state: you get the "Are you sure?" dialog when you leave and then when you go back, to get it again when it attempts to reload:
Screen.recording.2023-10-02.16.03.53.webm
There was a problem hiding this comment.
In the end, this code is not needed because upon pageshow, heartbeat will resume and it will start sending its wp-refresh-post-lock requests.
…en restoring from bfcache
| if ( event.originalEvent.persisted ) { | ||
| /* | ||
| * When page navigation is stored via bfcache (Back/Forward Cache), consider this the same as | ||
| * if the user had just switched to the tab since the behavior is similar. | ||
| */ | ||
| focused(); | ||
| } |
| jQuery(window).on( 'unload', function () { window.tinymce = window.tinyMCE = window.wpgallery = null; } ); // Cleanup. | ||
|
|
There was a problem hiding this comment.
Removal rationale: https://github.com/WordPress/wordpress-develop/pull/5056/files#r1332287807
See also #5056 (comment)
|
The changes from |
|
Committed in r56809. |



Chrome has deprecated the 'unload' event (https://developer.chrome.com/blog/deprecating-unload/)
Replacing event handlers to use the 'pagehide' instead based on the suggestion from Chrome's documentation.
Trac ticket: https://core.trac.wordpress.org/ticket/55491
Commit Message
Administration: Remove deprecated
unloadevent handlers and usepagehide(andpageshow) when appropriate.Use
pagehideevent instead ofunloadin the following cases:window.namewhen navigating away from a post preview.pageshowevent to resume as if it had been a focused tab in case page restored from bfcache.Also:
js/_enqueues/lib/gallery.js(introduced in [9894]). Do same forsrc/js/_enqueues/wp/media/models.js(introduced in [22872]). See #22552.js/_enqueues/wp/mce-view.jsfrom [39282]. See #38511.Fixes #55491.
Props spenserhale, westonruter, adamsilverstein, azaozz, shawfactor, peterwilsoncc, swissspidy.