Почему <! - <script> вызывает разрыв дерева DOM в браузере?

Когда я вижу ответ, чтобы решить уровень 15 http://escape.alf.nu, я заметил, что <!--<script> приведет к разрыву анализатора DOM, В следующем HTML вы не увидите строку "Тест" (протестированную в IE 11 и Firefox и Chrome):

<!DOCTYPE HTML>
<html>
    <body>
        <script>
            var a = '<!--<script>';
        </script>
        <p>Test</p>
    </body>
</html>

DOM tree of the above HTML

Но эти два сценария будут показывать "Тест":

<!DOCTYPE HTML>
<html>
    <body>
        <script>
            var a = '<!--';
        </script>
        <p>Test</p>
    </body>
</html>

и

<!DOCTYPE HTML>
<html>
    <body>
        <script>
            var a = '<script>';
        </script>
        <p>Test</p>
    </body>
</html>

Я не понимаю, почему это происходит?

Ответ 1

Это поднимает важный момент, когда текст внутри тегов <script> на HTML-странице анализируется парсером HTML до его анализа парсером Javascript.

Этот код недействителен синтаксисом HTML5, поэтому в спецификации HTML5 нет ничего, что могло бы дать нам представление о том, что здесь происходит. Чтобы быть конкретным, есть две проблемы:

Обе эти проблемы помещают браузер HTML-браузера в режим разбора ошибок, а это значит, что они пытаются понять недопустимый синтаксис. То, что браузеры будут делать, пытаясь понять недопустимый синтаксис, - это поведение undefined, что технически означает, что что-то может случиться (например, носовые демоны), По сути дела, де-факто поведение браузеров согласуется с тем, как они справляются с этим поведением undefined, но тем не менее оно undefined.

По какой-то причине эта комбинация проблем синтаксиса рядом друг с другом заставляет браузеры игнорировать текст позже в документе.


EDIT: Я определил, как возникает ошибка синтаксического анализа, перейдя через эту часть спецификации HTML5.

Текстовое содержимое script (исключая пробелы)

var a = '<!--<script>';

Это должно соответствовать следующему правилу грамматики:

data1 *( escape [ script-start data3 ] "-->" data1 ) [ escape ]

Мы можем начать синтаксический анализ текстового содержимого, сопоставляя data1, который имеет следующее правило:

data1         = < any string that doesn't contain a substring that matches not-data1 >
not-data1     = "<!--"    

То есть строка var a = ' совпадает с производством data1. Он заканчивается там, потому что следующая часть <!--.

Для последующего текста в script он должен соответствовать произведению escape, которое выглядит следующим образом:

escape        = "<!--" data2 *( script-start data3 script-end data2 )

Соответствует следующей части текста. До сих пор мы

data1    var a = '
escape   <!--
  data2  ???

Теперь ничто не может содержаться в data2, потому что data2 production запрещает подстроку <script> (т.е. a script-start)!

data2         = < any string that doesn't contain a substring that matches not-data2 >
not-data2     = script-start / "-->"  

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

Ответ 2

Во внутреннем механизме будет нарушено некоторое допущение.

Нет смысла пытаться рационализировать этот материал.

Вы написали неверный HTML, поэтому все может случиться.