【问题标题】:Why does <!--<script> cause a DOM tree break on the browser?为什么 <!--<script> 会导致浏览器上的 DOM 树中断?
【发布时间】:2014-01-23 09:55:13
【问题描述】:

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

<!DOCTYPE HTML>
<html>
    <body>
        <script>
            var a = '<!--<script>';
        </script>
        <p>Test</p>
    </body>
</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>

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

【问题讨论】:

    标签: javascript dom html


    【解决方案1】:

    这提出了重要的一点,即 HTML 页面上 &lt;script&gt; 标记内的文本在被 Javascript 解析器解析之前由 HTML 解析器解析。

    此代码不是有效的 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 产生式。它到此结束,因为下一部分是&lt;!--。

    如果脚本后面有任何文本,它必须匹配escape产生式,如下所示:

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

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

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

    现在data2 中不能包含任何内容,因为data2 产生式禁止子字符串&lt;script&gt;(即script-start)!

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

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

    【讨论】:

    • 我认为 HTML5 明确指定了错误处理应该如何工作?
    • @Peter:...这正是我所说的,但更长!希望您的答案不会像我的那样被破坏。 +1
    • @icktoofay 你是正确的,HTML5 准确地描述了解析过程,并且比 HTML 4.01 或 XHTML 更宽容地允许“标签汤”,可以这么说。但是,如果 HTML5 规范中的语法无法解析代码,则由浏览器决定如何处理。
    【解决方案2】:

    内部机制违反了一些假设。

    试图合理化这些东西没有多大意义。

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

    【讨论】:

    • @ruakh:我没有混淆任何东西。计算机系统必须选择如何处理无效输入的原则是普遍和基本的。在浏览器通过向用户显示错误消息来拒绝无效 HTML 之前,他们必须在渲染时做出“最佳猜测”,并且除了规范中的一些建议(我已经检查过——没有这个建议),这意味着这完全取决于浏览器。是UB。但是,如果您选择将我对这个问题的细分阅读为“啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊我当然不能阻止你”
    • @acarlon:当然,您可以制作一个可以做到这一点的浏览器。 但是为什么?它需要循环。这需要时间。它会减慢您的页面速度。全部用于无效输入。使输入合规,一切都解决了。而且,是的,script 标签的内容在4.3.1.2 中控制。
    • @gslin:点击我对 W3C 验证器的回答中的链接,自己找出答案!我没有说这是一个错误。
    • @ruakh: 好吧,今天没解决。不确定你对 C++ 的执着是什么:提到 UB 是因为这是所有指定语言的计算机软件的基本原则。此外,我什至没有在答案中提到它。请不要仅仅因为你不明白我在说什么就断言我“困惑”!
    • @ruakh:当然可以!如果你做了 HTML 规范没有定义的任何事情,那就是——根据定义——UB。这不是 C++ 所固有的。它是具有指定行为但没有无限多页规范的系统所固有的。是的,HTML 有更多关于优雅失败的保护措施和指南;这并不意味着您可以编写 anything 看起来有点像 HTML 并假设它具有明确定义的语义。如果您要求我们完全实际地看待这一点,那么请考虑到没有 C++ 编译器实际上会让恶魔飞出你的鼻子。
    猜你喜欢
    • 2015-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 2014-02-27
    • 2021-01-21
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多