Bug in array behavior when passing from JSNI to included script

177 views
Skip to first unread message

Erem

unread,
Apr 25, 2010, 1:18:30 AM4/25/10
to Google Web Toolkit
Hey guys,

I observed some unexplainable behavior in GWTTestCase today. Has
anyone else seen this? If not I'll go ahead and file an issue.

The problem:
Any GWT/JSNI-created Javascript Array that I pass to functions defined
in an external .js library will return FALSE for "instanceof Array".

I'm attaching a test case that reproduces the error, along with the
module.xml in question and the external script necessary to run the
tests.

=========== com/testarrays/TestArrays.gwt.xml ================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.3//
EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.3/distro-
source/core/src/gwt-module.dtd">
<module>
<inherits name="com.google.gwt.user.User" />

<!-- Include dependent packaged .js lib -->
<public path="client" />
<script src="testArrays.js" />

<!-- Paths for translatable java code -->
<source path='client'/>
</module>

=========== com/testarrays/client/testArrays.js
===================
var TestArrays = {}

TestArrays.isAnArray = function(inArray) {
return (inArray instanceof Array)
}

TestArrays.myArraysAreArrays = function() {
return (["a", "b", "c"] instanceof Array)
}

=========== com.testarrays.client.TestArrays.java ===================
package com.testarrays.client;

import com.google.gwt.junit.client.GWTTestCase;

public class TestArrays extends GWTTestCase {

/*
* Arrays passed to functions in external script are not recognized
* as arrays!
*/
public void testArraysAreRecognizableInExternalJavascript() {
//fails
assertTrue(arrayPassedToExternalFileIsAnArray());
}
final native boolean arrayPassedToExternalFileIsAnArray() /*-{
return $wnd.TestArrays.isAnArray(["a", "b", "c"])
}-*/;

/*
* But pure GWT JSNI recognizes arrays just fine
*/
public void testArraysAreArraysInPureJSNI() {
assertTrue(arrayInPureJSNIIsAnArray());
}
final native boolean arrayInPureJSNIIsAnArray() /*-{
return (["a", "b", "c"] instanceof Array)
}-*/;


/*
* Most logic within the external file works.
*/
public void testExternalFileIsImportedCorrectly() {
assertTrue(externalFileIsImportedCorrectly());
}
final native boolean externalFileIsImportedCorrectly() /*-{
return $wnd.TestArrays.myArraysAreArrays()
}-*/;


/*
* Even manually attaching a method to a $wnd doesn't yield the
* problem from the first test!
*/
public void testArraysInJsniMethodsWorkFine() {
assertTrue(arrayInJSNIMethodIsAnArray());
}
final native boolean arrayInJSNIMethodIsAnArray() /*-{
$wnd.InternalTest = {}

$wnd.InternalTest.isAnArray = function(inArray) {
return (inArray instanceof Array)
}

return $wnd.InternalTest.isAnArray(["a", "b", "c"])
}-*/;

@Override
public String getModuleName() {
return "com.testarrays.TestArrays";
}
}

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

Thomas Broyer

unread,
Apr 26, 2010, 9:59:02 AM4/26/10
to Google Web Toolkit


On Apr 25, 7:18 am, Erem <ehb...@gmail.com> wrote:
> Hey guys,
>
> I observed some unexplainable behavior in GWTTestCase today. Has
> anyone else seen this? If not I'll go ahead and file an issue.
>
> The problem:
> Any GWT/JSNI-created Javascript Array that I pass to functions defined
> in an external .js library will return FALSE for "instanceof Array".

Because GWT code runs in an iframe, the Array object (and prototype of
any array created within the iframe) is not the same as $wnd.Array.
In other words, "instanceof" won't work cross-frame; this is a known
JS flaw. In browsers following the ECMAScript specification to the
letter, it's possible to implement an "isArray" function as:
Object.prototype.toString.call(o) === '[object Array]', only if the
toString methods hasn't been overwritten of course!

See:
http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

Erem

unread,
Apr 26, 2010, 10:45:33 AM4/26/10
to Google Web Toolkit
Wow. Thanks. Though really, I don't know whether to thank or curse you
for exposing to me this particular skeleton in js's closet. =)


On Apr 26, 6:59 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> On Apr 25, 7:18 am, Erem <ehb...@gmail.com> wrote:
>
> > Hey guys,
>
> > I observed some unexplainable behavior in GWTTestCase today. Has
> > anyone else seen this? If not I'll go ahead and file an issue.
>
> > The problem:
> > Any GWT/JSNI-created Javascript Array that I pass to functions defined
> > in an external .js library will return FALSE for "instanceof Array".
>
> Because GWT code runs in an iframe, the Array object (and prototype of
> any array created within the iframe) is not the same as $wnd.Array.
> In other words, "instanceof" won't work cross-frame; this is a known
> JS flaw. In browsers following the ECMAScript specification to the
> letter, it's possible to implement an "isArray" function as:
> Object.prototype.toString.call(o) === '[object Array]', only if the
> toString methods hasn't been overwritten of course!
>
> See:http://perfectionkills.com/instanceof-considered-harmful-or-how-to-wr...
Reply all
Reply to author
Forward
0 new messages