从IE的一个奇怪的现象所联想到的(上)
2009-11-26 20:08 Nana's Lich 阅读(3356) 评论(10) 编辑 收藏 举报消歧义声明:因为上下文关系的缘故,JScript特指微软的JScript引擎以及其语言特点,但大部分时候可以在功能上视为JavaScript的等价物;JavaScript指一般意义的JavaScript。
大概有一年左右了吧,开着IE8浏览一些网站以后,我就会碰到IE8的界面失灵的现象,刚开始我还以为是32位的IE和64位的Windows有兼容问题。
上个月我装了32位的Windows 7,没过几天又发现了这个问题,所以我就把这种现象报告给了微软的技术支持。
微软的技术支持回信:在他们的测试中IE8不存在这种问题,根据他们以往研究经验,这种问题可能是由第三方加载项和组件造成的。
这一下倒是提醒了我,我总是装完操作系统以后马上就安装各种常用工具,可能是某个常用工具出现了问题。
仔细排查之后,我把目标锁定在了这两样东西上:NetTransport BHO和Flash Player。
NetTransport也就是国产的网络传送带,算是国产下载工具里面最干净的了,而我以前私下分析过它的原理,觉得它没什么可能产生这样的问题。
相比之下,Flash Player就显得很有嫌疑了,Flash Player本来就给我留下过不好的印象——怎么回事,马上就说。
之后的几天我就很少去那些在页面上放置一大堆Flash内容(尤其是Flash封装组件)的网站——说来也奇怪,到现在已经5天了,再没有出现过这样的问题。
不过这也不能说问题就是出在Flash Player身上,万一那些网站上正好有Flash以外的真正的罪魁祸首呢?
但是这次经历却再次提醒了我,的确应该小心对待Flash Player(ActiveX)。
2007年下半年,我为朋友做一个小小的Web程序,当时我用了ASP.NET和Flash……但在刚开始测试就发现有个严重问题,那就是:在ASP.NET WebForm上放置的Flash封装组件,无法调用!
只有在IE上才会这样,现在大家可能都知道怎么解决了,但当时我不知道,所以我就看弹出来的脚本调试器怎么说——
结论是,问题出在Flash Player对外部方法的实现上。
和它在Firefox中对XPCOM的实现不一样,Flash Player的ActiveX实现(用于Windows应用程序,包括IE)并没有好好利用ActiveX/OLE/Automation的技术基础——IDispatch接口,而是只暴露了CallFunction方法,再在盛装它的容器上运行一段JScript脚本。
这段JScript脚本需要把Flash Player控件自身当作参数,然而Flash Player用来寻找自身的办法就很有问题了——当时它使用了这样几个片段:
在运行时Flash Player会在这三个片段之间填入自身的id,也就是变成下边这样:
Flash Player(ActiveX)这样设计,是建立在“在IE中使用id和name可以直接访问一个节点”的前提之下的,但Macromedia或者Adobe的人其实是考虑不周——IE的这个特点不仅不是标准功能,连微软的技术文档都没保证过在任何情况下都可以这么用。
实际上,上面这个脚本错误的产生原因就是:在form内的节点是不属于全局作用域的——也就是说,在这个时候IdOfFlashPlayer、window.idOfFlashPlayer,都无效。
不光这样,就算可以直接用id找到form内的节点,万一id中有不能用作JScript标识符的字符,这种做法也是要出错的,比方说:
instance[name] = function () {
return eval(instance.CallFunction("<invoke name=\""+name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>"));
}
}