Câu hỏi thường gặp về SmooshGate

Smoosh đã xảy ra điều gì?!

Đề xuất cho JavaScript tính năng ngôn ngữ có tên Array.prototype.flatten hoá ra là Không tương thích với web. Việc vận chuyển tính năng trong Firefox Nightly đã dẫn đến ít nhất một trang web phổ biến phá vỡ. Do mã có vấn đề là một phần của MooTools phổ biến thì có thể nhiều trang web khác bị ảnh hưởng. (Mặc dù MooTools không thường được sử dụng cho các trang web mới trong năm 2018, nó đã từng rất phổ biến và vẫn xuất hiện trên nhiều trang web sản xuất.)

Tác giả đề xuất đùa giỡn đề xuất đổi tên flatten thành smoosh thành để tránh vấn đề về khả năng tương thích. Mọi người không rõ câu chuyện đùa đó, một số mọi người bắt đầu tin nhầm rằng tên mới đã được quyết định và mọi việc được chuyển lên cấp trên nhanh chóng.

Array.prototype.flatten có chức năng gì?

Array.prototype.flat, ban đầu được đề xuất là Array.prototype.flatten, làm phẳng các mảng theo cách đệ quy đến depth được chỉ định (theo mặc định) đến 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]

Đề xuất tương tự bao gồm Array.prototype.flatMap, giống như Array.prototype.map, ngoại trừ hàm này sẽ làm phẳng kết quả thành một mảng mới.

[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]

MooTools dùng để làm gì mà gây ra sự cố này?

MooTools xác định phiên bản Array.prototype.flatten không chuẩn của riêng chúng:

Array.prototype.flatten = /* non-standard implementation */;

Cách triển khai flatten của MooTools khác với tiêu chuẩn đề xuất. Tuy nhiên, đây không phải là vấn đề! Trường hợp trình duyệt bắt đầu có sẵn Theo mặc định, Array.prototype.flatten, MooTools sẽ ghi đè chế độ gốc trong quá trình triển khai. Điều này đảm bảo rằng mã dựa trên hành vi MooTools hoạt động như dự kiến bất kể có flatten gốc hay không. Đến giờ thì mọi thứ vẫn ổn!

Rất tiếc, sau đó lại có điều gì khác xảy ra. MooTools sao chép trên tất cả phương thức mảng tuỳ chỉnh vào Elements.prototype (trong đó Elements là một phương thức API dành riêng cho MooTools):

for (var key in Array.prototype) {
  Elements.prototype[key] = Array.prototype[key];
}

for-in lặp lại đối với các tài sản "có thể liệt kê", không bao gồm các phương thức gốc như Array.prototype.sort, nhưng bao gồm các thuộc tính thường xuyên được chỉ định như Array.prototype.foo = whatever. Nhưng — và đây là phần giới thiệu – nếu bạn ghi đè một thuộc tính không thể liệt kê, ví dụ: Array.prototype.sort = whatever, lớp này vẫn không thể liệt kê.

Hiện tại, Array.prototype.flatten = mooToolsFlattenImplementation tạo một thuộc tính flatten có thể liệt kê, nên sau đó thuộc tính này được sao chép vào Elements. Nhưng nếu trình duyệt gửi phiên bản gốc của flatten, phiên bản này không thể liệt kê được và chưa được sao chép vào Elements. Bất kỳ mã nào dựa trên MooTools Elements.prototype.flatten hiện đã bị lỗi.

Mặc dù có vẻ như thay đổi Array.prototype.flatten gốc thành liệt kê sẽ khắc phục sự cố, điều này có thể khiến nhiều vấn đề hơn nữa các vấn đề về khả năng tương thích. Mọi trang web dựa vào for-in để lặp lại một mảng (một phương pháp không phù hợp nhưng vẫn xảy ra) sau đó sẽ đột nhiên nhận được thêm một vòng lặp nữa cho thuộc tính flatten.

Vấn đề cơ bản lớn hơn ở đây là sửa đổi các đối tượng tích hợp. Đang mở rộng các nguyên mẫu gốc hiện nay thường được coi là phương pháp không phù hợp vì không kết hợp hài hoà với các thư viện khác và mã của bên thứ ba. Không sửa đổi của các đối tượng mà bạn không sở hữu!

Tại sao chúng ta không chỉ giữ tên hiện tại và phá vỡ Web?

Vào năm 1996, trước khi CSS trở nên phổ biến và rất lâu trước khi "HTML5" trở thành một trang web Space Jam đã đi vào hoạt động. Trang web này hiện vẫn hoạt động giống như 22 năm trước.

Điều đó xảy ra như thế nào? Ai đó đã duy trì trang web đó trong suốt những năm này, cập nhật trình duyệt mỗi lần nhà cung cấp trình duyệt xuất bản tính năng mới?

Hoá ra, “không phá vỡ trang web” là nguyên tắc thiết kế số một cho HTML, CSS, JavaScript cũng như bất kỳ tiêu chuẩn nào khác được sử dụng rộng rãi trên Web. Nếu việc cung cấp một tính năng mới của trình duyệt khiến các trang web hiện có ngừng hoạt động nhưng điều này không tốt cho mọi người:

  • khách truy cập của các trang web bị ảnh hưởng đột nhiên có trải nghiệm người dùng không tốt;
  • chủ sở hữu trang web đi từ một trang web hoạt động hoàn hảo thành không hoạt động mà không thay đổi gì;
  • các nhà cung cấp trình duyệt vận chuyển tính năng mới sẽ mất thị phần, do người dùng chuyển đổi trình duyệt sau khi nhận thấy “nó hoạt động trong trình duyệt X”;
  • khi biết vấn đề tương thích, các nhà cung cấp trình duyệt khác sẽ từ chối giao hàng nó. Thông số kỹ thuật của tính năng không phù hợp với thực tế (“không có gì ngoài một tác phẩm hư cấu”), điều này không tốt cho quá trình chuẩn hoá.

Chắc chắn rồi, khi nhìn lại, MooTools đã làm sai rồi, nhưng việc phá vỡ Internet không trừng phạt họ mà phạt người dùng. Những người dùng này không biết là gì của bạn là gì. Ngoài ra, chúng ta có thể tìm được một giải pháp khác để người dùng có thể tiếp tục sử dụng web. Lựa chọn rất dễ đưa ra.

Điều đó có nghĩa là API có hại sẽ không bao giờ bị xoá khỏi Nền tảng web?

Còn tùy. Trong một số ít trường hợp, các tính năng xấu có thể bị xoá khỏi môi trường web. Thậm chí chỉ là hình tượng trưng liệu có thể xóa một tính năng hay không là một công việc rất khó khăn, cần phải sử dụng phương pháp đo từ xa chuyên sâu để định lượng có bao nhiêu trang web sẽ có đã thay đổi hành vi. Tuy nhiên, khi tính năng này không an toàn sẽ gây hại cho hoặc được sử dụng rất hiếm khi, điều này có thể thực hiện được.

<applet>, <keygen>showModalDialog() đã sẵn sàng ví dụ về API không hợp lệ đã bị xoá thành công khỏi Nền tảng web.

Vì sao chúng ta không sửa MooTools?

Việc vá lỗi MooTools để không còn mở rộng các đối tượng tích hợp sẵn là một cách ý tưởng. Tuy nhiên, việc này không giải quyết được vấn đề bạn đang gặp phải. Ngay cả khi MooTools để phát hành một phiên bản bản vá, tất cả trang web hiện tại đang sử dụng phiên bản này sẽ phải để khắc phục sự cố về khả năng tương thích.

Không thể mọi người chỉ cần cập nhật bản sao MooTools của họ sao?

Một thế giới hoàn hảo, MooTools sẽ phát hành một bản vá và mọi trang web bằng cách sử dụng MooTools sẽ được cập nhật kỳ diệu vào ngày hôm sau. Vấn đề đã được giải quyết, đúng không?!

Rất tiếc, điều này không thực tế. Ngay cả khi ai đó bằng cách nào đó có thể xác định toàn bộ các trang web bị ảnh hưởng, hãy quản lý để tìm thông tin liên hệ của từng nhóm, liên hệ thành công với tất cả chủ sở hữu trang web, và thuyết phục tất cả họ thực hiện cập nhật (có thể phải tái cấu trúc toàn bộ cơ sở mã của họ), thì toàn bộ quá trình tốt nhất sẽ mất hàng năm.

Xin lưu ý rằng nhiều trang web trong số này đã cũ và có thể không được duy trì. Ngay cả khi người bảo trì vẫn còn ở đó, có thể họ không phải nhà phát triển web có tay nghề cao như bạn. Chúng tôi không thể kỳ vọng rằng mọi người đều tham gia và thay đổi trang web được 8 năm tuổi của họ do vấn đề về khả năng tương thích với web.

Quy trình TC39 hoạt động như thế nào?

TC39 là uỷ ban chịu trách nhiệm phát triển ngôn ngữ JavaScript thông qua tiêu chuẩn ECMAScript.

#SmooshGate khiến một số người tin rằng “TC39 muốn đổi tên flatten thành smoosh", nhưng đó chỉ là một câu đùa thân thuộc và không được truyền đạt rõ ràng ra bên ngoài. Các quyết định quan trọng như đổi tên đề xuất không được xem xét cẩn thận và sẽ không được đưa ra và chắc chắn không được thực hiện qua đêm dựa trên Nhận xét trên GitHub.

TC39 hoạt động theo quy trình thử nghiệm rõ ràng cho các đề xuất tính năng. Đề xuất ECMAScript và mọi thay đổi lớn đối với đề xuất đó (bao gồm phương pháp đổi tên) sẽ được thảo luận trong các cuộc họp TC39 và cần được trước khi trở thành người chính thức. Trong trường hợp Array.prototype.flatten, đề xuất này đã trải qua vài bước giai đoạn thoả thuận, cho đến Giai đoạn 3, cho biết tính năng này sẵn sàng để triển khai trong trình duyệt Web. Thông số kỹ thuật bổ sung thường gặp phát sinh trong quá trình triển khai. Trong trường hợp này, bước quan trọng nhất phản hồi đến sau khi cố gắng vận chuyển: tính năng, ở trạng thái hiện tại, phá vỡ Web. Các vấn đề khó dự đoán như thế này là một phần lý do tại sao quy trình TC39 không chỉ kết thúc khi các trình duyệt có một tính năng.

TC39 hoạt động dựa trên sự đồng thuận, nghĩa là uỷ ban phải thống nhất về mọi thay đổi. Ngay cả khi smoosh là một đề xuất nghiêm túc, có vẻ như một thành viên uỷ ban sẽ phản đối biểu quyết đó bằng một cái tên phổ biến hơn như compact hoặc chain.

Việc đổi tên từ flatten thành smoosh (ngay cả khi đó không phải là một trò đùa) đã chưa được thảo luận tại cuộc họp TC39. Do đó, quan điểm chính thức của TC39 về chủ đề này hiện chưa xác định. Không cá nhân nào có thể phát biểu thay mặt cho tất cả TC39 cho đến khi đạt được sự đồng thuận tại cuộc họp tiếp theo.

Các cuộc họp TC39 thường có sự tham gia của những người có tính đa dạng cao nền tảng: một số người có nhiều năm kinh nghiệm thiết kế ngôn ngữ lập trình, những người khác làm việc trên trình duyệt hoặc công cụ JavaScript và số lượng người dùng đại diện cho cộng đồng nhà phát triển JavaScript.

Rốt cuộc thì SmooshGate đã được giải quyết như thế nào?

Trong cuộc họp TC39 vào tháng 5 năm 2018, #SmooshGate đã chính thức được giải quyết bằng cách đổi tên flatten thành flat.

Array.prototype.flatArray.prototype.flatMap được xuất bản trong V8 phiên bản 6.9 và Chrome 69.