スムージングが何ですか?
Array.prototype.flatten
という JavaScript 言語機能の提案が、ウェブと互換性がないことがわかりました。Firefox Nightly でこの機能をリリースしたところ、少なくとも 1 つの人気のあるウェブサイトが機能しなくなったため、問題のコードは広く使用されている MooTools ライブラリの一部であるため、多くのウェブサイトが影響を受けている可能性があります。(MooTools は 2018 年現在、新しいウェブサイトでは一般的に使用されていませんが、かつては非常に人気があり、多くの本番環境ウェブサイトにまだ存在しています)。
提案の作成者は、互換性の問題を回避するために flatten
の名前を smoosh
に変更することを冗談めかして提案しました。このジョークはすべてのユーザーに伝わらなかったため、新しい名前がすでに決まっていると誤って信じ始めたユーザーもおり、事態は急速にエスカレーションしました。
Array.prototype.flatten
の機能は次の通りです。
Array.prototype.flat
(元々 Array.prototype.flatten
として提案)は、指定された depth
(デフォルトは 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]
同じ提案には Array.prototype.flatMap
も含まれます。これは Array.prototype.map
に似ていますが、結果を新しい配列にフラット化します。
[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]
この問題の原因となっているのは、MooTools のどのような行為ですか?
MooTools は、独自の非標準バージョンの Array.prototype.flatten
を定義します。
Array.prototype.flatten = /* non-standard implementation */;
MooTools の flatten
の実装は、提案されている標準とは異なります。しかし、これは問題ではありません。ブラウザが Array.prototype.flatten
をネイティブに提供している場合、MooTools はネイティブ実装をオーバーライドします。これにより、ネイティブの flatten
が使用可能かどうかにかかわらず、MooTools の動作に依存するコードが意図したとおりに動作します。ここまでは順調です。
残念ながら、別の事象が発生します。MooTools は、カスタム配列メソッドをすべて Elements.prototype
にコピーします(Elements
は MooTools 固有の API です)。
for (var key in Array.prototype) {
Elements.prototype[key] = Array.prototype[key];
}
for
~in
は「列挙可能」なプロパティを反復処理します。これには、Array.prototype.sort
などのネイティブ メソッドは含まれませんが、Array.prototype.foo = whatever
などの定期的に割り当てられるプロパティは含まれます。ただし、Array.prototype.sort = whatever
などの列挙不可能なプロパティを上書きしても、列挙不可のままになります。
現在、Array.prototype.flatten = mooToolsFlattenImplementation
は列挙可能な flatten
プロパティを作成するため、後で Elements
にコピーされます。ただし、ブラウザがネイティブ バージョンの flatten
を配布する場合、それは列挙不能になり、Elements
にコピーされません。MooTools の Elements.prototype.flatten
に依存するコードはすべて破損します。
ネイティブの Array.prototype.flatten
を列挙可能に変更すると問題が解決するように思えますが、互換性の問題がさらに発生する可能性があります。for
~in
を使用して配列を反復処理するすべてのウェブサイト(これは好ましくない方法ですが、実際に行われています)で、flatten
プロパティのループが突然追加されます。
根本的な問題は、組み込みオブジェクトの変更です。ネイティブ プロトタイプの拡張は、他のライブラリやサードパーティ コードとうまくコンポーズされないため、現在では一般的に悪い方法と見なされています。自分が所有していないオブジェクトは変更しないでください。
既存の名前をそのままにして、ウェブを壊さないのはなぜですか?
1996 年、CSS が普及する前、そして「HTML5」が登場するずっと前に、スペース ジャムのウェブサイトが公開されました。現在、このウェブサイトは 22 年前とまったく同じ方法で動作しています。
なぜでしょうか?ブラウザ ベンダーが新機能をリリースするたびにウェブサイトを更新し、
結局のところ、「ウェブを壊さない」ことが、HTML、CSS、JavaScript など、ウェブで広く使用されているあらゆる標準における設計原則の最重要事項です。新しいブラウザ機能をリリースした結果、既存のウェブサイトが動作しなくなると、すべての人にとって不利な結果になります。
- 影響を受けるウェブサイトの訪問者が突然、ユーザー エクスペリエンスの不具合に遭遇する。
- ウェブサイト所有者が何も変更していないにもかかわらず、ウェブサイトが正常に動作していた状態から機能しなくなった状態に変化した
- 新機能をリリースしたブラウザ ベンダーが市場シェアを失う。ユーザーが「ブラウザ X では動作する」ことに気づき、ブラウザを切り替えるからです。
- 互換性の問題が判明すると、他のブラウザ ベンダーはリリースを拒否します。機能の仕様が現実と一致しない([nothing but a fun 編])ため、標準化プロセスに不利です。
確かに、後から考えると MooTools は間違ったことをしたが、ウェブを破壊しても彼らを罰することはできない。罰せられるのはユーザーである。このようなユーザーは、moo ツールが何であるかを知りません。また、別の解決策を見つけて、ユーザーがウェブを引き続き使用できるようにすることもできます。選択は簡単です。
ウェブ プラットフォームから不適切な API を削除できないということでしょうか?
場合によって変わります。まれに、不適切な機能がウェブから削除されることがあります。機能を削除できるかどうかを判断するだけでも非常に難しい作業です。ウェブページの動作が変更されるページの数を定量化するには、広範なテレメトリーが必要です。ただし、機能が十分に安全でない場合、ユーザーに有害な場合、または使用頻度が非常に低い場合は、この操作を行うことができます。
<applet>
、<keygen>
、showModalDialog()
は、ウェブ プラットフォームから正常に削除された不適切な API の例です。
MooTools を修正しないのはなぜですか?
MooTools にパッチを適用して、組み込みオブジェクトを拡張しないようにすることをおすすめします。ただし、これでは当面の問題は解決しません。MooTools がパッチ適用版をリリースしたとしても、互換性の問題を解消するには、それを使用している既存のすべてのウェブサイトを更新する必要があります。
MooTools のコピーを更新するだけでよいのでは?
理想的には、MooTools がパッチをリリースし、MooTools を使用しているすべてのウェブサイトが翌日に魔法のように更新されるはずです。これで問題は解決しましたか?
残念ながら、これは現実的ではありません。誰かがなんらかの方法で影響を受けるウェブサイトをすべて特定し、すべてのウェブサイトの連絡先情報を見つけ、すべてのウェブサイト所有者に連絡し、更新を実行するよう説得(コードベース全体をリファクタリングする)を説得したとしても、プロセス全体にはせいぜい数年かかるでしょう。
このようなウェブサイトの多くは古く、管理されていない可能性が高いのでご注意ください。 メンテナンス担当者がまだ存在する場合でも、その担当者があなたのような高度なスキルを持つウェブ デベロッパーではない可能性があります。ウェブの互換性の問題があるからといって、8 年前のウェブサイトを変更するよう求めることはできません。
TC39 のプロセスの仕組み
TC39 は、ECMAScript 標準を通じて JavaScript 言語の進化を担当する委員会です。
#SmooshGate により、「TC39 は flatten
の名前を smoosh
に変更したい」と考える人がいましたが、これは社内向けの冗談で、社外に十分に伝えられていませんでした。提案の名前変更などの重要な決定は、軽率に行われるものではなく、1 人の担当者が行うものでもありません。また、GitHub のコメント 1 件に基づいて、1 晩で行われるものでもありません。
TC39 は、機能提案に対して明確なステージング プロセスを運用しています。ECMAScript の提案とその主な変更(メソッドの名前変更など)は TC39 のミーティングで議論され、正式になる前に委員会全体の承認を得る必要があります。Array.prototype.flatten
の場合、提案はすでにいくつかの合意段階(ステージ 3 まで)を経ており、ウェブブラウザに実装する準備ができていることを示しています。実装中に追加の仕様の問題が発生することはよくあります。この場合、最も重要なフィードバックは、リリース後に寄せられました。この機能は、現在の状態ではウェブを破壊します。このような予測が難しい問題は、ブラウザが機能をリリースした後に TC39 プロセスが終了するわけではない理由の一つです。
TC39 はコンセンサスに基づいて運営されています。つまり、新しい変更については委員会が合意する必要があります。smoosh
が真面目な提案だったとしても、委員会のメンバーは compact
や chain
などの一般的な名前を支持し、反対する可能性が高いと思われます。
flatten
から smoosh
への名前変更は(冗談であっても)、TC39 会議で議論されたことはありません。そのため、このトピックに関する TC39 の公式なスタンスは現在不明です。次の会議でコンセンサスに達するまで、TC39 全体を代表して発言できる個人はいません。
通常、TC39 ミーティングには、さまざまなバックグラウンドを持つ人々が参加します。たとえば、プログラミング言語の設計に関する長年の経験を持つ人、ブラウザや JavaScript エンジンに携わる人、JavaScript デベロッパー コミュニティを代表する参加者が増えています。
SmooshGate は最終的にどのように解決されましたか?
2018 年 5 月の TC39 会議で、#SmooshGate は flatten
の名前を flat
に変更することで正式に解決されました。
Array.prototype.flat
と Array.prototype.flatMap
は、V8 v6.9 と Chrome 69 でリリースされました。