Opened 14 years ago

Closed 12 years ago

#670 closed defect (wontfix)

[patch] [cla] support applets as children of widgets

Reported by: adam@… Owned by: bill
Priority: high Milestone: 1.3
Component: Dojox Version: 0.2
Keywords: Cc: adam@…
Blocked By: Blocking:

Description

Main panel of our application is a SplitPane?. One of the split screens contains the applet. In that situation when we try to close IE it freezes and you have to kill the IE process to close this window (in Firefox everything is ok). For the fastest solution I have searched the dojo code and I have found the code which sets window.onunload event only for IE. The problem disappeared after commenting the fragment with dojo.widget.manager.destroyAll(). My solution is of course temporary and I hope you will repaire the problem which is located somewhere in dojo.widget.manager.destroyAll().

Below is the code of my fix.

if(dojo.render.html.ie){

window.onunload=function(){ dojo_ie_clobber.clobber(); /*try{

if((dojowidget?)&&(dojo.widgetmanager?)){

dojo.widget.manager.destroyAll();

}

} catch(e){}*/ try{

window.onload=null;

} catch(e){} try{

window.onunload=null;

} catch(e) {} dojo_ie_clobber.clobberNodes=[]; };

}

Attachments (1)

Mail.html (4.8 KB) - added by adam@… 13 years ago.
Dojo mail demo html with applet

Download all attachments as: .zip

Change History (17)

comment:1 Changed 14 years ago by dylan

Cc: adam@… added
Milestone: 0.4

Have you tried setting djConfig.ieClobberMinimal: true ? Please let us know if that resolves this issue.

comment:2 Changed 13 years ago by dylan

Owner: changed from anonymous to dylan
Status: newassigned

comment:3 Changed 13 years ago by adam@…

  1. Current situation of this problem in our project:
    • we have changed applet loading behaviour (there are no applets displayed on first page loading, only in the background).
    • now we dont need the fix - IE window is closing properly.
  2. Conclusions:
    • probably problem appears when applet is loaded on page load (when dojo parses widgets)
    • I have checked that problem on simple page with widgets and it's still exists - djConfig.ieClobberMinimal: true doesn't help (just put <applet/> into splitpane - I have used Mail.html from dojo's demo [look at attachment])

Changed 13 years ago by adam@…

Attachment: Mail.html added

Dojo mail demo html with applet

comment:4 Changed 13 years ago by dylan

Owner: changed from dylan to alex
Status: assignednew

comment:5 Changed 13 years ago by dylan

Milestone: 0.40.5

given that there is an umpleasant workaround, moving to 0.5

comment:6 Changed 13 years ago by marcel_p@…

Hi,

I have the similar problem - I created my own Widget based on HtmlWidget? class and this custom widget injects a Java Applet into DIV. Everything works fine (applet is properly loaded, I can work with it), however when I try to close the browser (MSIE 6.0/SP2), it freezes and I have to kill it from Task Manager. My Dojo version is final release of 0.4.2.

Then I downgraded Dojo to dojo-0.4.1rc2-ajax (without changing anything in my application) and suddenly the problem disappeared.

Marcel

comment:7 Changed 13 years ago by bill

Milestone: 0.91.0
Owner: changed from alex to koranteng

comment:8 Changed 13 years ago by Adam Peller

Component: WidgetsDijit

comment:9 Changed 12 years ago by bill

Owner: changed from koranteng to bill

comment:10 Changed 12 years ago by bill

Milestone: 1.02.0

comment:11 Changed 12 years ago by guest

I have good information on this bug. It is something that I've encountered in recent development and I've been able to pinpoint the problem. The solution that I've found, however, is not in Dojo code. It's the responsibility of the Widget developer to make sure that the Applet can be properly cleaned up when the window closes.

The Background:

(all dojo code here is from dojo 0.4.3)
When the user closes the IE window, the Java Applet is stopped, destroyed, and the applet quits (all within the JVM). Here's the debug Java Console output when my particular applet (I'm using Ephox EditLive? HTML editor) is cleaned up in IE7:


basic: Stopping applet ...
basic: Removed progress listener: sun.plugin.util.GrayBoxPainter@1415056
basic: Finding information ...
basic: Releasing classloader: sun.plugin.ClassLoaderInfo@1cfb802, refcount=0
basic: Caching classloader: sun.plugin.ClassLoaderInfo@1cfb802
basic: Current classloader cache size: 1
basic: Done ...
basic: Joining applet thread ...
basic: Destroying applet ...
basic: Disposing applet ...
basic: Joined applet thread ...
basic: Quiting applet ...


Now, this is all done before the JavaScript layer gets notification that the window is unloading. So, after the applet has been destroyed, the window's onunload (or onbeforeunload) hook is called and Dojo begins destroying widgets. When the widget containing the applet is destroyed, the call stack goes something like:

Widget.destroy -> HtmlWidget.destroyRendering -> DomWidget.destroyRendering -> dojo.dom.destroyNode -> dojo.event.browser.clean -> dojo._ie_clobber.clobber

When dojo calls the clobber function it will iterate through the DOM tree using the "node.all" property. The <object> node referencing the destroyed applet will be included in this node set.

The PROBLEM:

When dojo iterates through the DOM nodes, it encounters the <object> node for the applet that has already been destroyed. If script tries to reference this DOM node in any way, IE (and any debuggers attached to it) will freeze. The window or tab will not be able to be closed (even though other tabs can still be used) and the process will eventually have to be terminated. I suspect this crash occurs because IE is trying to attach the Applet's public properties and functions to the DOM Node object for script-level access.

The error in this case occurs in dojo/src/event/browser.js, function dojo._ie_clobber.clobber(), on line 25(in the src build): "tna[x]", where tna is the array of DOM nodes and x is an index to the array.

The Solution:

The Applet's DOM Node needs to remain in the DOM until the window is completely closed. This means preventing Dojo from cleaning up after it. However, Dojo's cleanup code is important to prevent memory leaks and it provides good general cleanup of the DOM. So, in order for this to be most effective, the application developer needs to place the applet inside of a wrapper element within the widget that contains it. During the widget's destroy method, the widget must move the wrapper element to a place in the DOM where Dojo will not remove it. Here's a code sample of a proposed "AppletContainer" widget (abbreviated):

dojo.widget.defineWidget(
    "dojo.widget.AppletContainer",
    dojo.widget.HtmlWidget,
    {
        isContainer: true,
        templatePath: dojo.uri.moduleUri("dojo.widget", "templates/AppletContainer.html",
        destroy: function(){
            // Move the Applet's DOM Node so that it isn't part of any widget any more.
            // This allows the JVM in IE to clean up the Applet when the window is closing.
            document.body.appendChild(this.containerNode); // move to the end of the document
            dojo.widget.AppletContainer.superclass.destroy.apply(this, arguments);
        }
    });

This widget example assumes that the widget's template has a wrapper element (the containerNode) with an applet inside of it. For example:

<div id="${this.widgetId}">
    <div dojoAttachPoint="containerNode">
        <object ...><!-- This is the Applet --></object>
    </div>
</div>

To generalize it more, we could say that the applet doesn't need to be defined in the template, in which case the template would look like

<div id="${this.widgetId}">
    <div dojoAttachPoint="containerNode"></div>
</div>

and the widget could be instantiated through markup like

<div dojoType="AppletContainer">
    <object ...><!-- This is the Applet --></object>
</div>

This isn't necessarily a general enough solution for everyone yet, because it assumes that when the widget is being destroyed, the window is closing. But this is a direction to work in. With more work, I think that a general solution could be reached, and that this could possibly be moved back to the 1.0 Milestone. I am a Dojo Contributor, so this code can be used, and I'm happy to help with developing it further. Obviously, in the dojo trunk, the proposed widget would either be in dijit or dojox. Let me know what you think, Bill.

~Michael Smith (msmith in Dojo forums)
savoyboy@…

comment:12 Changed 12 years ago by guest

After a couple more days of working with it, here's an improved impl of the AppletContainer widget:

dojo.widget.defineWidget(
    "dojo.widget.AppletContainer",
    dojo.widget.HtmlWidget,
    {
        isContainer: true,
        templatePath: dojo.uri.moduleUri("dojo.widget", "templates/AppletContainer.html",
        destroy: function(){
            // Remove the applet's DOM node (remove, not destroy -- this is so we don't reference the <object> node directly)
            dojo.dom.removeNode(this.containerNode);

            // Clear the innerHTML so that IE doesn't keep a reference of the applet
            this.containerNode.innerHTML = "";
            
            dojo.widget.AppletContainer.superclass.destroy.apply(this, arguments);
        }
    });

This impl cleans up the applet when the window is closing or when just the widget is being destroyed.

~Michael Smith (msmith) [CLA]

comment:13 Changed 12 years ago by Adam Peller

we'd need code on the new (0.9+) trunk. This appears to be based off obsolete 0.4 code. Also, it's Bill's call, but applet support sounds like dojox to me.

comment:14 Changed 12 years ago by bill

Component: DijitDojox
Priority: highnormal
severity: majornormal
Summary: Applet inside SplitPane -> freeze IE on close[patch] [cla] support applets as children of widgets

I agree; this is an esoteric case, so let's add that widget to dojox, or maybe just document how to do it in the manual.

comment:15 Changed 12 years ago by alex

Milestone: 2.01.3

Milestone 2.0 deleted

comment:16 Changed 12 years ago by bill

Resolution: wontfix
Status: newclosed

Sorry, no plans to support this. Closing as wontfix.

Note: See TracTickets for help on using tickets.