js-bindings Error: Invalid Native Object

Hello,

I got this error.
12-30 14:43:55.368: D/cocos2d-x debug info(27933): JS: assets/tablero.js:1143:Error: Invalid Native Object

When I call this method.

var seq = cc.Sequence.create(listaSecuencia);

On cocos2d-html5 works fine, but on android I got errors. Could someone help me find a solution?

This is the code of the function that doesn’t work fine.

  muestraAnimacionPreguntar: function(carasOcultar, acertado, selContinuar, sender) {
        this.getChildByTag(this._ultimaVentana).ocultaBotones();

        var count = carasOcultar.length;

        var listaSecuencia = [];

        var nullF = cc.CallFunc.create(this.nullFunction, this);
        nullF.setDuration(JS.CONSTANTS.TABLERO.TIEMPO_ESPERA);

        listaSecuencia.push(nullF);

        if (acertado) {
            var showAura = cc.CallFunc.create(this.muestraAuraResolver, this);
            showAura.setDuration(JS.CONSTANTS.TABLERO.TIEMPO_AURA);
            listaSecuencia.push(showAura);
        }else {
            var showX = cc.CallFunc.create(this.muestraXResolver, this);
            showX.setDuration(JS.CONSTANTS.TABLERO.TIEMPO_X);
            listaSecuencia.push(showX);
        }

        var ocultaPS = cc.CallFunc.create(this.cierraVentana, this, true);
        ocultaPS.setDuration(JS.CONSTANTS.TABLERO.TIEMPO_ESPERA);
        listaSecuencia.push(ocultaPS);

        //Activo todas las caras que no cumplen la condicion (para que el usuario las pulse)
        for (var i = 0; i < count; i++) {
            var number = carasOcultar[i];
            var showX = cc.CallFunc.create(this.muestraCancelaCara, this, number.id);
            showX.setDuration(0);//Tiene que ser 0 para que todas se muestren a la vez
            listaSecuencia.push(showX);
        }


        if (sender) {
            listaSecuencia.push(cc.CallFunc.create(this.endAnimacionPreguntar, this));

            var cambioJugador = cc.CallFunc.create(selContinuar, sender);
            cambioJugador.setDuration(0);

            listaSecuencia.push(cambioJugador);
        }else {
            //Actualizo el numero de caras a tachar
            this._carasATacharCount = count;
            //Eliminar el array al acabar la animacion de preguntar
            this._carasATachar = carasOcultar.slice(0);

            //Activo y permito escuchar touches
            var activarTouches = cc.CallFunc.create(this.escuchaTouches, this, true);
            activarTouches.setDuration(0);
            listaSecuencia.push(activarTouches);

            //Pausa
            var nullF2 = cc.CallFunc.create(this.nullFunction, this);
            nullF2.setDuration(JS.CONSTANTS.TABLERO.TIEMPO_TACHADO_MANUAL);
            listaSecuencia.push(nullF2);

            //Acabo la animacion
            listaSecuencia.push(cc.CallFunc.create(this.tachadoAutomaticoPreguntar, this));
        }

        cc.log("listaSecuencia "+ listaSecuencia.toString());  <--- listaSecuencia is valid
        var seq = cc.Sequence.create(listaSecuencia);  <----Throws the error.
        cc.log("seq "+seq);
        this.runAction(seq);

Ok, after looking to js-binding I think I found the problem.

I’m passing a javascript Array, and it seems like this function is not working fine.

JSBool js_cocos2dx_CCSequence_create(JSContext *cx, uint32_t argc, jsval *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    if (argc > 0) {
        cocos2d::CCArray* array = cocos2d::CCArray::create();
        uint32_t i = 0;
        while (i < argc) {
            js_proxy_t *proxy;
            JSObject *tmpObj = JSVAL_TO_OBJECT(argv[i]);
            proxy = jsb_get_js_proxy(tmpObj);
            cocos2d::CCObject *item = (cocos2d::CCObject*)(proxy ? proxy->ptr : NULL);
            TEST_NATIVE_OBJECT(cx, item)
            array->addObject(item);
            i++;
        }
        cocos2d::CCFiniteTimeAction* ret = cocos2d::CCSequence::create(array);
        jsval jsret;
        do {
            if (ret) {
                js_proxy_t *p = jsb_get_native_proxy(ret);
                if (p) {
                    jsret = OBJECT_TO_JSVAL(p->obj);
                } else {
                    // create a new js obj of that class
                    js_proxy_t *proxy = js_get_or_create_proxy(cx, ret);
                    jsret = OBJECT_TO_JSVAL(proxy->obj);
                }
            } else {
                jsret = JSVAL_NULL;
            }
        } while (0);
        JS_SET_RVAL(cx, vp, jsret);
        return JS_TRUE;
    }
    JS_ReportError(cx, "wrong number of arguments");
    return JS_FALSE;
}

But I don’t know how to solve the problem. I will try to find another method for calling my sequence with objects, rather than with an array of objects.

Try:

runAction(cc.Sequence.create(pAnimate,
cc.CallFunc.create(this.setBoomInvisible, this),
null));

This code doesn’t work for me, because I don’t know the exact number of actions to run. All the actions are on an array.

But I found a solution looking at cocos2d-html5 code.

var prev = listaSecuencia[0];
        for (var i = 1; i < listaSecuencia.length; i++) {
            if (listaSecuencia[i])
                prev = cc.Sequence.create(prev, listaSecuencia[i]);
        }
        //var seq = cc.Sequence.create(listaSecuencia);
        this.runAction(prev);

(/)

i found this problem too, cc.Sequence don’t work well with js array.
I write a new create method for array argument to solve this problem.

cc.Sequence.createWithArray = function(arr) {
    if (arr.length === 0) {
        return cc.Sequence.create();
    } else if (arr.length === 1) {
        return cc.Sequence.create(arr[0]);
    } else if (arr.length === 2) {
        return cc.Sequence.create(arr[0], arr[1]);
    } else {
        var last = arr.pop();
        return cc.Sequence.create(cc.Sequence.createWithArray(arr), last);
    }
};

:slight_smile: ,Good Job!

I get this error when i add sprites to an array, it works perfectly the first time i enter the scene, but when you re-initialize the scene (next level), it throws this error.

I have

this._enemiesArray:[]; //as a class variable

//In some places in my code:
this.enemiesArray.push(enemy);

//Then, onUpdate, i call this, and it throws invalid object error
//loop through enemiesArray
enemy.getBoundingBox();

hi, this problem perhaps cause by the enemy was not retained.
in c**, one object will be release in next frame if it was not add to node, though the js-object is exist, but its’ c**-object is null, so this error occurs.
to solve this problem, you could add enemy to a node and set visible false, or call retain for every enemy, you will need to release them when you not use them.

bad idea.
in js. we could use function.apply.
fun(a,b,c) same as fun.apply(undefined,[a,b,c])
so use cc.Sequence.create.apply(undefined,actionList) should be ok