О том, как ошибка, найденная в IE9 Platform Preview, стала причиной изменения стандарта Javascript перевод

image
Когда мы впервые обнародовали наши планы по поводу предварительных версий IE9, мы сказали что «разработчики и люди, интересующиеся стандартами и веб-разработкой, смогут попробовать предварительную версию IE9 и высказать свои замечания и предложения относительно его работы». На данный момент мы ежедневно получаем отзывы и используем их для улучшения Internet Explorer 9. Однако обратная связь иногда касается не только IE9. Эта история о том, как недавний отзыв на Internet Explorer 9 Platform Preview вызвал изменение нового стандарта JavaScript – 5-ую редакцию EcmaScript.

Стандарт «EcmaScript 5» был официально принят в декабре 2009 года, и третья предварительная версия Internet Explorer 9 является нашей первой наиболее полной его реализацией. ES5 был спроектирован так, чтобы оставаться полностью совместимым с существующими сайтами, и технический комитет TC39 работал над тем, чтобы избежать любых не связанных с безопасностью изменений, которые могли бы привести в нерабочее состояние существующий JavaScript-код. Однако в мире программного обеспечения ничего совершенного не бывает, и, когда мы выпустили третью предварительную версию Internet Explorer 9, нам стало интересно, обнаружатся ли какие-нибудь проблемы совместимости с существующими сайтами, связанные с ES5.

image
Вскоре после выпуска предварительной версии нашего браузера мы получили несколько жалоб, что некоторые веб-приложения, использующие jQuery некорректно работают в IE9. Мы выяснили, что проблема заключалась в следующем методе JQuery API, который в некоторых случаях не работал, потому что код метода перед вызовом Object.prototype.toString не проверял переданное пользователем значение на null или undefined. В частности некоторые вызовы этого метода jQuery
isFunction: function( obj ) {
   return toString.call(obj) === "[object Function]";
}


* This source code was highlighted with Source Code Highlighter.

завершаются исключением: “TypeError: Object expected”. Дальнейший анализ показал, что toString является встроенным методом Object.prototype.toString, который вызывал сбой, когда isFunction вызывала его со значением undefined в качестве аргумента. Почему данное исключение возникало только в IE9, а не в более ранних версиях IE, а также в браузерах других производителей? Именно потому, что поведение третей предварительной версии IE9 в режиме стандартов действительно соответствует спецификации ES5 Object.prototype.toString.

Согласно предыдущей спецификации EcmaScript вызов встроенного метода с параметром null или undefined приводит к передаче «глобального объекта» (у браузеров это объект DOM window). Это открывает целый ряд потенциальных дыр в безопасности для фреймворков, цель которых обеспечить работу веб-приложений в безопасном режиме.

Спецификация ES5 изменила данное поведение так, что передача null или undefined не приводит к передаче в функцию объекта window. Определение каждого встроенного метода было обновлено специально для решения проблемы получения этих значений в качестве значения this. Технический комитет пытался сделать так, чтобы сохранить обратную совместимость для обычного использования и генерировать исключение в случае, когда это невозможно. Это создало проблему совместимости, описанную выше.

Данная проблема может быть просто решена изменением кода jQuery:
isFunction: function( obj ) {
   return obj && toString.call(obj) === "[object Function]";
},


* This source code was highlighted with Source Code Highlighter.

На самом деле команда jQuery планирует внести данное изменение. Однако данное изменение не затронет тысячи локально используемых библиотек jQuery существующих в вебе. Учитывая широкую распространенность jQuery, становится очевидным, что спецификация ES5 содержит серьезную проблему совместимости. Также вполне очевидно, каким образом мы можем изменить нашу реализацию ES5 в IE9 для решения проблемы. Мы можем просто вернуть строковое значение "[object Object]", это же значение возвращает IE8 в данной ситуации. Такой фикс не добавляет проблем с безопасностью, которые старается решить ES5. Тем не менее, мы не хотим в одностороннем порядке вводить такое различие в нашу реализацию нового стандарта. Данное решение не поможет решению проблем совместимости и интероперабельности, если IE исправит эту проблему одним из способов, а другие браузеры не исправят вообще или сделают это иначе.

Как только мы разобрались в проблеме и возможном решении, я поднял этот вопрос в списке рассылки для обсуждений комитета TC39. Мое первое сообщение по данной проблеме было опубликовано в 17:51 в пятницу 25 июня. К 22 часам уже были получены ответы от членов TC39, представляющих Apple, Mozilla и Google. Мы все согласились, что это была проблема совместимости, которую необходимо решить, и генерация исключения в данном случае не нужна и нежелательна. Изначально мы согласились с тем, что идея возврата строкового значения, как написано в ES3, для таких случаев выглядит как хорошая идея. Тем не менее, при дальнейшем обсуждении на выходных мы поняли, что не все браузеры в данный момент возвращают "[object Object]", мы также рассматривали следующие значения "[object Window]" и "[object Global]".

Было предложено возвращать "[object null]" и "[object undefined]". Это решение, кажется, лучшее, поскольку не только устраняет такую проблему, как в случае jQuery, но и позволяет явно различать неопределенные и null-объекты. Данное решение также повышает интероперабельность браузеров, потому что требует, чтобы браузеры выдавали одинаковый результат, а не ситуацию ES3, которая приводила к различным результатам в различных браузерах.

Во вторник данное решение было принято консенсусом как окончательное. Как только было достигнуто согласие, я передал пересмотренные спецификации Object.prototype.toString в команду разработчиков IE9 JavaScript, чтобы они могли внести исправления в текущую реализацию перед публичным испытанием следующей предварительной версии IE9. Mozillа также подтвердила, что примет данное исправление в следующей бета-версии Firefox. Я также обновил официальный список исправлений TC39 для ES5, это изменение описано в разделе 15.2.4.2 спецификации.

Веб-стандарты – сложные программные артефакты, и как все ПО, они содержат ошибки. Иногда лучший способ найти и исправить ошибку совместимости, это реализовать стандарт в широко распространенном браузере. Данный способ обычно применяется в контексте выпуска ранних версий браузера, как в случае с Internet Explorer 9 Platform Preview. Таким образом, когда вы, как веб-разработчик отправляете фидбек на какой-либо конкретный браузер, вы также даете обратную связь тем стандартам, которые он реализует. Конечно, в таком случае, авторы браузеров и писатели стандартов должны иметь возможность быстро отреагировать на проблему. Быстрое реагирование на проблему ES5 Object.prototype.toString, а также другие нестыковки, хороший пример того, как разработчики браузеров и другие члены TC39 могут и работают вместе для обеспечения совместимого и интероперабельного веба. Но все начинается с ваших отзывов, которым мы всегда рады.

--
Allen Wirfs-Brock
Microsoft JavaScript Language Architect
+93
21 июля 2010, 11:57
13
mstyura 10,6

комментарии (31)

+25
boston #
Ну молодцы, что сказать. Всё правильно сделали.
–37
amarao #
Интересно, где были их совещания с производителями прочих браузеров в момент реализации ActiveX…
+22
mstyura #
Согласно википедии
ActiveX… ...It was introduced in 1996 by Microsoft

О каких производителях и стандартах Вы говорите?
Да, вспоминаем, что Опера существует с 1995 года, но разве она имела на тот момент хоть какой-либо авторитет?
Вспоминаем, когда образовался w3c — 1994, и он так же не мог иметь сильного влияния всего-лишь после двух лет сущетсрования.
Да, был Netscape, но они тоже творили, что хотели.
А ведь главное сейсас не это, а то, что Майкрософт понял свои ошибки и исправляется.
+1
Anei #
Так тогда ж откровенная война шла.
+3
z123 #
просто на то время производители прочих браузеров ещё ещё пешком под стол ходили, с ними было неинтересно совещаться
НЛО прилетело и опубликовало эту надпись здесь
0
Grundiss #
А что произойдет, если логика моего приложения строится на таком выражении:
try {
o.toString();
alert('ok');
} catch(e) {
alert('Something wrong!');
}
0
PVOID #
Я так понял что как у null и undefined по прежнему нельзя вызывать методы. Изменения коснулись только вызова toString с явным указанием this
–1
kirilloid #
Мне почему-то показалось, что изменения коснутся Function.prototype.call
0
Grundiss #
хорошо:
try{
toString.call(a);
} catch(e) {
alert('looks like a == null');
}
0
PVOID #
Тогда ваш код не работал. Читайте в статье.
0
Grundiss #
Действительно, извиняюсь, выпустил из виду.
0
mironov_anton #
Скажите, а есть ли какая-то официальная информация по поводу поддержки Websockets в IE9?
Пытался найти – не смог.
НЛО прилетело и опубликовало эту надпись здесь
0
mironov_anton #
И не будет?
НЛО прилетело и опубликовало эту надпись здесь
+2
shai_hulud #
прошу прощения, но вы неправильно используете сложный технический термин «красноглазые»
НЛО прилетело и опубликовало эту надпись здесь
–1
shai_hulud #
lurkmore.ru/%D0%9A%D1%80%D0%B0%D1%81%D0%BD%D0%BE%D0%B3%D0%BB%D0%B0%D0%B7%D0%B8%D0%BA%D0%B8

я понимаю что между сборками ядра нет времени расширять кругозор
+4
develop7 #
Да нормально, фанаты — они везде фанаты. А красные глаза намного проще приобрести в процессе секса с IE6, нежели в процессе компиляци ядра.
–4
shai_hulud #
там скорее можно лишиться волос, чисто на «трах-тибидохах».

Вы не поймите меня неправильно, я ничего не имею против компиляции ядра, только против фанатиков от любой «религии»
0
develop7 #
только против фанатиков
аналогично
+7
bolk #
Что-то я вас не понимаю. А есть прецеденты, когда MS или сторонники MS заявляли, что «в IE что-то есть с шестой версии», но при этом это не было бы правдой?
–8
kartoshin #
Даже поддерживая стандарты, майкрософт добавляет проблем веб-мастерам. Это же уметь надо.
0
LexL #
Походу это ECMA добавила проблем, «улучшив» стандарт
+1
glazs #
> IE9 в режиме стандартов действительно соответствует спецификации ES5
Я в шоке! Неужели это время наступило? Если IE действительно будет вести себя в соответствии со стандартами, наступит новая эра в веб разработке.
+1
VolCh #
Угу, остальные браузеры тоже будут вынуждены их поддерживать :) Глядишь и доживём когда-нибудь до того времени, что для разработчика будет «просто браузер», поддерживающий одни фичи стандарта и не поддерживающий другие (вроде так задумывается html5 и иже с ним) и не надо будет уточнять, как именно он их поддерживает
0
Inquirer #
На какой год ставите?
+2
tenshi #
> object undefined
мдя… веселье продолжается… не забудьте про object number и object string для примитивов х)
+3
tenshi #
а вообще, проверять тип значения через его строковое представление — это очень сильно х) я понимаю эти костыли для массивов — там без этого никак, но для функций-то чем typeof не угодил?
0
s0rr0w #
Скорее всего разным значением в некоторых браузерах. Другого предположения, почему нужна столь замысловатая конструкция, у меня нет

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.