Сегодня начал писать проект частью которого были неубиваемые таймеры с Воркерами, выдерживающие полный перебор clearTimeout/clearInterval. Одним из условий было, что воркер или прочие функции/объекты могут подменить перед запуском скрипта. Для этого я написал функции
Но тут дело не в этих функциях и тем более не в моём проекте. Прогоняя всевозможные нативные объекты я наткнулся на вопиюще разное поведение браузеров при обработке объектов с typeof и toString.
Например, меня крайне поразил тот факт, что абсолютно все браузеры выдают разные значения на
Сафари во все нативные конструкторы и прототипы подсовывает Prototype, Constructor —
В статье описаны другие интересные случаи поведения браузеров с typeof и toString.
Firefox оптимизирует константы, заменяет кавычки и выравнивает код в toString:
Firefox выбрасывает исключение при попытке изменить navigator.userAgent
В опере более-менее хорошо с typeof и toString, но подозрительно следующее поведение:
Названия аналогичны Safari, кто у кого «перенял»?
Opera позволяет менять navigator.userAgent
Сафари кроме своих Prototype, Constructor префиксов имеет следующую особенность — все её нативные объекты имеют typeof === 'object', хотя некоторые (XHR и Worker) должны быть 'function'.
Сафари не меняет navigator.userAgent и не выбрасывает исключение
Из всего, что я проверял ИЕ смог опознать только XMLHttpRequest и RegExp, поэтому список для него не такой большой:
IE 8 выбрасывает исключение при попытке изменить navigator.userAgent, IE 9 ведет себя как сафари.
В IE 9 поправлены все вышеперечисленные баги, кроме того, что в [native code] функциях до сих пор полно \n
Хром имеет всего лишь одну «фичу»:
Хром как и сафари не меняет navigator.userAgent и не выбрасывает исключение
Сводная, полная таблица по браузерам и объектам: goo.gl/tD1jr
Код тестера: jsfiddle.net/azproduction/V4LeE
Хотя все браузеры (не ие 8) проходят acid 3, но в них остается ещё много много багов в деталях. Фиксированные ответы на typeof и toString очень важны для JavaScript с его утиной типизацией.
В исследовании участвовали объекты: Worker, XMLHttpRequest, CanvasContext, CanvasContext3D, Storage, WebSocket, FileReader, EventSource, navigator.geolocation, HTMLElement, RegExp, querySelectorAll, getElementsByTagName, childNodes.
Браузеры: Firefox 4, Firefox 3.6, Opera 11, Safari, IE 8, IE 9, Chrome 10 beta, Mobile Safari iOS 4.2.1
По техническим причинам не могу добавить все мобильные браузеры. Не стал выделять отдельно разбор полетов с HTMLElement — во всех браузерах творится ерунда.
PS Буду благодарен тем, кто просканирует остальные мобильные браузеры (Chrome Mobile, Opera Mobile) — киньте выдачу тестера мне в ЛС. Если вы желаете добавить какой-то свой тест — добавьте его в конец тестера с ссылкой в комментарий — позднее я обновлю таблицу.
UPD Добавлен Firefox 4, IE 9 (спасибо hf35), Mobile Safari iOS 4.2.1, ws для Opera (спасибо SKYnv)
Добавлены querySelectorAll, getElementsByTagName, childNodes
UPD2 Добавлены ответы для каждого объекта на Object.prototype.toString(...)
isNativeObject()
, isNativeFunction()
, каждая имеет с десяток условий и определяют подмену/не подмену функции/объекта и косвенных признаков указывающих на «мухлёж».Но тут дело не в этих функциях и тем более не в моём проекте. Прогоняя всевозможные нативные объекты я наткнулся на вопиюще разное поведение браузеров при обработке объектов с typeof и toString.
Например, меня крайне поразил тот факт, что абсолютно все браузеры выдают разные значения на
Worker.prototype + "";
// FF 3.6 [xpconnect wrapped native prototype]
// Op 11 [object DedicatedWorkerPrototype]
// Sa 4 [object WorkerPrototype]
// Ch 10 [object Object]
Сафари во все нативные конструкторы и прототипы подсовывает Prototype, Constructor —
[object WorkerConstructor], [object WorkerPrototype]
В статье описаны другие интересные случаи поведения браузеров с typeof и toString.
Firefox 3.6, Firefox 4
typeof Worker // function
Worker + "" // [object Worker] - не понятно почему [object ...]
Worker.prototype + "" // [xpconnect wrapped native prototype] ???
// аналогично с XMLHttpRequest и FileReader
typeof localStorage.prototype // object - во всех других браузерах undefined
localStorage.prototype + "" // null
navigator.geolocation + "" // [object GeoGeolocation] - не понятно какие ещё геолокации есть кроме Geo- во всех остальных браузерах [object Geolocation]
Firefox оптимизирует константы, заменяет кавычки и выравнивает код в toString:
(function(){return'a'+'b';}).toString();
// function () {
// return "ab";
// }
Firefox выбрасывает исключение при попытке изменить navigator.userAgent
Opera 11
В опере более-менее хорошо с typeof и toString, но подозрительно следующее поведение:
Worker.prototype + "" // [object DedicatedWorkerPrototype] - Dedicated!
XMLHttpRequest.prototype + "" // [object XMLHttpRequestPrototype]
EventSource.prototype + "" // [object EventSourcePrototype]
Названия аналогичны Safari, кто у кого «перенял»?
Opera позволяет менять navigator.userAgent
Safari и Mobile Safari
Сафари кроме своих Prototype, Constructor префиксов имеет следующую особенность — все её нативные объекты имеют typeof === 'object', хотя некоторые (XHR и Worker) должны быть 'function'.
RegExp.prorotype + "" // // - у всех кроме IE /(?:)/
Сафари не меняет navigator.userAgent и не выбрасывает исключение
IE 8
Из всего, что я проверял ИЕ смог опознать только XMLHttpRequest и RegExp, поэтому список для него не такой большой:
typeof XMLHttpRequest // object
XMLHttpRequest.prototype + "" // [Interface prototype object]
RegExp + "" // \nfunction RegExp() {\n [native code]\n}\n - к чему лишние переносы строк не ясно
RegExp.prorotype + "" // // - как и у Сафари
typeof document.getElementById // object o_O
IE 8 выбрасывает исключение при попытке изменить navigator.userAgent, IE 9 ведет себя как сафари.
В IE 9 поправлены все вышеперечисленные баги, кроме того, что в [native code] функциях до сих пор полно \n
Chrome 10 beta
Хром имеет всего лишь одну «фичу»:
Worker.hasOwnProperty("toString") // true - не понятно почему бы не брать с прототипа...
Хром как и сафари не меняет navigator.userAgent и не выбрасывает исключение
Это ещё не все
Сводная, полная таблица по браузерам и объектам: goo.gl/tD1jr
Код тестера: jsfiddle.net/azproduction/V4LeE
Заключение
Хотя все браузеры (не ие 8) проходят acid 3, но в них остается ещё много много багов в деталях. Фиксированные ответы на typeof и toString очень важны для JavaScript с его утиной типизацией.
В исследовании участвовали объекты: Worker, XMLHttpRequest, CanvasContext, CanvasContext3D, Storage, WebSocket, FileReader, EventSource, navigator.geolocation, HTMLElement, RegExp, querySelectorAll, getElementsByTagName, childNodes.
Браузеры: Firefox 4, Firefox 3.6, Opera 11, Safari, IE 8, IE 9, Chrome 10 beta, Mobile Safari iOS 4.2.1
По техническим причинам не могу добавить все мобильные браузеры. Не стал выделять отдельно разбор полетов с HTMLElement — во всех браузерах творится ерунда.
PS Буду благодарен тем, кто просканирует остальные мобильные браузеры (Chrome Mobile, Opera Mobile) — киньте выдачу тестера мне в ЛС. Если вы желаете добавить какой-то свой тест — добавьте его в конец тестера с ссылкой в комментарий — позднее я обновлю таблицу.
UPD Добавлен Firefox 4, IE 9 (спасибо hf35), Mobile Safari iOS 4.2.1, ws для Opera (спасибо SKYnv)
Добавлены querySelectorAll, getElementsByTagName, childNodes
UPD2 Добавлены ответы для каждого объекта на Object.prototype.toString(...)