Приветствую!
Баг в bfcache: у Map нет метода remove()
Тема 4.20.1.c (в .d не проверял, все никак не поставлю), CS-Cart 4.20.1.
Файл design/themes/abt__unitheme2/templates/addons/abt__unitheme2/hooks/index/head_scripts.pre.tpl, строка 13:
const removeWs = (target) => {
window._websockets.remove(target);
}
Строкой выше (9) _websockets создаётся как new Map(), а у Map метод удаления — delete(), не remove(). В вашем же соседнем файле js/addons/abt__unitheme2/abt__ut2_bfcache.js:28 используется правильный вариант: window._websockets?.delete(closedWs).
Это не косметика. Исключение возникает внутри Proxy над ws.close до return target.apply(...), поэтому сокет не закрывается вообще:
ws.close = new Proxy(ws.close, {
apply(target, thisArg, args) {
if (args[0] !== 4444) removeWs(thisArg); // TypeError здесь
return target.apply(thisArg, args); // сюда уже не доходит
}
});
Страдает любой сторонний скрипт, закрывающий свой WebSocket. У нас это чат Ringostat: close() не выполняется, сокет остаётся в readyState 0. Один такой вызов даёт серию одинаковых исключений — у нас 12 подряд в одну секунду, все с этим стектрейсом:
TypeError: window._websockets.remove is not a function
at removeWs (страница:13)
at Object.apply
at M (https://script.ringostat.com/v5/ringostat-clients-script.js:1:34809)
Фикс в одну строку:
window._websockets?.delete(target);
Проверил после правки на боевом сайте: close(1000) отрабатывает и запись уходит из Map; close(4444) из pagehide запись сохраняет; pageshow восстанавливает сокеты вместе со слушателями — логика bfcache не ломается.