Parameter marshalling between iframes + DWR

View: New views
7 Messages — Rating Filter:   Alert me  

Parameter marshalling between iframes + DWR

by matan_a :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I came upon an issue... not with DWR directly but with how the browsers (Firefox + IE at least) marshal object parameters between iframes which makes a nice mess.

When you pass an object as a parameter between a window and an iframe the object is "cloned" i guess and the type information of the object is removed.  All the functionality of the object is copied though so you mostly won't notice.  For example:

On page 1:

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

            function test() {
                var d = new Date();
                var s = new String();
                var b = new Boolean();
                var n = new Number();

                alert("Parent Date: " + (d instanceof Date));
                alert("Parent String: " + (s instanceof String));
                alert("Parent Boolean: " + (b instanceof Boolean));
                alert("Parent Number: " + (n instanceof Number));
                window.test2.testdate(d);
                window.test2.teststring(s);
                window.test2.testboolean(b);
                window.test2.testnumber(n);
            }

        </script>
    </head>
    <body>
        <input type="button" value="Test!" onclick="test()" />

        <iframe id="test2" name="test2" src="test2a.html" />
    </body>
</html>


And on page 2:

<html>
    <head>
        <title>test2</title>
        <script type="text/javascript" src="/includes/dojo/dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: false, baseScriptUri: '/includes/dojo'"></script>
        <script type="text/javascript">

            function testdate(d) {
                alert("IFrame Date: " + (d instanceof Date));
            };

            function testboolean(b) {
                alert("IFrame Boolean: " + (b instanceof Boolean));
            };

            function testnumber(n) {
                alert("IFrame Number: " + (n instanceof Number));
            };

            function teststring(s) {
                alert("IFrame String: " + (s instanceof String));
            };

        </script>
    </head>
    <body>
    </body>
</html>


All the results of the page 2 will be false because the object loses it's type definition during marshalling.  This matters to DWR because the serializing done in the engine.js relies on instanceof to correctly create data - which causes errors because the type information is gone.   Obviously this only will be noticed if you are using DWR inside the iframe with data passed in from another window:

From engine.js:

dwr.engine._serializeAll = function(batch, referto, data, name) {
  if (data == null) {
    batch.map[name] = "null:null";
    return;
  }

  switch (typeof data) {
  case "boolean":
    batch.map[name] = "boolean:" + data;
    break;
  case "number":
    batch.map[name] = "number:" + data;
    break;
  case "string":
    batch.map[name] = "string:" + encodeURIComponent(data);
    break;
  case "object":
    if (data instanceof String) batch.map[name] = "String:" + encodeURIComponent(data);
    else if (data instanceof Boolean) batch.map[name] = "Boolean:" + data;
    else if (data instanceof Number) batch.map[name] = "Number:" + data;
    else if (data instanceof Date) batch.map[name] = "Date:" + data.getTime();
    else if (data && data.join) batch.map[name] = dwr.engine._serializeArray(batch, referto, data, name);
    else batch.map[name] = dwr.engine._serializeObject(batch, referto, data, name);
    break;
  case "function":
    // We just ignore functions.
    break;
  default:
    dwr.engine._handleWarning(null, { name:"dwr.engine.unexpectedType", message:"Unexpected type: " + typeof data + ", attempting default converter." });
    batch.map[name] = "default:" + data;
    break;
  }
};


If this case for a "marshalled" date, it would still be typeof "object", but not instanceof Date anymore and would use the regular _serializeObject.

I personally have avoided this fix by reinstating the correct objects before calling DWR but this can be a pain and is error-prone.  Is there any chance for a fix inside DWR itself?

For your convenience, i attached the example as html files so you can see it happen.test.zip

Re: Parameter marshalling between iframes + DWR

by matan_a :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sorry, just wanted to say that the dojo script reference is irrelevant to the example :) forgot to remove it.

RE: Parameter marshalling between iframes + DWR

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi matan,

[sorry about the delay, going through old mails...]

> I came upon an issue... not with DWR directly but with how
> the browsers
> (Firefox + IE at least) marshal object parameters between
> iframes which
> makes a nice mess.
>
> When you pass an object as a parameter between a window and
> an iframe the
> object is "cloned" i guess and the type information of the object is
> removed.  All the functionality of the object is copied
> though so you mostly
> won't notice.  For example:

Yes, instanceof and multiple frames usually means problems (but it
actually isn't about cloning, it's about different prototype
objects on types).

Joe: I think we decided to remove all use of instanceof some time
ago. Should I go in and fix engine.js for 2.0.4 ?

Best regards
Mike

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...


Re: Parameter marshalling between iframes + DWR

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Yes please, Mike.
Thanks,

Joe.

On Wed, May 14, 2008 at 4:58 PM, Mike Wilson <mikewse@...> wrote:
Hi matan,

[sorry about the delay, going through old mails...]

> I came upon an issue... not with DWR directly but with how
> the browsers
> (Firefox + IE at least) marshal object parameters between
> iframes which
> makes a nice mess.
>
> When you pass an object as a parameter between a window and
> an iframe the
> object is "cloned" i guess and the type information of the object is
> removed.  All the functionality of the object is copied
> though so you mostly
> won't notice.  For example:

Yes, instanceof and multiple frames usually means problems (but it
actually isn't about cloning, it's about different prototype
objects on types).

Joe: I think we decided to remove all use of instanceof some time
ago. Should I go in and fix engine.js for 2.0.4 ?

Best regards
Mike

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...



RE: Parameter marshalling between iframes + DWR

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ok, now I've checked in updated code for correctly detecting native types across frames.
 
To get this working across all browsers (available to me: IE6, IE7, FF2, Safari 2 & 3, Opera 9) I had to use the classic Object.prototype.toString.call() trick. This decreases type detection performance to 17usec from previous 11usec (using instanceof) on my mid-range PC.
 
In the great whole of serializing data this is probably not a big deal, but we could improve this performance by f ex caching the type detection on each native class's constructor function. That would bring type detection cost down to 8usec (ie better than before) but would mean adding a property (something like "$dwrclass" or similar) on each visited native class on the global object. Note that this wouldn't imply any property pollution on user objects as the property would be added to the constructor function and not to the prototype object.
Any comments or opinions about this?
 
Joe: I've only checked this in for the 2.x branch currently. Should I update HEAD as well or will you do it yourself?
 
Best regards
Mike


From: joseph.walker@... [mailto:joseph.walker@...] On Behalf Of Joe Walker
Sent: den 16 maj 2008 18:18
To: users@...
Subject: Re: [dwr-user] Parameter marshalling between iframes + DWR


Yes please, Mike.
Thanks,

Joe.

On Wed, May 14, 2008 at 4:58 PM, Mike Wilson <mikewse@...> wrote:
Hi matan,

[sorry about the delay, going through old mails...]

> I came upon an issue... not with DWR directly but with how
> the browsers
> (Firefox + IE at least) marshal object parameters between
> iframes which
> makes a nice mess.
>
> When you pass an object as a parameter between a window and
> an iframe the
> object is "cloned" i guess and the type information of the object is
> removed.  All the functionality of the object is copied
> though so you mostly
> won't notice.  For example:

Yes, instanceof and multiple frames usually means problems (but it
actually isn't about cloning, it's about different prototype
objects on types).

Joe: I think we decided to remove all use of instanceof some time
ago. Should I go in and fix engine.js for 2.0.4 ?

Best regards
Mike

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...



Re: Parameter marshalling between iframes + DWR

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Sun, Jun 29, 2008 at 11:28 AM, Mike Wilson <mikewse@...> wrote:

In the great whole of serializing data this is probably not a big deal, but we could improve this performance by f ex caching the type detection on each native class's constructor function. That would bring type detection cost down to 8usec (ie better than before) but would mean adding a property (something like "$dwrclass" or similar) on each visited native class on the global object. Note that this wouldn't imply any property pollution on user objects as the property would be added to the constructor function and not to the prototype object.
Any comments or opinions about this?

My gut reaction is that this could still end up breaking things. I think the general rule for libraries is to polute close to nothing - which is what this is all about: http://www.openajax.org/member/wiki/Registry_Candidates
 
Joe: I've only checked this in for the 2.x branch currently. Should I update HEAD as well or will you do it yourself?

Yes please (IIRC, you did already?).

Joe.
 


RE: Parameter marshalling between iframes + DWR

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

we could improve this performance by f ex caching the type detection on each native class's constructor function. That would bring type detection cost down to 8usec (ie better than before) but would mean adding a property (something like "$dwrclass" or similar) on each visited native class on the global object.

My gut reaction is that this could still end up breaking things. I think the general rule for libraries is to polute close to nothing - which is what this is all about: http://www.openajax.org/member/wiki/Registry_Candidates 
That's fine, we'll skip that then.
Joe: I've only checked this in for the 2.x branch currently. Should I update HEAD as well or will you do it yourself?

Yes please (IIRC, you did already?). 
No, I only checked in 2.x branch so there's still instanceof in HEAD's engine.js?
(But I'll be checking in the fixed version the next few minutes.)
 
Best regards
Mike