How to create a "real" JavaScript array in Rhino

Ok, I'm a bit stumped. I probably missed something obviously obvious, but apparently I just don't see the forest for the trees:

I am trying to call a JavaScript function that expects its parameter to be an array, i.e. checks if (arg instanceof Array)... Unfortunately, I (or Rhino) simply cannot create such an array:

  Context cx = Context.enter(); Scriptable scope = cx.initStandardObjects(); String src = "function f(a) { return a instanceof Array; };"; cx.evaluateString(scope, src, "<src>", 0, null); Function f = (Function) scope.get("f", scope); Object[] fArgs = new Object[]{ new NativeArray(0) }; Object result = f.call(cx, scope, scope, fArgs); System.out.println(Context.toString(result)); Context.exit(); 

And, alas, result is false .

What am I missing here?

Edit :
Some more information: [] instanceof Array and new Array() instanceof Array return true , as you would expect. If I add elements to the array, they will appear in the JavaScript code with the correct indexes (numeric, starting from zero):

  NativeArray a = new NativeArray(new Object[]{ 42, "foo" }); 

When output using this JavaScript function:

  function f(a) { var result = []; result.push(typeof a); for (var i in a) { result.push(i + ' => ' + a[i]); } return result.join('\\n'); } 

Result:

  object 0 => 42 1 => foo 

And so it works. Except that I need a "real" array :)

+7
javascript arrays rhino
source share
2 answers

Almost forgot: Object.prototype.toString.call(a) returns [object Array]

Well, this is important information. This tells us that the array is indeed an array, it is simply initialized by the Array constructor in a different area than the one that the function is testing, just as if you were testing an array from one window against another window Array in the browser. For example, there is a problem with the scope.

Try replacing

 Object[] fArgs = new Object[]{ new NativeArray(0) }; 

from

 Object[] fArgs = new Object[]{ cx.newArray(scope, 0) }; 

... to ensure the correct Array constructor. Since you went directly to the NativeArray constructor, you circumvented checking the validity of your area and therefore the constructor array object is an Array constructor, but not the same Array constructor as the one on the global object that the function sees.

+8
source share

For those who intentionally create another subclass of array implementation and therefore cannot use cx.newArray, what you can do: add this line ScriptRuntime.setBuiltinProtoAndParent(fArgs, scope, TopLevel.Builtins.Array);

+1
source share

All Articles