论坛首页 Web前端技术论坛

EXT的destroy方法是不是存在漏洞?

浏览 10814 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-03-18  
EXT的destroy方法是不是存在漏洞?销毁的不彻底?

利用
http://fins.iteye.com/blog/172891
提到的工具,在IE下对EXT进行测试

只是一个简单的页面,页面内只是简单的定义一个简单的window ,如下
	var win=new Ext.Window({title:"my window",
			width:400,
			draggable : false,
			shadow : false,
			resizable : false,
			shim :false,
			autoDestroy : true,
			height:300});

关闭这个window时 产生很多ie无法自动回收的孤立结点
每次创建 关闭 创建 关闭  ....
孤立结点都会越来越多

也许这是IE的错 但是EXT不应该忽视IE的 毕竟IE的占有率在那里放着呢

还请大家帮忙分析分析

我看了一下 window/panel的destroy方法似乎确实存在着一些缺陷啊

我重写了 window的destroy方法,效果提升一些,一些顽固结点可以删除了
但是还剩下一下更加顽固的结点无法删除
Ext.Window.prototype.beforeDestroy = function(){

       Ext.Window.superclass.beforeDestroy.call(this);

        Ext.destroy(

			this.header,
            this.tbar,
            this.bbar,
            this.footer,
            this.body,
			this.bwrap,
			this.focusEl,
			this.toolTarget,

			this.resizer,
            this.dd,
            this.proxy,
            this.mask
        );

			this.header=null;
            this.tbar=null;
            this.bbar=null;
            this.footer=null;
            this.body=null;
			this.bwrap=null;
			this.focusEl=null;
			this.toolTarget=null;

			this.resizer=null;
            this.dd=null;
            this.proxy=null;
            this.mask=null;


    }


这个问题如果不弄明白, 在一个复杂的ext页面内,随着操作的增加 内存消耗也将越来越大.
deskto那个例子里的 窗口 大家打开关闭打开关闭 几个来回之后内存占用就会达到6 7十M了.


我怀疑 ext的各个组件的destroy方法内部的实现考虑的不够全面, 销毁内容 和销毁顺序 不当造成部分元素无法销毁.
希望大家能够一起讨论分析一下ext的问题到底处在哪里


   发表时间:2008-03-18  
jack要让我疯狂了!!!!
为了找出问题所在 我一行行的分析 2.02版本代码的 太辛苦了
看到一个地方彻底崩溃了
Template.js   204行
return returnEl ? Ext.get(newNode, true) : newNode;
注意  Ext.get(newNode, true)


再来看 Ext.get 方法的代码

Element.js 2880行

El.get = function(el){
    var ex, elm, id;
    if(!el){ return null; }
    if(typeof el == "string"){ // element id
        if(!(elm = document.getElementById(el))){
            return null;
        }
        if(ex = El.cache[el]){
            ex.dom = elm;
        }else{
            ex = El.cache[el] = new El(elm);
        }
        return ex;
    }else if(el.tagName){ // dom element
        if(!(id = el.id)){
            id = Ext.id(el);
        }
        if(ex = El.cache[id]){
            ex.dom = el;
        }else{
            ex = El.cache[id] = new El(el);
        }
        return ex;
    }else if(el instanceof El){
        if(el != docEl){
            el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
                                                          // catch case where it hasn't been appended
            El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
        }
        return el;
    }else if(el.isComposite){
        return el;
    }else if(Ext.isArray(el)){
        return El.select(el);
    }else if(el == document){
        // create a bogus element object representing the document object
        if(!docEl){
            var f = function(){};
            f.prototype = El.prototype;
            docEl = new f();
            docEl.dom = document;
        }
        return docEl;
    }
    return null;
};

// 省去一些.....

Ext.get = El.get;


我是绞尽脑汁也没弄明白那个true是做什么的

我怀疑这个地方jack弄错了
他本意可能是要给 get弄一个是否从cache里取对象的参数吧
但是没有写.



0 请登录后投票
   发表时间:2008-03-18  
ext1.1 里启用垃圾回收后,等30秒才从Element的cache里清除。
刷新页面后内存还占用?
0 请登录后投票
   发表时间:2008-03-18  
问题的根本原因找到了

一会儿单独发帖讨论
0 请登录后投票
   发表时间:2008-03-18  
下面这段代码也有问题
看来 ext的 Ext.destroy 果然不够强大
问题还是出在事件管理方面
疑惑中


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" />
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-all.js"></script>
<script type="text/javascript">


function alertMsg(){
		alert('click div c');
}

function addEventDiv(){
	if (!Ext.get("div1") ){
		return;
	}
	// 使用下面这种方式注册事件 , 那么ext无法正确的移除  
	Ext.get("div1").on("click",alertMsg);


}


Ext.onReady(function(){

	Ext.get("btn1").on("click",addEventDiv);
	Ext.get("btn2").on("click",function(){ Ext.destroy(Ext.get("div1")); });

	
});



</script>
</head>
<body >
<input id="btn1" type="button"  value=" 为 div1 添加事件 " />
<input id="btn2" type="button"  value=" 移除 div1 " />

<div id="div1">I'm div 1</div>
</body>
</html>
0 请登录后投票
   发表时间:2008-03-18  
前几天也研究过这里的代码,看不出漏洞在那,lisenter的移除,节点的移除都是正确的。。。
0 请登录后投票
   发表时间:2008-03-18  
en  代码上确实没找到什么问题
但是实际情况就是无法移除
而如果用下面的方法给上面代码中的 div注册事件 那么就可以移除:

Ext.get("div1").on("click",function(){ alertMsg() }); 
0 请登录后投票
   发表时间:2008-03-18  

但其实ext已经用传入的function包装了一个新的function,然后才绑定到节点去。
0 请登录后投票
   发表时间:2008-03-18  
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <link rel="stylesheet" type="text/css" href="/script/yuiExt/resources/css/ext-all.css" />
  <script type="text/javascript" src="/script/yuiExt/adapter/ext/ext-base.js"></script>
  <script type="text/javascript" src="/script/yuiExt/ext-all.js"></script>
  <script type="text/javascript">


  function alertMsg(){
          alert('click div c');
  }

  function addEventDiv(){
      if (!Ext.get("div1") ){
          return;
      }
      // 使用下面这种方式注册事件 , 那么ext无法正确的移除
      Ext.get("div1").on("click",alertMsg);


  }


  Ext.onReady(function(){

      Ext.get("btn1").on("click",addEventDiv);
      Ext.get("btn2").on("click",function(){
		  Ext.destroy(Ext.get("div1"));
		  alert(alertMsg._handlers.length);
		  alert(alertMsg._handlers[0][0]);
		  alert(alertMsg._handlers[0][1]);
		  alert(alertMsg._handlers[0][2]);
	  });



  });



  </script>
  </head>
  <body >
  <input id="btn1" type="button"  value=" 为 div1 添加事件 " />
  <input id="btn2" type="button"  value=" 移除 div1 " />

  <div id="div1">I'm div 1</div>
  </body>
 </html>  


发现问题在于ext的 wrap function,就是listener是global的话就会有问题。
见 EventManager.js的140行:
        fn._handlers = fn._handlers || [];

        fn._handlers.push([Ext.id(el), ename, h]);

这里给传入的listener加了_handlers属性,stopLisener负责清除,那么就能正确的处理。
但是destroy直接调用了E.purgeElement...,这个方法好像没办法看到原来的listen,所以,没办法正确的清除_handlers,而_handlers引用了element
1 请登录后投票
   发表时间:2008-03-18  
nihongye 的分析是正确的。
on的加入是通过EventManager的addListener方法来做的,这里在每个fn上绑定了_handlers,purgeElement的时候通过Ext.lib.Event的removeListener方法,
见300行
                delete listeners[index][this.WFN];
                delete listeners[index][this.FN];

但是这里是只是删除了fn,没有清楚掉里面的handlers,而handlers有el的引用,因为没法清楚对象.而这个时候fn也就是alertMsg是在window下的,我测了一下,单纯删除他是没用的,必须wrap一下,所以出现了你说的必须用function(){
   alertMsg()
}
才正确的情况
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics