Search code examples
rustnode.js-addon

Can't use a neon JsArray: This function takes 3 parameters but 2 were supplied


I'm learning how to use neon, but I don't understand a thing. If I try to execute this code:

#[macro_use]
extern crate neon;
use neon::vm::{Call, JsResult};
use neon::mem::Handle;
use neon::js::{JsInteger, JsNumber, JsString, JsObject, JsArray, JsValue, Object, Key};
use neon::js::error::{JsError, Kind};

fn test(call: Call) -> JsResult<JsArray> {
    let scope = call.scope;
    let js_arr: Handle<JsArray> = try!(try!(call.arguments.require(scope, 1)).check::<JsArray>());

    js_arr.set(0, JsNumber::new(scope, 1000));

    Ok(js_arr)
}

register_module!(m, {
    m.export("test", test)
});

I get this error when I call js_arr.set: This function takes 3 parameters but 2 were supplied.

I don't understand why since it's a JsArray. Even Racer tells me that the set method takes 2 parameters. No matter what, js_arr.set takes 3 parameters in this order: &mut bool, neon::macro_internal::runtime::raw::Local and neon::macro_internal::runtime::raw::Local.

What's happening? I can't understand how JsArray works.


Solution

  • As paulsevere says on a GitHub issue for Neon, import neon::js::Object. In addition, do not import Key, which also provides a set method:

    #[macro_use]
    extern crate neon;
    
    use neon::vm::{Call, JsResult};
    use neon::js::{Object, JsArray, JsInteger, JsObject, JsNumber};
    
    fn make_an_array(call: Call) -> JsResult<JsArray> {
        let scope = call.scope; // the current scope for rooting handles
        let array = JsArray::new(scope, 3);
        array.set(0, JsInteger::new(scope, 9000))?;
        array.set(1, JsObject::new(scope))?;
        array.set(2, JsNumber::new(scope, 3.14159))?;
        Ok(array)
    }
    
    register_module!(m, {
        m.export("main", make_an_array)
    });
    

    This creates a brand new array. If you'd like to accept an array as the first argument to your function and then modify it, this works:

    #[macro_use]
    extern crate neon;
    
    use neon::vm::{Call, JsResult};
    use neon::js::{Object, JsArray, JsInteger, JsUndefined};
    use neon::mem::Handle;
    
    fn hello(call: Call) -> JsResult<JsUndefined> {
        let scope = call.scope;
        let js_arr: Handle<JsArray> = call.arguments.require(scope, 0)?.check::<JsArray>()?;
    
        js_arr.set(0, JsInteger::new(scope, 1000))?;
    
        Ok(JsUndefined::new())
    }
    
    register_module!(m, {
        m.export("hello", hello)
    });