Pull to refresh

Выкрутасы Opera

Reading time3 min
Views8.9K
Сразу замечу, данный пост не попытка подлить масла в огонь браузерной холивар. Это маленький рассказ об одном моем открытии в браузере Opera.
Многие наверняка слышали, что Опера «фиксит» работу некоторых сайтов (и js библиотек), чтобы те в свою очередь нормально работали в этом браузере. Я как то натыкался на страницу с перечислением какие сайты и какие проблемы на них исправлены. Но как то не задумывался, как же они это «правят».

И вот сегодня один из пользователей прислал нам «баг репорт» о том что наш сервис (ajax приложение) не работает в Опера 9.24, и прислал сообщение об ошибке из «Консоли ошибок». Странность в этом то, что еще недавно все работало в этой и других (более младших) версиях Оперы, а новых релизов у нас не было более полутора месяцев. Открыл Оперу, прошел на урл — у меня тоже не работает. Причем вылетает в самом начале. Ругается на странную строчку, ищу в своих скриптах. Нет такой. Тут вспомнил про «патчи» Оперы для сайтов — может там? После непродолжительных поисков нашел файл с хаками — который по сути обычный JS файл (называется browser.js), грузится самым первым и делает некоторую работу. Там то и оказалась злосчастная строчка. Немного осмотрелся: к чему это, что такое. Оказывается этот файл обновляется сам, и последний его update был 13 декабря (для этой версии) в нем так и написано, а закачался ко мне 20 декабря, когда я запускал оперу последний раз.
По большей части все костыли в этом файле адресные, то есть предназначены для конкретных сайтов (да! проверяется location.hostname). Но часть общих. В частности, в моем случае проблему вызвал следующий код:
    Array.prototype.concat = function(){  // working around incompatibility with prototype, bug 241832
        var array = [];
        for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
        for(var i = 0, length = arguments.length; i < length; i++) {
          if(arguments[i].constructor == Array) {
        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
          } else {
        array.push(arguments[i]);
          }
        }
        return array;
    }

Насторожило. Где то это я уже видел. Смотрю на комментарий (потому как не понятно к чему это они сюда приляпали) — точно: «working around incompatibility with prototype». В prototype я как раз это и видел. Посмотрел prototype, на машине оказалась версия 1.5 в которой есть:
if (window.opera){
  // тот же код
}

Что за бред? В свое время сломал голову осмысливая данные строки в prototype. Я не знаю чем их не устроила реализация concat в Опера, но я не нашел тогда отличий от других реализации в других браузерах. Однако в Опере решили сделать как в prototype, создавая патовую ситуацию для приложений, когда arguments[i] имеет значение null или undefined (проверочку бы не помешало сделать). И не важно что вы пишите и какие библиотеки используете, в опера concat работает как в prototype.
Ломаю голову как чинить (до этого были маленькие проблемы только с методомы Array.splice, но тут то что/как?!).
А вообще всем рекомендую изучить этот browser.js, особенно тем кому интересно изучить работу Оперы изнутри. К тому же очень занятны комментарии, например:
// 194334, Y!Mail remove selectSingleNode and selectNodes
/* because Yahoo mail is better at emulating proprietary IE functions than we are.. */
Node.prototype.selectSingleNode=undefined;
Node.prototype.selectNodes=undefined;

Кстати все эти танцы с бубном в Opera называют «magic fixes». Действительно «magic»!

ЗЫ Пока писал каким то чудесным образом баг починился, но только у меня. Файл browser.js тот же самый, но ошибок не выдает. У остальных ничего не работает и пишет в консоль ошибку.
UPDATE Выяснилось почему у меня «починился» баг. Дело в том, что в начале файла browser.js содержится подпись содержимого. Соответственно если поменять содержимое файла (я как раз поставил перевод строки в одном месте), то подпись уже будет другой и Опера перестает использовать этот файл, так как считает битым и ждет следующего обновления. Браузер еженедельно проверяет обновления этого файла, скачивает и использует, если конечно это не отключено в конфиге (например, opera6.ini). Настройка называется Browser Javascript. Спасибо rsa2048 за наводку.
Tags:
Hubs:
+40
Comments49

Articles