Как браузеры точно анализируют тег скрипта?

17

Я просто столкнулся с патологическим случаем с разбором HTML. Я всегда думал, что тег <script> будет работать до первого закрывающего тега </script> . Но, оказывается, это не всегда случай .

Это действительно:

<script><!--
alert('<script></script>');
--></script>

И даже это действительно:

<script><!--
alert('<script></script>');
</script>

Но это не так:

<script><!--
alert('</script>');
--></script>

И это не так:

<script>
alert('<script></script>');
</script>

Такое поведение согласуется с Firefox и Chrome. Таким образом, как трудно полагать, браузеры, похоже, принимают тег open + close script внутри комментария html внутри тега скрипта. Итак, вопрос заключается в том, как браузер действительно анализирует теги сценариев? Это имеет значение, потому что библиотека разбора HTML, которую я использую, Nokogiri, принимала очевидное (но неправильное) правило до первого закрытия и не обрабатывала этот край. Я полагаю, что большинство других библиотек тоже не справятся.

    
задан Daniel 29.01.2013 в 02:59
источник
  • Поместите свои скрипты в отдельный файл. –  Kevin Boucher 29.01.2013 в 03:04
  • Вопрос связан с анализом html, другими словами, я имею дело с чужими веб-страницами. –  Daniel 29.01.2013 в 03:06
  • Крайние случаи разбора HTML ... Я собираюсь плакать, чтобы спать сейчас, удачи: D –  jbabey 29.01.2013 в 03:07
  • @ Даниэль Да, и я хотел бы взять фактический код JavaScript из разбора HTML, поместив его в указанный файл JS. –  Kevin Boucher 29.01.2013 в 03:07
  • Это описательное описание состояния машины, которую должны использовать браузеры: whatwg.org/specs/web-apps/current-work/multipage/.... TBH, я не уверен, поддерживает ли он то, что вы видите или нет. –  Tim Medora 29.01.2013 в 03:46
Показать остальные комментарии

4 ответа

6

После просмотра ссылок , предоставленных Tim и Jukka Я пришел к следующий ответ:

  • после открытия тэга <script> , синтаксический анализатор переходит в состояние data1
  • Если <!-- встречается в состоянии data1 , переключитесь на data2 состояние
  • Если --> встречается в любом состоянии, переключитесь на data1 состояние
  • , если <script[\s/>] встречается в состоянии data2 , переключается на data3 состояние
  • Если </script[\s/>] встречается в состоянии data3 , переключитесь на data2 состояние
  • Если </script[\s/>] встречается в любом другом состоянии, прекратите синтаксический анализ
ответ дан Daniel 30.01.2013 в 17:01
  • Другими словами, если вы встраиваете JSON, все, что вам нужно, после его подстановки заменяет все <на \ 074, и вы в безопасности? Так как это может появляться только в строках, и они будут читать эту escape-строку как <снова? –  w00t 24.11.2016 в 12:03
  • Err, JSON не нравится восьмеричный, он должен быть unicode, поэтому \ u003c –  w00t 24.11.2016 в 12:16
5

Все примеры недопустимы в соответствии со спецификацией HTML 4.01: содержимое script объявляется как CDATA , а описание CDATA говорит:

  

"Хотя элементы STYLE и SCRIPT используют CDATA для своей модели данных, для этих элементов CDATA должен обрабатываться по-разному с помощью пользовательских агентов. Разметка и объекты должны рассматриваться как необработанные и передаваться в приложение как есть. Первое вхождение символьной последовательности « </ » (разделитель открытого конца тега) рассматривается как завершение конца содержимого элемента. В действительных документах это будет конечным тегом для элемента. "

Как вы заметили, браузеры могут не применять это правило, но вместо этого распознавать пары стартовых и конечных тегов в некоторых ситуациях. С точки зрения спецификации это обработка недопустимых документов, то есть обработка ошибок. Неясно, что именно они здесь делают и почему. Кажется, что это зависит от наличия <!-- , что не должно влиять на разбор HTML 4.01 (это not средство комментариев в CDATA content).

В XHTML применяются разные правила, поскольку в XHTML <!-- открывает комментарий в содержимом элемента script .

В целом, все примеры недействительны HTML 4.01 и неверный XHTML из-за отсутствия атрибута type в script . Атрибут не требуется (браузеры по умолчанию обрабатывают контент как JavaScript), но это требуется для этих спецификаций.

В HTML5 применяются другие правила. Они довольно сложны, и они должны описывать поведение браузера. В дополнение к ограничениям ограничений на контент ( запрещая, например, <!-- без соответствия --> ), HTML5 также определяет правила синтаксического анализа .     

ответ дан Jukka K. Korpela 29.01.2013 в 07:42
1

Содержимое тегов по-прежнему является HTML, если вы не отметили его как не HTML. В HTML <word> считается тегом, < необходимо записать как &lt; , чтобы избежать такого поведения. Кроме того, вы хотите сделать содержимое <script> текстовым узлом; используйте эту формулу:

<script type="text/javascript">
//<![CDATA[
  // your code, with < and & and "", woohoo!
//]]>
</script>

<![CDATA[ ... ]]> определяет часть документа как чистый текст без разметки. Слэш там, поэтому JavaScript не запутался; первый набор косой черты находится вне CDATA, но они безопасны для HTML, поэтому проблем нет.

EDIT: Просто понял, что речь идет о разборе, а не написании HTML. К сожалению.

    
ответ дан Amadan 29.01.2013 в 03:16
  • Вы были бы правы в XHTML и, возможно, даже в HTML 4, но HTML 5 специально обрабатывает теги скриптов. –  icktoofay 29.01.2013 в 07:46
1

Гипотетически, если теги сначала разбираются и комментарии анализируются позже, анализатор HTML даст вам эти результаты.

(я не имею в виду, что это обязательно так, просто возможное объяснение.)

1-й случай

<script><!--
alert('<script></script>');
--></script>

Внутри <script></script> есть набор <script></script> . Парсер может сначала игнорировать имя тегов и просто проверяет правильность открытия и закрытия этих тегов. Затем он анализирует комментарии.

<script><!--
--></script>

Итак, это действительно.

Второй случай

<script><!--
alert('<script></script>');
</script>

Внутри <script></script> есть набор <script></script> . Затем он анализирует комментарии.

<script><!--

Комментарий распространяется до конца документа. Это не является строго правильным, но браузер правильно его обрабатывает.

Третий случай

<script><!--
alert('</script>');
--></script>

В наборе <script></script> имеется один закрытый тег. Это недействительно перед тем, как выполнить анализ </script> в качестве комментариев.

4-й случай

<script>
alert('<script></script>');
</script>

Внутри <script></script> есть набор <script></script> , и комментариев нет. Первый проход действителен, но затем он действительно просматривает теги, чтобы узнать, что они собой представляют. Он может не принимать пару тэгов <script> внутри другого, что делает его недействительным.

    
ответ дан Antony 29.01.2013 в 03:32
  • Я думаю, что в 4-м случае тег скрипта закрывается преждевременно, и все после первого </script> переходит к узлу-брату, в то время как второй, «непревзойденный» </script> игнорируется. –  bfavaretto 29.01.2013 в 03:58
  • И третий случай дает SyntaxError в Chrome (возможно, первый </script> тоже закрывает скрипт, не уверен здесь). –  bfavaretto 29.01.2013 в 04:00