打印

HY9001: Safari 中错误的注释将导致部分 JavaScript 代码无法执行

作者:孙东国

标准参考

关于 SCRIPT 标记的 "src" 属性说明请参考 W3C HTML 4.01 规范: http://www.w3.org/TR/html4/interact/scripts.html#edef-SCRIPT

关于 HTML 注释说明请参考 W3C HTML 4.01 规范: http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4

问题描述

页面中存在外部 Javascript 文件引用时,其它 SCRIPT 标记内脚本程序段使用错误的 HTML 注释将导致此块内所有脚本程序以及此块后 SCRIPT 标记内程序无法运行。

造成的影响

Safari 浏览器中注释标记后的脚本程序无法被运行。

受影响的浏览器

Safari  

问题分析

SCRIPT 标记中的 "src" 属性用来引用外部脚本程序文件。

HTML 注释以成对的 <!-- 和 --> 方式出现,其间的文字不被渲染引擎渲染出来。如果在 SCRIPT 标记内使用 HTML 注释也不会影响脚本程序解析,这样使用是为了向下兼容不支持 SCRIPT 脚本的老旧浏览器,避免他们将脚本内容渲染到页面中。

外部引用的脚本文件和脚本块标记内的未闭合 HTML 注释标记将结合产生出怪异问题,分析以下代码:

<p>=========分割线============<p>

<div></div>
<div></div>
<div></div>
<div></div>
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript"> 【 脚本块 A 】 document.getElementsByTagName("div")[0].innerHTML = "HTML 注释错误之前的 SCRIPT 标记块内脚本程序已运行"; </script> <script type="text/javascript"> 【 脚本块 B 】 document.getElementsByTagName("div")[1].innerHTML = "HTML 注释错误之前脚本程序已运行"; <!-- document.getElementsByTagName("div")[2].innerHTML = "HTML 注释错误之后脚本程序已运行"; </script> <script type="text/javascript"> 【 脚本块 C 】 document.getElementsByTagName("div")[3].innerHTML = "HTML 注释错误之后的 SCRIPT 标记块内脚本程序已运行"; </script> <p>=========分割线============<p>

页面中最初引用了外部脚本文件,然后依次执行了脚本块 A B C,其中脚本块 B 中第二行语句开始存在一个 HTML 注释标记。这个注释标记存在疏漏,他没有按照规范使用 --> 字符将本身闭合。

此实例在各浏览器内运行效果如下:

  IE Firefox Chrome Opera Safari
脚本块 A 正常执行 正常执行
脚本块 B HTML注释语句之前程序 正常执行 未执行
脚本块 B HTML注释语句之后程序 正常执行 未执行
脚本块 C 正常执行 未执行
错误 HTML 注释之后的文档内容 正常显示 未显示

根据上表可看出,其他浏览器对此种情况均正常处理。

仅 Safari 浏览器忽略了存在错误 HTML 注释的脚本块以及其后的脚本块内程序执行,同时位于错误注释后的 HTML 标记以及其内容也被浏览器忽略。

 

根据这个现象,修改代码将错误 HTML 注释标记修正完整:

<script type="text/javascript"> 【 脚本块 B 】
  document.getElementsByTagName("div")[1].innerHTML = "HTML 注释之前脚本程序已运行";
  <!--
  document.getElementsByTagName("div")[2].innerHTML = "HTML 注释内后脚本程序已运行";
 -->
</script>
  IE Firefox Chrome Opera Safari
脚本块 A 正常执行 正常执行
脚本块 B HTML注释语句之前程序 正常执行 正常执行
脚本块 B HTML注释语句内程序 正常执行 正常执行
脚本块 C 正常执行 正常执行
错误 HTML 注释之后的文档内容 正常显示 正常显示

当错误的 HTML 注释标记被修复后,所有浏览器执行效果一致。同理,如果将错误的注释标记去掉后,所有浏览器执行效果也将一致。

 

此种情况下,如果在不尝试修复错误标记的前提下将最初的外部脚本程序引用去除,将会怎样?继续尝试修改代码,观察现象:

<p>=========分割线============<p>

<div></div>
<div></div>
<div></div>
<div></div>

<script type="text/javascript"> 【 脚本块 A 】
  document.getElementsByTagName("div")[0].innerHTML = "HTML 注释错误之前的 SCRIPT 标记块内脚本程序已运行";
</script>

<script type="text/javascript"> 【 脚本块 B 】
  document.getElementsByTagName("div")[1].innerHTML = "HTML 注释错误之前脚本程序已运行";
  <!--
  document.getElementsByTagName("div")[2].innerHTML = "HTML 注释错误之后脚本程序已运行";
</script>

<script type="text/javascript"> 【 脚本块 C 】
  document.getElementsByTagName("div")[3].innerHTML = "HTML 注释错误之后的 SCRIPT 标记块内脚本程序已运行";
</script>

<p>=========分割线============<p>
  IE Firefox Chrome Opera Safari
脚本块 A 正常执行 正常执行
脚本块 B HTML注释语句之前程序 正常执行 正常执行
脚本块 B HTML注释语句之后程序 正常执行 正常执行
脚本块 C 正常执行 正常执行
错误 HTML 注释之后的文档内容 正常显示 正常显示

外部脚本程序引用去除后,即使脚本块中存在错误的HTML注释语句,整体程序执行与内容渲染均正常。

 

那么,如果将拥有错误语句的内联脚本块放置到外部文件中是否还会存在此问题呢?继续修正代码观察现象:

<p>=========分割线============<p>

<script type="text/javascript" src="1.js"></script>

<script type="text/javascript"> 【 脚本块 B 】
  document.getElementsByTagName("div")[0].innerHTML = "HTML 注释错误之前的 SCRIPT 标记块内脚本程序已运行";
</script>

<script type="text/javascript" src="2.js"></script> 【 外部脚本文件B 】
<script type="text/javascript"> 【 脚本块 C 】 document.getElementsByTagName("div")[3].innerHTML = "HTML 注释错误之后的 SCRIPT 标记块内脚本程序已运行"; </script> <p>=========分割线============<p> <!-- 2.js 文件 --> document.getElementsByTagName("div")[1].innerHTML = "外部 JS 文件中 HTML 注释错误之前脚本程序已运行"; <!-- document.getElementsByTagName("div")[2].innerHTML = "外部 JS 文件中 HTML 注释错误之后脚本程序已运行";
  IE Firefox Chrome Opera Safari
脚本块 A 正常执行 正常执行
外部脚本文件 B 中 HTML 注释错误之前脚本程序 正常执行 正常执行
外部脚本文件 B 中 HTML 注释错误之后脚本程序 正常执行 正常执行
脚本块 C 正常执行 正常执行
错误 HTML 注释之后的文档内容 正常显示 正常显示

所有浏览器均运行正常,看来外部脚本文件中存在的错误 HTML 注释并不能触发此问题。

 

综合以上情况,出现此问题的条件如下:

  • 页面中有外部脚本文件引用。
  • 外部脚本文件标记之后存在脚本标记块。
  • 此脚本块中有未封闭的 HTML 注释标签。

解决方案

SCRIPT 标记内如有 HTML 注释标记,请仔细检查,注意他们的闭合情况。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6
Chrome 6.0.472.11 dev
Safari 4.0.5
Opera 10.53
测试页面: internal_script_html_comments_error_bug.html
external_script_html_comments_error.html
本文更新时间: 2010-07-29

关键字

nested comment script html 注释