前言

很多人都知道我们在做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. <自动化测试方案_6>第六章、API自动化测试

    第六章.API自动化测试 (一)工具实现 目前大众接口测试的工具有:Postman.SoupUI.jmeter他们的特点介绍有人做个宏观的研究,这里进行引用:https://blog.csdn.net ...

  2. Android6.0 源码修改之屏蔽系统短信功能和来电功能

    一.屏蔽系统短信功能 1.屏蔽所有短信 android 4.2 短信发送流程分析可参考这篇 戳这 源码位置 vendor\mediatek\proprietary\packages\apps\Mms\ ...

  3. (网页)websocket例子

    转载自博客园张果package action; import javax.websocket.CloseReason; import javax.websocket.OnClose; import j ...

  4. 餐饮ERP相关问题FAQ

    1.订单无法自动上传,手动上传也是失败. 检查网络是否有问题,网络如果正常,打开本地连接-属性-internet协议版本4-首选DNS服务器设置为(114.114.114.114) 然后再打开IE浏览 ...

  5. 【Linux高频命令专题(24)】grep

    简述 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来.grep全称是Global Regular Expression Print,表示全局正则 ...

  6. windows下安装consul

    Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件, 由 HashiCorp 公司用 Go 语言开发, 基于 Mozilla Public License 2.0 的协议进行 ...

  7. February 21st, 2018 Week 8th Wednesday

    Our life is what our thoughts make it. 我们的思想成就了我们的生活. The mind is everything. What you think, you be ...

  8. Vue使用枚举类型实现HTML下拉框

    下拉框包含option中的Value和用来显示的选项, 一般后台都是使用的Value值,而不是显示在前台的选项 第一步: 编写下拉框需要的枚举类型 StatusEnum.java public enu ...

  9. 早期nginx tcp代理(基于patch实现)

    nginx tcp代理功能由nginx_tcp_proxy_module模块提供,同时监测后端主机状态.该模块包括的模块有: ngx_tcp_module, ngx_tcp_core_module, ...

  10. (转)Spring Boot(五):Spring Boot Jpa 的使用

    http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html 在上篇文章Spring Boot(二):Web 综合开发中简单介 ...