I have found out that this bug also surfaces out as history entries in browsing history being somewhat corrupted which I consider a more severe issue. More specifically a new title is assigned to an old URL when navigation is handled by JS. This happens pretty much always in Firefox but is quite rare in Chrome (I found one instance so far: going from /top to a topic).
@sam is right that it’s caused by the order of operations in which the URL and title are modified. I wish there were some kind best practices guide published somewhere that says what the correct order is: always update the title after using history API.
I’ve tried to do some debugging (and I wanna say in advance that I’m quite averse to building any moderately big npm adjacent project). Initially I used this code to do a small reconnaissance:
It indeed has shown that there’s almost always one title modification right before history API operation. Unfortunately it wasn’t more helpful than that: relating what happens at runtime to the source code was quite hard – the operations of interest are quite scattered, call stack was misleading b/c execution already yielded to Ember’s event loop, and generally debugging experience in Firefox was quite hellish. Having switched to Chrome, I was a bit more successful. Long story short, AFAIK Ember decides by itself when to update URL. On the other hand, modification of the title can be initiated from two places: [1] and [2]
Only the latter is ever executed before the history API call. The ‘common code ancestor’ of them is located here:
// Run all the necessary enter/setup/exit hooks
this.setupContexts(newState, transition); // <- title change initiated here, by triggering `model.title:change` event
// Check if a redirect occurred in enter/setup
if (transition.isAborted) {
// TODO: cleaner way? distinguish b/w targetRouteInfos?
this.state!.routeInfos = this.currentRouteInfos!;
return Promise.reject(logAbort(transition));
}
this._updateURL(transition, newState); // <- url change initiated here
Interestingly, “router.js is the routing microlib used by Ember.js.”
Now I would like to hand out handling the issue to some one that’s, contraty to me, remotely familiar with discourse codebase.
Edit: forgot to mention: document.title is modified by [1] one or more times after (both) it being modified [2] and url being modified by history API.