throttle calls to replaceState to fix security error when navigating quickly in Safari #3147

This commit is contained in:
hakimel 2022-03-09 09:44:19 +01:00
parent 853764bc8c
commit fc861fca50

View File

@ -3,6 +3,10 @@
*/ */
export default class Location { export default class Location {
// The minimum number of milliseconds that must pass between
// calls to history.replaceState
MAX_REPLACE_STATE_FREQUENCY = 250
constructor( Reveal ) { constructor( Reveal ) {
this.Reveal = Reveal; this.Reveal = Reveal;
@ -10,6 +14,8 @@ export default class Location {
// Delays updates to the URL due to a Chrome thumbnailer bug // Delays updates to the URL due to a Chrome thumbnailer bug
this.writeURLTimeout = 0; this.writeURLTimeout = 0;
this.replaceStateTimestamp = 0;
this.onWindowHashChange = this.onWindowHashChange.bind( this ); this.onWindowHashChange = this.onWindowHashChange.bind( this );
} }
@ -142,10 +148,10 @@ export default class Location {
else if( config.hash ) { else if( config.hash ) {
// If the hash is empty, don't add it to the URL // If the hash is empty, don't add it to the URL
if( hash === '/' ) { if( hash === '/' ) {
window.history.replaceState( null, null, window.location.pathname + window.location.search ); this.debouncedReplaceState( window.location.pathname + window.location.search );
} }
else { else {
window.history.replaceState( null, null, '#' + hash ); this.debouncedReplaceState( '#' + hash );
} }
} }
// UPDATE: The below nuking of all hash changes breaks // UPDATE: The below nuking of all hash changes breaks
@ -163,6 +169,26 @@ export default class Location {
} }
replaceState( url ) {
window.history.replaceState( null, null, url );
this.replaceStateTimestamp = Date.now();
}
debouncedReplaceState( url ) {
clearTimeout( this.replaceStateTimeout );
if( Date.now() - this.replaceStateTimestamp > this.MAX_REPLACE_STATE_FREQUENCY ) {
this.replaceState( url );
}
else {
this.replaceStateTimeout = setTimeout( () => this.replaceState( url ), this.MAX_REPLACE_STATE_FREQUENCY );
}
}
/** /**
* Return a hash URL that will resolve to the given slide location. * Return a hash URL that will resolve to the given slide location.
* *