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

Original author: Allen Wirfs-Brock
  • Translation
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

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 31

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

        О каких производителях и стандартах Вы говорите?
        Да, вспоминаем, что Опера существует с 1995 года, но разве она имела на тот момент хоть какой-либо авторитет?
        Вспоминаем, когда образовался w3c — 1994, и он так же не мог иметь сильного влияния всего-лишь после двух лет сущетсрования.
        Да, был Netscape, но они тоже творили, что хотели.
        А ведь главное сейсас не это, а то, что Майкрософт понял свои ошибки и исправляется.
          +1
          Так тогда ж откровенная война шла.
            +3
            просто на то время производители прочих браузеров ещё ещё пешком под стол ходили, с ними было неинтересно совещаться
        • UFO just landed and posted this here
            0
            А что произойдет, если логика моего приложения строится на таком выражении:
            try {
            o.toString();
            alert('ok');
            } catch(e) {
            alert('Something wrong!');
            }
              0
              Я так понял что как у null и undefined по прежнему нельзя вызывать методы. Изменения коснулись только вызова toString с явным указанием this
                –1
                Мне почему-то показалось, что изменения коснутся Function.prototype.call
                  0
                  хорошо:
                  try{
                  toString.call(a);
                  } catch(e) {
                  alert('looks like a == null');
                  }
                    0
                    Тогда ваш код не работал. Читайте в статье.
                      0
                      Действительно, извиняюсь, выпустил из виду.
                0
                Скажите, а есть ли какая-то официальная информация по поводу поддержки Websockets в IE9?
                Пытался найти – не смог.
                • UFO just landed and posted this here
                    0
                    И не будет?
                    • UFO just landed and posted this here
                        +2
                        прошу прощения, но вы неправильно используете сложный технический термин «красноглазые»
                        • UFO just landed and posted this here
                            –1
                            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
                              Да нормально, фанаты — они везде фанаты. А красные глаза намного проще приобрести в процессе секса с IE6, нежели в процессе компиляци ядра.
                                –4
                                там скорее можно лишиться волос, чисто на «трах-тибидохах».

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

                        Only users with full accounts can post comments. Log in, please.