O que o smoosh aconteceu?!
Uma proposta para um recurso de linguagem
JavaScript chamado Array.prototype.flatten
acaba sendo
incompatível com a Web. O envio do recurso no Firefox Nightly causou o travamento de pelo menos um site popular. Como o código problemático faz parte da biblioteca MooTools, é provável que muito mais sites sejam afetados. Embora o MooTools
não seja comumente usado para novos sites em 2018, ele era muito popular e
ainda está presente em muitos sites de produção.
O autor da proposta sugeriu, em tom de brincadeira, renomear flatten
para smoosh
para
evitar o problema de compatibilidade. A piada não ficou clara para todos. Algumas
pessoas começaram a acreditar incorretamente que o novo nome já tinha sido
decidido, e as coisas escalaram rapidamente.
O que Array.prototype.flatten
faz?
Array.prototype.flat
, originalmente proposto como Array.prototype.flatten
,
aplana matrizes de forma recursiva até o depth
especificado, que é o padrão
para 1
.
// Flatten one level:
const array = [1, [2, [3]]];
array.flat();
// → [1, 2, [3]]
// Flatten recursively until the array contains no more nested arrays:
array.flat(Infinity);
// → [1, 2, 3]
A mesma proposta inclui Array.prototype.flatMap
, que é semelhante a
Array.prototype.map
, exceto por achatar o resultado em uma nova matriz.
[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]
O que o MooTools está fazendo para causar esse problema?
O MooTools define a própria versão não padrão de Array.prototype.flatten
:
Array.prototype.flatten = /* non-standard implementation */;
A implementação do flatten
do MooTools é diferente do padrão proposto.
No entanto, esse não é o problema. Quando os navegadores enviam
Array.prototype.flatten
de forma nativa, o MooTools substitui a implementação
nativa. Isso garante que o código que depende do comportamento do MooTools
funcione conforme o esperado, independente da disponibilidade do flatten
nativo.
Até aqui, tudo bem!
Infelizmente, algo mais acontece. O MooTools copia todos os
métodos de matriz personalizados para Elements.prototype
(em que Elements
é uma
API específica do MooTools):
for (var key in Array.prototype) {
Elements.prototype[key] = Array.prototype[key];
}
for
-in
itera sobre propriedades "enumeráveis", que não incluem
métodos nativos como Array.prototype.sort
, mas incluem
propriedades atribuídas regularmente, como Array.prototype.foo = whatever
. No entanto,
e aqui está o problema: se você substituir uma propriedade não enumerável, por exemplo,
Array.prototype.sort = whatever
, ela continuará não enumerável.
No momento, Array.prototype.flatten = mooToolsFlattenImplementation
cria
uma propriedade flatten
enumerável, que é copiada mais tarde para Elements
. No entanto, se
os navegadores enviarem uma versão nativa de flatten
, ela se tornará não enumerável e
não será copiada para Elements
. Qualquer código que dependa do Elements.prototype.flatten
do MooTools agora está corrompido.
Embora pareça que mudar o Array.prototype.flatten
nativo para ser
enumerável corrigiria o problema, isso provavelmente causaria ainda mais
problemas de compatibilidade. Todos os sites que dependem de for
-in
para iterar em
uma matriz (o que é uma prática inadequada, mas acontece) receberiam de repente
uma iteração de loop adicional para a propriedade flatten
.
O maior problema aqui é modificar objetos integrados. Estender protótipos nativos geralmente é aceito como uma prática não recomendada atualmente, porque não se compõe bem com outras bibliotecas e códigos de terceiros. Não modifique objetos que não são seus.
Por que não manter o nome atual e quebrar a Web?
Em 1996, antes que o CSS se tornasse difundido e muito antes de o "HTML5" se tornar uma coisa, o site do Space Jam foi lançado. Hoje, o site ainda funciona da mesma forma que há 22 anos.
Como isso aconteceu? Alguém manteve esse site por todos esses anos, atualizado sempre que os fornecedores de navegadores lançavam um novo recurso?
A regra "não quebre a Web" é o princípio de design número um para HTML, CSS, JavaScript e qualquer outro padrão amplamente usado na Web. Se o envio de um novo recurso do navegador fizer com que os sites parem de funcionar, isso será ruim para todos:
- os visitantes dos sites afetados têm uma experiência do usuário ruim de repente;
- os proprietários do site passaram de um site que funcionava perfeitamente para um não funcional sem mudar nada;
- os fornecedores de navegadores que enviam o novo recurso perdem participação de mercado porque os usuários mudam de navegador depois de perceberem que "ele funciona no navegador X";
- Quando o problema de compatibilidade é conhecido, outros fornecedores de navegadores se recusam a enviar o produto. A especificação do recurso não corresponde à realidade (“nada além de um trabalho de ficção”), o que é ruim para o processo de padronização.
Claro, em retrospecto, o MooTools fez a coisa errada, mas quebrar a Web não os pune, pune os usuários. Esses usuários não sabem o que é uma ferramenta moo. Como alternativa, podemos encontrar outra solução, e os usuários podem continuar usando a Web. A escolha é fácil.
Isso significa que APIs ruins nunca podem ser removidas da plataforma Web?
Depende. Em casos raros, recursos incorretos podem ser removidos da Web. Mesmo apenas descobrir se é possível remover um recurso é um esforço muito complicado, exigindo telemetria extensiva para quantificar quantas páginas da Web teriam o comportamento alterado. No entanto, isso pode ser feito quando o recurso não é seguro o suficiente, é prejudicial aos usuários ou é usado muito raramente.
<applet>
, <keygen>
e
showModalDialog()
são
exemplos de APIs inválidas que foram removidas da Plataforma Web.
Por que não corrigimos o MooTools?
Aplicar um patch no MooTools para que ele não estenda mais objetos integrados é uma boa ideia. No entanto, isso não resolve o problema em questão. Mesmo que o MooTools lancasse uma versão corrigida, todos os sites que o usam teriam que ser atualizados para que o problema de compatibilidade fosse resolvido.
As pessoas não podem simplesmente atualizar a cópia do MooTools?
Em um mundo perfeito, o MooTools lançaria um patch, e todos os sites que usam o MooTools seriam magicamente atualizados no dia seguinte. Problema resolvido, certo?!
Infelizmente, isso não é realista. Mesmo que alguém identificasse o conjunto completo de sites afetados, conseguisse encontrar as informações de contato de cada um deles, conseguisse entrar em contato com todos os proprietários dos sites e os convencesse a fazer a atualização (o que pode significar refatorar toda a base de código), o processo todo levaria anos, na melhor das hipóteses.
Muitos desses sites são antigos e provavelmente não são mantidos. Mesmo que o mantenedor ainda esteja por perto, é possível que ele não seja um desenvolvedor da Web altamente qualificado como você. Não podemos esperar que todos mudem o site de 8 anos por causa de um problema de compatibilidade da Web.
Como funciona o processo do TC39?
O TC39 é o comitê responsável por evoluir a linguagem JavaScript pelo padrão ECMAScript.
O #SmooshGate fez com que algumas pessoas acreditassem que o "TC39 quer renomear flatten
para
smoosh
", mas era uma brincadeira interna que não foi bem comunicada externamente.
Decisões importantes, como renomear uma proposta, não são tomadas de ânimo leve, não são tomadas
por uma única pessoa e definitivamente não são tomadas de um dia para o outro com base em um único
comentário do GitHub.
O TC39 opera em um processo de preparo claro para propostas de recursos.
As propostas do ECMAScript e todas as mudanças importantes nelas (incluindo a renomeação
de métodos) são discutidas durante as reuniões do TC39 e precisam ser aprovadas por
todo o comitê antes de se tornarem oficiais. No caso de
Array.prototype.flatten
, a proposta já passou por várias
etapas de acordo, até a Etapa 3, indicando que o recurso está
pronto para ser implementado em navegadores da Web. É comum que outros problemas de especificação
surjam durante a implementação. Nesse caso, o feedback mais importante
veio depois de tentar enviar: o recurso, no estado atual,
quebra a Web. Problemas difíceis de prever como esses fazem parte da razão pela qual
o processo TC39 não termina apenas quando os navegadores oferecem um recurso.
O TC39 opera por consenso, o que significa que o comitê precisa concordar com todas as novas
mudanças. Mesmo que smoosh
fosse uma sugestão séria, é provável que
um membro do comitê se opusesse a ela em favor de um nome mais comum, como
compact
ou chain
.
A mudança de nome de flatten
para smoosh
(mesmo que não fosse uma piada) nunca foi
discutida em uma reunião do TC39. Dessa forma, a postura oficial do TC39 sobre
esse assunto é desconhecida. Nenhum indivíduo pode falar em nome de
toda a TC39 até que um consenso seja alcançado na próxima reunião.
As reuniões do TC39 geralmente são realizadas por pessoas com origens muito diversas: algumas têm anos de experiência em design de linguagem de programação, outras trabalham em um navegador ou mecanismo JavaScript, e um número cada vez maior de participantes está presente para representar a comunidade de desenvolvedores JavaScript.
Como o SmooshGate foi resolvido, no fim das contas?
Durante a reunião do TC39 de maio de 2018, o #SmooshGate
foi oficialmente resolvido com a renomeação de flatten
para flat
.
Array.prototype.flat
e Array.prototype.flatMap
enviados na V8 v6.9 e
no Chrome 69.