2010-06-22 13 views
7

Bien, estoy un poco perplejo. Probablemente me falta algo descaradamente obvio, pero aparentemente no puedo ver el bosque para los árboles:Cómo crear una matriz de JavaScript "real" en Rhino

Estoy tratando de llamar a una función de JavaScript que espera que su parámetro sea una matriz, es decir, comprueba if (arg instanceof Array)... Desafortunadamente, yo (o Rhino) parece que no puede crear una gama tan amplia:

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(); 

Y por desgracia, es resultfalse.

¿Qué me falta aquí?

Editar:
Sólo un poco más de información: tanto [] instanceof Array y new Array() instanceof Array retorno true como cabría esperar. Si agrego elementos a la matriz que aparecen en el código JavaScript con los índices correctos (numéricos, a partir de cero):

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

Cuando la salida de usar esta función JavaScript:

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

El resultado es :

object 
    0 => 42 
    1 => foo 

Así que funciona. Excepto que yo quiero una matriz 'real' :)

+1

¿Es posible añadir algunas diagnistics af() para averiguar cuál es el argumento que obtienes en realidad? – djna

+0

Agregué cierta información, tal vez eso ayuda – n3rd

+1

El control que está haciendo la biblioteca ('a instanceof Array') es razonable, pero limitado. Por ejemplo, incluso sin Rhino, no podría identificar una matriz en una aplicación basada en navegador si esa matriz se originó en otra ventana. ¿Intentarías agregar 'result.push (Object.prototype.toString.call (a));' a tu función? Será interesante ver si dice '[object Object]' or '[object Array]'. Este último sería similar a un arreglo de otra ventana, el primero indicaría que 'NativeArray' no era exactamente lo que su nombre implica. –

Respuesta

8

casi lo olvido: Object.prototype.toString.call(a) vuelve [object Array]

bien, esa es la información crucial. Eso nos dice que la matriz realmente es una matriz, es solo que está siendo inicializada por un constructor Array en un alcance diferente al que la función está probando, exactamente como si estuvieras probando una matriz desde una ventana contra otra ventana Array constructor en una aplicación basada en navegador. Por ejemplo, hay un problema de alcance.

intentar sustituir

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

con

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

... para asegurar que se utilice la correcta Array constructor. Debido a que usted ha ido directamente a la NativeArray constructor, que ha Omitió asegurando que su alcance es correcta, y así de constructor el objeto de matriz es un Array constructor, pero no la misma Array constructor como el que está en el objeto global la función ve.

+0

Me di cuenta de eso, aunque podría haber jurado que lo intenté más temprano hoy. ¡Gracias! – n3rd

1

Para aquellos que están creando intencionalmente una subclase diferente de la aplicación matriz, y por lo tanto no se puede utilizar cx.newArray, lo que puede hacer es: añadir esta línea ScriptRuntime.setBuiltinProtoAndParent(fArgs, scope, TopLevel.Builtins.Array);

Cuestiones relacionadas