前言

很多人都知道我们在做FineUI控件库,而且我们也做了超过 9 年的时间,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅:

这类BUG之所以被大家所深恶痛绝,在于其隐蔽性,很多时候不能用常规的逻辑去分析。另一个原因的开发人员一般都很善良,出现问题总是从自身找原因,很少会怀疑到IDE,浏览器这些开发工具上面来。

事实情况是,浏览器也是开发人员开发的,是个软件就有BUG!

今天公开的这个IE11的Crash BUG也郁闷了我好长时间,今天终于被我逮到了,哈哈哈哈......

发现问题

FineUI(专业版)其实在2016年3月就已经对桌面,平板和手机浏览器进行了适配,并且为手机浏览器增加了动画效果(iOS下的Webkit和Andriod下的Chrome),但是这个CSS3动画仅限于 WebKit 浏览器,并不支持Firefox,Edge,IE11等浏览器。

最近在版本更新中,我想把CSS3动画效果扩展到桌面版的Firefox,Edge和IE11等浏览器,在开发过程中,突然有一天,我发现IE11只要打开调试工具(F12),浏览器就崩溃了,屡试不爽:

IE11下打开页面没问题,但是只要F12打开调试工具,浏览器立马Crash,点击调试按钮,出现的错误信息:

Unhandled exception at 0x754ED8D3 (KernelBase.dll) in iexplore.exe: 0xC0000005: Access violation writing location 0x08090FFC.

貌似是内存写入错误,对于纯前端开发人员来说,遇到这样的问题是一脸无奈:

分析问题

幸运的是,上个版本的FineUI(专业版)没有类似的问题,由于此时已经更新了很多代码,所以下面就进入漫长的代码比对阶段。。。。

。。。。。

。。。。。

。。。。。

经过近一天的分析,问题集中在 CSS3 的 keyframes 关键字和 IFrame 一起使用时出现,我写了两个测试页面:

test1.aspx:

<!DOCTYPE html>

<html>
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<f:PageManager ID="PageManager1" runat="server" /> <iframe src="./test2.aspx"></iframe>
</form>
</body>
</html>

test2.aspx

<!DOCTYPE html>

<html>
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<f:PageManager ID="PageManager1" runat="server" /> <f:Button Text="按钮" runat="server" />
</form>
</body>
</html>

test2.aspx 生成的 HTML 代码如下:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link type="text/css" rel="stylesheet" href="/res.axd?css=f.css&t=636364679643916663"/>
<link type="text/css" rel="stylesheet" href="/res.axd?css=themes.default.theme.css&t=636264594331716901"/> <title> </title></head>
<body>
<form name="form1" method="post" action="test2.aspx" id="form1"> 。。。。。
<div id="ctl02_wrapper" class="f-inline-block"></div> <script type="text/javascript" src="/res.axd?js=f.js&t=636364680829342350"></script>
<script type="text/javascript" src="/res.axd?js=lang.zh_CN.js&t=636364679651261140"></script> <script type="text/javascript">
//<![CDATA[
F.load(function () {
F.f_init({
theme: 'default',
baseUrl : '/',
displayMode: 'normal',
_version: '3.7.0',
_customId: '0oOOoo'
});
F.f_pagemanager = new F.Component({
f_state: {},
id: 'PageManager1',
name: 'PageManager1',
hidden: true
});
var f1 = new F.Button({
f_state: {},
id: 'ctl02',
name: 'ctl02',
renderTo: '#ctl02_wrapper',
text: '按钮',
handler: function () {
F.f_disable('ctl02');
__doPostBack('ctl02', '');
}
});
});//]]>
</script>
</form>
</body>
</html>

为了方便调试,我们把 test2.aspx 中引用的 CSS 文件下载下来,并更新 test2.aspx 为:

<!DOCTYPE html>
<html>
<head>
<title></title>
<link type="text/css" rel="stylesheet" href="/res.axd?css=f.css&t=636364679643916663"/> </head>
<body> </body>
</html>

此时问题依旧,F12浏览器照样Crash。遵循怀疑一切的原则,我们把 res.axd 加载的资源文件下载到本地 f.css,并把上面的 test2.aspx 改为:

<!DOCTYPE html>
<html>
<head>
<title></title>
<link type="text/css" rel="stylesheet" href="f.css"/> </head>
<body> </body>
</html>

此时问题消失!!所以我们不得不怀疑 res.axd?css=f.css 和 f.css 的响应头不一样,因为两者的内容完全相同。

事后看来这一怀疑是错误的,事后诸葛每个人都会做,但真正遇到类似的无厘头BUG时,还是怀疑一切的好,我们甚至比较两者的响应头,唯一的不同是:

res.axd?css=f.css:

Content-Type:text/css; charset=utf-8

f.css:

Content-Type:text/css

然后,我们尝试修改的 res.axd?css=f.css,使其和 f.css 的完全一样,还是不行,浏览器照样崩溃。

郁闷中....

此路不通

既然 res.axd?css=f.css 和 f.css  的响应头完全相同,内容完全相同,但是效果却截然不同,一个导致IE11崩溃,而另一个不会!

好吧,我们只好怀疑两者的URL不同了,再来仔细对比下:

<link type="text/css" rel="stylesheet" href="/res.axd?css=f.css&t=636364679643916663"/>   (IE11打开调试工具时崩溃)

<link type="text/css" rel="stylesheet" href="f.css"/>   (IE11打开调试工具时不崩溃)

难道是。。。难道是。。。难道是。。。难道是。。。难道是。。。

一个最不可能的念头在我脑海里出现,难道是第一个URL太长了???

不要搞笑,这怎么可能呢,Windows文件的路径好像有长度限制,但,但,但,但,这个URL真的不长啊。。。。

不可能。。。算了。。。不是这个地方的问题。。。。

。。。。。

。。。。。

。。。。。

不行,还是把自己当个傻子,我就把URL改短一点,看是否有问题,我很坎坷的删除了最后一个数字 3,把:

/res.axd?css=f.css&t=636364679643916663

改为:

/res.axd?css=f.css&t=63636467964391666

问题消失!!!!!

我都要惊呼了,难道真是URL太长了,还就多个一个字符!!!

一阵兴奋之后,是一阵郁闷,因为我把URL加长了,同样问题消失:

/res.axd?css=f.css&t=636364679643916663897978783784328467326473624763274632764732

再次思考

好吧,我是有点语无伦次,在经历多次怀疑,否定,再怀疑,再否定之后,我们终于能够重现问题了,其实很简单:

IFrame中的这个CSS文件和父页面中的CSS文件URL相同导致的(而不是URL长度的问题)!

至此,我们可以简单的重现如下(下载可重现压缩包,IE11打开后,F12直接崩溃):

test1.html

<!DOCTYPE html>
<html>
<head>
<title></title>
<link type="text/css" rel="stylesheet" href="fineui.css" /> </head>
<body>
<iframe src="./test2.html"></iframe>
</body>
</html>

test2.html:

<!DOCTYPE html>
<html>
<head>
<title></title>
<link type="text/css" rel="stylesheet" href="fineui.css" /> </head>
<body> </body>
</html>

fineui.css:

@keyframes slideLeftIn {
0% { opacity: 0; }
100% { opacity: 1; }
}

在IE11中打开 test1.html,F12打开调试窗口,浏览器立马崩溃!!!

说好的《三招搞死你的IE11》

后来发现,这个问题不用 iframe 也能重现,只要满足两个条件,立马崩溃:

  1. 页面加载同一个CSS文件两次
  2. CSS文件中包含 @keyframes 的定义

下面给出一个最简单的测试例子(下载可重现压缩包,IE11打开后,F12直接崩溃):

第一步:新建一个 test3.html 文件:

<!DOCTYPE html>
<html>
<head>
<title></title>
<link type="text/css" rel="stylesheet" href="fineui.css" />
<link type="text/css" rel="stylesheet" href="fineui.css" /> </head>
<body> </body>
</html>

第二步:相同目录新建一个 fineui.css 文件:

@keyframes slideLeftIn {
0% { opacity: 0; }
100% { opacity: 1; }
}

第三步:在IE11中打开上述页面,F12调出调试窗口,IE立马崩溃!不服来辩

解决问题

暂无!

没办法,IE11自身的BUG,除非你不用IE11,或者绕行。

绕行有几个简单的办法:

  1. CSS文件中不要包含 @keyframes 关键字(这个不可能,特别是希望IE11下支持CSS3动画效果的)
  2. 不要在页面中引用同一个CSS文件两次(正确情况下没人会引用两次,而IFrame中就不可避免了!)
  3. 主页面和IFrame中引用同一个CSS文件,给CSS文件加个随机后缀(影响浏览器缓存,正式环境不建议用)

好吧,如果你真正需要 @keyframes 和 iframe 两个元素时,还真没办法避免这个问题。

反馈

由于 Windows 操作系统和IE的版本众多,我这边使用的版本:

1. Windows 10 家庭版

2. IE11版本如下:

如果你用我们提供的《三步搞死你的IE11,浏览器打开后,F12直接崩溃》附件,能够本机重现,请评论提供如下信息:

1. Windows 版本

2. IE11 版本

【原创】三招搞死你的IE11,可重现代码下载(IE Crash keyframes iframe)!的更多相关文章

  1. 【原创】IE11惊现无厘头Crash BUG(三招搞死你的IE11,并提供可重现代码)!

    前言 很多人都知道我们在做FineUI控件库,而且我们也做了超过 9 年的时间,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅: 分享IE7一个神奇的BUG(不是封闭 ...

  2. 三招搞挂Mysql(转)

    一.产生大量的undo日志 众所周知,InnoDB是一个支持MVCC的存储引擎,为了支持MVCC,InnoDB需要保存undo日志,以便对用户提供记录的历史版本.如果我们开启一个事务,反复地更新一条记 ...

  3. .NET Core单元测试之搞死开发的覆盖率统计(coverlet + ReportGenerator )

    .NET Core单元测试之搞死开发的覆盖率统计 这两天在给项目补单元测试,dalao们要求要看一下测试覆盖率 翻了一波官方test命令覆盖率倒是有支持了,然而某个更新日志里面写着 ["Su ...

  4. 14招搞定JavaScript调试

    14招搞定JavaScript调试 译者按: 很多时候,大家可能只是依靠console.log来调试JavaScript代码,这样做的局限性不言而喻,这篇博客将教你几招实用的调试技巧. 原文: The ...

  5. 从20s优化到500ms,我用了这三招

    前言 接口性能问题,对于从事后端开发的同学来说,是一个绕不开的话题.想要优化一个接口的性能,需要从多个方面着手. 其实,我之前也写过一篇接口性能优化相关的文章<聊聊接口性能优化的11个小技巧&g ...

  6. 不要让catalogs搞死你的eclipse

    不要让catalogs搞死你的eclipse 楼主终于走出校园,踏上软件职场之路.新人要学的东西有很多,要战胜的东西很多,这些东西除了技术本身,还有对未知领域的恐惧,新接触技术,比如新的框架,可能好几 ...

  7. 云计算之路-阿里云上:消灭“黑色n秒”第三招——禁用网卡的TCP/IP Offload

    程咬金有三板斧,我们有三招.在这篇博文中我们要出第三招,同时也意味着昨天在“希望的田野”上的第二招失败了. 前两招打头(CPU)不凑效,这一招要换一个部位,但依然要坚持攻击敌人最弱(最忙最累)部位的原 ...

  8. iOS开发三步搞定百度推送

    iOS开发三步搞定百度推送   百度推送很简单,准备工作:在百度云推送平台注册应用,上传证书. 步骤一: 百度云推送平台 http://push.baidu.com/sdk/push_client_s ...

  9. windows+mysql集群搭建-三分钟搞定集群

    注:本文来源:  陈晓婵   <  windows+mysql集群搭建-三分钟搞定集群   > 一:mysql集群搭建教程-基础篇 计算机一级考试系统要用集群,目标是把集群搭建起来,保证一 ...

随机推荐

  1. 使用fiddler抓包手机请求数据

    1.启动Fiddler,打开菜单栏中的 Tools > Fiddler Options,打开“Fiddler Options”对话框. 2.在Fiddler Options”对话框切换到“Con ...

  2. (后端)mybatis中使用Java8的日期LocalDate、LocalDateTime

    原文地址:https://blog.csdn.net/weixin_38553453/article/details/75050632 MyBatis的型处理器是属性“createdtime参数映射为 ...

  3. Node.js学习记录(一)--安装设置篇

    安装Node window window上安装node可选择以下两种方式: 方式一:直接进入官网下载安装 进入node.js官网点击windows,选择.msi后缀的,根据自己的电脑选择对应的64位或 ...

  4. x3D 下载以及如何使用原版NetBeans IDE 来搭建x3d编辑环境

    安装前: Overview X3D-Edit version 3.3 standalone application and Netbeans plugin are available and read ...

  5. sqlserver——cube:多维数据集

    1.cube:生成多维数据集,包含各维度可能组合的交叉表格,使用with 关键字连接 with cube 根据需要使用union all 拼接 判断 某一列的null值来自源数据还是 cube 使用G ...

  6. raid1 raid2 raid5 raid6 raid10的优缺点和做各自raid需要几块硬盘

    Raid 0:一块硬盘或者以上就可做raid0优势:数据读取写入最快,最大优势提高硬盘容量,比如3快80G的硬盘做raid0 可用总容量为240G.速度是一样.缺点:无冗余能力,一块硬盘损坏,数据全无 ...

  7. Linux进程调度器概述--Linux进程的管理与调度(十五)

    调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个不同的部分, 其中一个涉及调度策略, 另外一个涉及上下文切换. 1 背景知识 1.1 什么是调度器 ...

  8. [Hive_9] Hive 的排序

    0. 说明 全排序(order by) | 部分排序(sort by) | hash 分区(distribute by)  | cluster by 1. 前期准备 1.1 建表 create tab ...

  9. css点滴1—八种方式实现元素垂直居中

    这里介绍实现元素垂直居中的方式,文章是参考了<css制作水平垂直居中对齐>这一篇文章. 1.行高和高度实现 这种方式实现单行垂直居中是很简单的,但是要保证元素内容是单行的,并且其高度是不变 ...

  10. ABAP 7.40, SP08 中的 Open SQL 新特性

    1,使用 data_source~*指定列 在7.40, SP08中,可以在SELECT语句中使用data_source~*来指定选取不同的数据库表.视图的全部列来作为结果集.它也可以和单独指定的列c ...