zoukankan      html  css  js  c++  java
  • 【原创】三招搞死你的IE11,可重现代码下载(IE Crash keyframes iframe)!

    前言

    很多人都知道我们在做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 版本

  • 相关阅读:
    vue Bus事件用法与bug
    移动端超出三行显示第三行显示省略号+查看全部
    Vuex
    vue点击旋转,再点击复原
    vue项目(cli-3)替换浏览器logo
    悬浮广告(二)vue版本
    悬浮广告(一)html版本
    vue下获得经纬度省市区
    一个可以输出当前移动设备机型(安卓,ios)系统版本的html页面
    谱聚类(spectral clustering)原理总结
  • 原文地址:https://www.cnblogs.com/sanshi/p/7262495.html
Copyright © 2011-2022 走看看