为什么<! - <script>会导致浏览器中的DOM树中断? - >

时间:2014-01-06 03:21:30

标签: javascript dom html

当我看到解决http://escape.alf.nu的第15级的答案时,我注意到<!--<script>将导致DOM解析器中断。在以下HTML中,您将看不到字符串“Test”(在IE 11&amp; Firefox&amp; Chrome上测试):

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

DOM tree of the above HTML

但是这两个脚本将显示“Test”:

<!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>

我不明白,为什么会这样?

2 个答案:

答案 0 :(得分:23)

这提出了一个重要的观点,即HTML解析器解析HTML页面上<script>标记内的文本,然后由Javascript解析器解析。

此代码不是有效的HTML5语法,因此HTML5规范中没有任何内容可以为我们提供有关此处的内容的线索。具体而言,有两个问题:

这两个问题都会使浏览器的HTML解析器进入错误解析模式,这意味着他们试图理解无效语法。当尝试理解无效语法时,浏览器将会做什么未定义行为,这在技术上意味着任何事情都可能发生(例如nasal demons)。这里的事实上的行为似乎是浏览器同意他们如何处理这种未定义的行为,但它仍然是未定义的行为。

无论出于何种原因,这种语法问题的组合彼此相邻会导致浏览器忽略文档中的文本。


编辑:我已经确定了如何通过this part of the HTML5 spec逐步产生解析错误。

脚本的文本内容(不包括空格)是

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<!--制作匹配。它结束了,因为下一部分是escape

对于之后在脚本中有任何文本,它必须与escape = "<!--" data2 *( script-start data3 script-end data2 ) 制作相匹配,如下所示:

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

让我们匹配文本的下一部分。到目前为止我们已经

data2

现在data2中无法包含任何内容,因为<script>制作会禁止子字符串script-start(即data2 = < any string that doesn't contain a substring that matches not-data2 > not-data2 = script-start / "-->" )!

{{1}}

词法分析器无法根据语法继续执行有效步骤,因此浏览器现在必须进行错误处理。

答案 1 :(得分:3)

在内部机制中会违反某些假设。

尝试对这些东西进行合理化并没有什么意义。

You wrote invalid HTML,所以任何都可能发生。