Opened 13 years ago

Closed 12 years ago

#2462 closed defect (fixed)

dojo.event.connect() call does not free up reference to the connected node causing the node to remain in memory even after disconnecting and destroying the node.

Reported by: adishabnave@… Owned by: alex
Priority: high Milestone: 0.9beta
Component: Events Version: 0.4.1
Keywords: Cc:
Blocked By: Blocking:

Description

Using dojo.event.connect call to connect a dom node to event handlers causes the dom node to remain in memory even after disconnecting and destroying the node. This is because all the references to the node are not cleared. If i use an 'onclick'/'oncontextmenu' property instead of doing a connect, the memory is reclaimed. Below is a test case. Dojo version is 0.4.1 Browser is IE Needs sIeve to test the memory issue http://home.wanadoo.nl/jsrosman/


<!DOCTYPE HTML PUBLIC "-W3CDTD HTML 4.01EN"

"http://www.w3.org/TR/html4/strict.dtd">

<html> <head> </script> <script type="text/javascript">

dojo.require("dojo.widget.Menu2"); dojo.hostenv.writeIncludes();

</script> </head> <body> <h3 id="test1" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 1</h3> <h3 id="test2" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 2</h3> <h3 id="test3" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 3</h3> <h3 id="test4" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 4</h3> <h3 id="test5" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 5</h3> <h3 id="test6" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 6</h3> <h3 id="test7" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 7</h3> <h3 id="test8" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 8</h3> <h3 id="test9" style="background-color: gray; display: block; width: 200px;text-align: center;">TEST 9</h3>

<div widgetId="testMenu" dojoType="PopupMenu2" targetNodeIds="test1;test2;test3;test4;test5;test6;test7;test8;test9">

<div dojoType="MenuItem2" caption="MENU ITEM!"></div>

</div> </body> </html>


1.) Open the page in sIeve, click 'show in use' nodes. 2.) Close the tab, see that all the <h3> elements which were bound to the menu are not freed, so they keep occupying browser memory. 3.) Now in Menu2.js -> replace the bindDomNode and unBindDomNode method with the following:


bindDomNode: function(/*String|DomNode?*/ node){

summary: attach menu to given node node = dojo.byId(node);

var win = dojo.html.getElementWindow(node); if(dojo.html.isTag(node,'iframe') == 'iframe'){

win = dojo.html.iframeContentWindow(node); node = dojo.withGlobal(win, dojo.body);

} fixes node so that it supports oncontextmenu if not natively supported, Konqueror, Opera more? dojo.widget.Menu2.OperaAndKonqFixer?.fixNode(node);

/*dojo.event.kwConnect({

srcObj: node, srcFunc: "oncontextmenu", targetObj: this, targetFunc: "onOpen", once: true

});*/

node.oncontextmenu = this.onContextMenu;

normal connect does not work if document.designMode is on in FF, use addListener instead if(dojo.render.html.moz && win.document.designMode.toLowerCase() == 'on'){

dojo.event.browser.addListener(node, "contextmenu", dojo.lang.hitch(this, "onOpen"));

} dojo.widget.PopupManager?.registerWin(win);

},

onContextMenu: function(evt){

if (!evt){

evt = window.event; evt = dojo.event.browser.fixEvent(evt);

}

dojo.widget.byId('testMenu').onOpen(evt);

},

unBindDomNode: function(/*String|DomNode?*/ nodeName){

summary: detach menu from given node var node = dojo.byId(nodeName); /*dojo.event.kwDisconnect({

srcObj: node, srcFunc: "oncontextmenu", targetObj: this, targetFunc: "onOpen", once: true

});*/

node.oncontextmenu = null;

cleans a fixed node, konqueror and opera dojo.widget.Menu2.OperaAndKonqFixer?.cleanNode(node);

},


4.) Repeat steps 1 and 2 and see that all <h3> elements are freed and memory reclaimed.

We are using a tree with 1000's of nodes and different nodes have different context menus so we need to call the bindDomNode on each Tree Node.Now if we destroy the tree by closing the tab which contains the tree, all the tree nodes are orphaned but they still remain in the browser memory. I have noticed this issue with the connect call in a lot of places.

Change History (3)

comment:1 Changed 13 years ago by alex

Milestone: 0.4.20.9M1
Status: newassigned

Yep. Confirmed. Don't know if we'll hit it for 0.4.2, though.

comment:2 Changed 13 years ago by alex

Milestone: 0.9M10.9beta

comment:3 Changed 12 years ago by alex

Resolution: fixed
Status: assignedclosed

A new reference handling system in 0.9's dojo.connect() should eliminate this issue. Feel free to reopen if your testing shows differently than ours does.

Note: See TracTickets for help on using tickets.