Opened 9 years ago

Closed 9 years ago

Last modified 6 years ago

#11262 closed defect (wontfix)

[regression] can't create widget with params object from another frame

Reported by: Douglas Hays Owned by: Eugene Lazutkin
Priority: high Milestone: 1.5
Component: Core Version: 1.5.0b2
Keywords: Cc: bill
Blocked By: Blocking:

Description

Run the following web page in IE. A simple widget is created by an iframe in the parent window. Click the button in the main window to destroy the widget. An exception is thrown saying bases is not defined. This seems to be part of the dojo.declare refactor. This works in Dojo 1.3 but not 1.4 nor 1.5. This is preventing a customer from upgrading.

<html>
<head>
        <script type="text/javascript" src="../trunk/dojo/dojo.js" djConfig="isDebug: true"></script>
        <script type="text/javascript">
                dojo.require("dijit.dijit");
        </script>
</head>
<body>
        <script type="text/javascript">
                dojo.declare("Some.Widget", [dijit._Widget, dijit._Templated], {
                        templateString: "<div>programmatically created widget</div>"
                });
        </script>
        <div id="widgetGoesHere"></div>
        <iframe src="javascript:'<html><body><script>new window.parent.Some.Widget({},\'widgetGoesHere\');<\/script><\/body><\/html>'"></iframe>
        <button onclick="dijit.byId('widgetGoesHere').destroy()">click here to destroy the widget and see exception in inherited</button>
</body>
</html>

Attachments (1)

11262.jpg (25.4 KB) - added by Douglas Hays 9 years ago.

Download all attachments as: .zip

Change History (11)

comment:1 Changed 9 years ago by Eugene Lazutkin

Priority: highlow
severity: criticalminor
Status: newassigned

What was the exception exactly, and where? Is there a test case besides the anecdotal evidence?

Changed 9 years ago by Douglas Hays

Attachment: 11262.jpg added

comment:2 Changed 9 years ago by Douglas Hays

The actual testcase is in the description. The customer's actual code could not be included here so I narrowed it down to this simple test. I made it critical/high priority since it's a regression and the customer can't upgrade to 1.4 or 1.5 until its fixed. The exception occurs in the method inherited at this location:

meta = this.constructor._meta;
bases = meta.bases;

With this testcase, meta is undefined. Here's the exception when you click the button that does a destroy:

comment:3 Changed 9 years ago by Clayton Coleman

The issue occurs when dijit._Widget.create() is called on the widget in the iframe (in dojo 1.4.1, at least). When dojo.mixin is called to mix in the empty object {} to the widget, IE8 overwrites most of the "special" properties with values from the 'empty' object. The following segment from dojo.mixin

		if(extraLen && source){
			for(i = 0; i < extraLen; ++i){
				name = extraNames[i];
				s = source[name];
				if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
					target[name] = s;
				}
			}
		}

is invoking 'target[name] = s' on all names in extraNames. (empty[name] !== s) is returning true and (target[name] !== s) is also returning true.

comment:4 Changed 9 years ago by Clayton Coleman

This appears to be the same issue as #9409 - the comment http://bugs.dojotoolkit.org/ticket/9409#comment:18 describes mixin problems for objects in different frames in IE.

comment:5 Changed 9 years ago by Douglas Hays

So changing {} in the testcase to new window.parent.dojo.global.Object() is ugly but seems to workaround the problem.

comment:6 Changed 9 years ago by Clayton Coleman

Has Dojo made a definitive statement as to whether or not it supports cross-frame operations? The statements in the other ticket were a bit vague about whether this should or should not work.

This worked in 1.2 because the empty object that dojo.mixin was comparing to was created in the interpreter context of the iframe. 1.4 uses an empty object on the dojo interpreter context.

Without a fix dojo.mixin is unsafe in IE on any object where the target is created via dojo.declare and the mixin object is created in another frame. Instantiating dijit widgets programmatically across frames is probably not a common practice, but calling dojo.mixin across frames where the target is a dojo class doesn't seem like it should fail.

The simplest possible change which would fix this issue would be changing the empty comparison object to be created during each dojo.mixin call instead of globally. This could potentially be done on IE only, or done conditionally only if one of the special properties does not match. Another option would be the creation of a dijit.mixin (suggested in 9409) specifically for widgets, but that would be more complex and doesn't address the general issue.

comment:7 Changed 9 years ago by Eugene Lazutkin

Priority: lowhigh

comment:8 Changed 9 years ago by Eugene Lazutkin

Priority: highnormal
Resolution: wontfix
Status: assignedclosed

It is impossible to guard against all bugs caused by IE running separate interpreters in different frames. dojo.declare() uses constructor, which is a hidden property on IE, and there are two ways to check it against being non-user-defined:

  1. Check it against the default property value. This is what we do now, and this breaks when creating objects in different frames.
  2. See if it is defined something like that:
"
function Object() {
    [native code]
}
"

I guess we can duplicate the code for IE and check all methods if they are the native ones ignoring them in all place where objects are copied using for..in loops. I don't think it is worth the increased size to support exotic cases like provided when iframe creates objects in the main document using resources of the main document, yet creating its own objects.

I close this ticket for now, but if you have really convincing arguments --- I want to see them.

comment:9 Changed 7 years ago by xipanxiao

Just want to say we hit the same problem now. However starting from IE9 it seems there is no problem. IE8 still has the same problem, even now I'm using dojo 1.7.

comment:10 Changed 6 years ago by bill

Summary: regression: exception in inherited()[regression] can't create widget with params object from another frame

We could interpret this bug report in two ways:

  1. a bug/limitation that dojo.mixin(source, target) doesn't work on IE <= 8 when target is from a different frame
  2. a bug/limitation that new MyWidget(params) fails on IE <= 8 when params is from a different frame

It doesn't seem like an issue with dojo.declare() at all.

(2) could be "fixed" by changing _WidgetBase.js (nee _Widget.js) to just use a for(var p in params) loop rather than dojo.mixin(). The only fallout would be if someone specified a parameter with a funny name, like toString(), which is possible but unlikely.

However, you might soon hit a problem somewhere else due to dojo.mixin() not handling targets from other frames.

Also, I wouldn't say that this ticket is the same as #9409, but rather that it's fallout from #9409, which fixed one problem but caused this other one.

And finally, to answer Clayton's comments, I don't think we've ever officially supported mixin javascript objects from cross frames, although people still keep trying to do it.

Last edited 6 years ago by bill (previous) (diff)
Note: See TracTickets for help on using tickets.