Descobri que esse bug também se manifesta como entradas corrompidas no histórico de navegação, o que considero um problema mais grave. Mais especificamente, um novo título é atribuído a uma URL antiga quando a navegação é tratada pelo JS. Isso acontece quase sempre no Firefox, mas é bem raro no Chrome (encontrei uma instância até agora: indo de /top para um tópico).
@sam está certo ao dizer que isso é causado pela ordem das operações em que a URL e o título são modificados. Gostaria que houvesse algum tipo de guia de melhores práticas publicado em algum lugar que dissesse qual é a ordem correta: sempre atualize o título depois de usar a API history.
Tentei fazer alguma depuração (e quero dizer desde já que sou bastante avesso a construir qualquer projeto moderadamente grande adjacente ao npm). Inicialmente, usei este código para fazer um pequeno reconhecimento:
De fato, mostrou que quase sempre há uma modificação de título logo antes da operação da API history. Infelizmente, não foi mais útil do que isso: relacionar o que acontece em tempo de execução com o código-fonte foi bastante difícil – as operações de interesse estão bastante dispersas, a pilha de chamadas era enganosa porque a execução já cedeu ao loop de eventos do Ember, e, em geral, a experiência de depuração no Firefox foi bastante infernal. Tendo mudado para o Chrome, tive um pouco mais de sucesso. Resumindo, tanto quanto sei, o Ember decide por si mesmo quando atualizar a URL. Por outro lado, a modificação do título pode ser iniciada de dois lugares: [1] e [2]
Apenas o último é executado antes da chamada da API history. O ‘ancestral comum de código’ deles está localizado aqui:
// Executa todos os hooks necessários de entrada/configuração/saída
this.setupContexts(newState, transition); // <- mudança de título iniciada aqui, acionando o evento `model.title:change`
// Verifica se uma redireção ocorreu na entrada/configuração
if (transition.isAborted) {
// TODO: forma mais limpa? distinguir entre routeInfos de destino?
this.state!.routeInfos = this.currentRouteInfos!;
return Promise.reject(logAbort(transition));
}
this._updateURL(transition, newState); // <- mudança de URL iniciada aqui
Interessantemente, “router.js é a microlib de roteamento usada pelo Ember.js.”
Agora, gostaria de passar o tratamento do problema para alguém que, ao contrário de mim, esteja remotamente familiarizado com a base de código do discourse.
Edição: esqueci de mencionar: document.title é modificado por [1] uma ou mais vezes depois de (ambos) ser modificado [2] e a URL ser modificada pela API history.