Opened 9 years ago

Closed 9 years ago

#11910 closed defect (fixed)

Using multiple dojo versions in same page breaks dijit._destroyAll

Reported by: rafael.coutinho Owned by: bill
Priority: high Milestone: 1.6
Component: Dijit Version: 1.5
Keywords: dijit destroyall multiple dojos Cc: rdombrowski@…
Blocked By: Blocking:

Description (last modified by bill)

We are using 2 dojo versions in the same page. One with the name esriDojo and another with standard dojo. And we have some Dijits in the page, some using dojo other esriDojo. The problem is that when we are unloading the page in IE 7 the method dijit._destroyAll breaks. It breaks because it tries to destroy widgets that are actually declared in the other dojo. The dijit_destroyAll section that is breaking is as below:

// Destroy all the widgets, top down
	dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
		// Avoid double destroy of widgets like Menu that are attached to body
		// even though they are logically children of other widgets.
		if(!widget._destroyed){
			if(widget.destroyRecursive){
				widget.destroyRecursive();
			}else if(widget.destroy){
				widget.destroy();
			}
		}
	});


The problem is that dijit.findWidgets(dojo.body() returns ALL widgets in body. However when the esriDijit tries to get the widget ID 1, that belongs to the standard dijit version, from its hash it returns undefined (as expected). Unfortunately the destroyAll method will execute: widget._destroyed but widget is undefined (because it belongs to the dijit context not to the esriDijit one) and breaks it.

It only happens in IE, not in FF.

Anyone has any ideas on how to fix it?

I believe dijit.js should add a verification before that 'if' checking if the widget is not undefined.

Thanks.

Change History (3)

comment:1 Changed 9 years ago by James Burke

It looks like dijit.getUniqueId uses dijit._scopeName to generate the widget ID. Seems like dijit.findWidgets should use this information when selecting which widgets to select: if dijit._scopeName is not "dijit" and the widget ID contains dijit._scopeName + "_" then it is a widget for that version, otherwise if dijit._scopeName is "dijit" and the widget Id does not have an underscore in it, then a match.

That logic could be made simpler if dijit.getUniqueId always prepended dijit._scopeName to the ID.

comment:2 Changed 9 years ago by bill

Component: GeneralDijit
Description: modified (diff)
Milestone: tbd1.6
Owner: changed from anonymous to bill
Status: newassigned

@jburke - That would solve half (or most) of the problem, but a problem would still happen when the app specifies id's for all of it's widgets.

@rafael.coutinho - When you say that

dijit.findWidgets(dojo.body() returns ALL widgets in body

I assume you mean that it returns a sparse array with undefined for widgets from the other dojo version. Does that sound right?

findWidgets() has this code, which I think just needs to check that the id is in hash rather than assuming it is:

var widgetId = node.getAttribute("widgetId");
if(widgetId){
	outAry.push(hash[widgetId]);
}else{

It should be changed to something like:

var widgetId = node.getAttribute("widgetId"),
	widget = widgetId && hash[widgetId],
if(widget){
	outAry.push(widget);
}else{

comment:3 Changed 9 years ago by bill

Resolution: fixed
Status: assignedclosed

(In [23319]) Make findWidgets() and thus _destroyAll() ignore widgets created by other dijit instances. Fixes #11910 !strict.

Note: See TracTickets for help on using tickets.