Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GWT-JSNI passing a JavaScriptObject in an external JS library

I'm desesperatly trying to create an Anno object in a JSNI method but I have a strange problem : the code in the jsni method doesn't work but if I do the same in my browser console, it works fine.

Java Part

I'm using a JSONArray in wich I add some JSONObject (with all the elements, according to Anno doc). Here's my JSNI method :

// I'm using the getJavaScriptObject() on my JSONArray
private static native void launch( JavaScriptObject steps )/*-{
        var anno = new $wnd.Anno(steps);
        anno.chainIndex().show();
                                                            }-*/;

Browser Part

Just to be clear, the method is called on a onShow event, so all the ressources are loaded and rendered. So when the element is displayed and the function called, I have this error in my console :

Couldn't find Anno.target 'h1'. --- anno.js:265

NB : In Anno.js, h1 is the dafault value of target.

But my steps value is right and when I do the same commands in the console it works :

var testAnno = new Anno([{
    content: "namespinnerFrequencyA",
    position: "center-right",
    target: ".dataAuto0"
},{
    content: "chooseFrequencyB",
    position: "top",
    target: ".dataAuto1"}]);
testAnno.show();

I don't understand why it works in one case and not in the other. I've also tried to use JSON.stringify then JSON.parse but it doesn't work either.


EDIT :

I figured something out. While debugging anno.js I figured something : when I initialized Anno in the console, the local scope look like this (bigger image here ) :

local scope for the console commands

But when I use the jsni method, the local scope is absolutely different, my parameter is stored as an actual array instead of being processed normally (bigger image here ) :

enter image description here

like image 226
Carvallegro Avatar asked May 08 '26 14:05

Carvallegro


1 Answers

The problem is that GWT code runs in an iframe (for sandboxing/isolation) and Anno only supports array types from the same browsing context.

See http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ and http://web.mit.edu/jwalden/www/isArray.html for descriptions of the problem.

ECMAScript 5.1 added an Array.isArray() function that solves that issue and has wide browser support (back up to IE9): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
And jQuery has one too, which makes it incomprehensible (to me) that Anno doesn't use it instead of using the broken if arg.__proto__ is Array.prototype (unless it's by design). So first things first: file an issue on Anno.

As a workaround, it should be possible to use $wnd.Array.apply($wnd.Array, steps) to copy your array into an array from the top window.

like image 59
Thomas Broyer Avatar answered May 10 '26 03:05

Thomas Broyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!