When a JsClass wraps a Rust datatype, there should be an API that lets you construct an instance of the class by transferring the data in and bypassing the usual JS constructor.
馃憤
Is there any plan to add this? With the addition of the Task API, it would make it possible to write an asynchronous function that constructs a Class and passes it to a callback.
Are you still planning to implement this?
Is there currently a workaround for this (e.g. could we call the constructor of the JsClass from Rust)?
Thinking about something like this:
method getAddress(call) {
let scope = call.scope;
let user_handle = call.arguments.this(scope);
let mut user = *user_handle;
let address = user.grab(|u| { &u.address });
let addressClass: Handle<JsClass<JsAddress>> = JsAddress::class(scope)?;
let addressConstructor: Handle<JsFunction<JsAddress>> = addressClass.constructor(scope)?;
let constructor = *addressConstructor;
let args: Vec<Handle<JsNumber>> = vec![];
Ok(constructor.call(scope, JsNull::new(), args)?)
}
... which fails with the error message
TypeError: Address constructor called without new.
are we close to solving this?
Working on an RFC for this! I will post it this weekend, and then if we all like the look of it, the writeup should make it easier for someone to implement!
OK, I looked into this! I actually think we already have what @abrodersen and @mrzenioszeniou are asking for, with JsFunction::construct(). So for example, with @mrzenioszeniou's example, you could do:
method getAddress(call) {
let scope = call.scope;
let user_handle = call.arguments.this(scope);
let mut user = *user_handle;
let address = user.grab(|u| { &u.address });
let addressClass: Handle<JsClass<JsAddress>> = JsAddress::class(scope)?;
let addressConstructor: Handle<JsFunction<JsAddress>> = addressClass.constructor(scope)?;
let constructor = *addressConstructor;
let args: Vec<Handle<JsNumber>> = vec![];
Ok(constructor.construct(scope, args)?)
}
I think we can also add a shorthand JsClass::construct method to abstract out the boilerplate of extracting the constructor from the class before invoking it.
This issue proposed a slightly different thing, which I think is actually not future-proof for eventually adding support for subclassing and the ES6 super() protocol. I think what I'll do is separate out the two things as RFC issues, and the first one (JsClass::construct) should be a tiny RFC and straightforward, and the second one should be more of an exploration for now, since neither the V8 API nor the N API yet support the super() protocol.
Actually I think we can also add a Class::construct convenience method too. That would simplify the example to:
method getAddress(call) {
let scope = call.scope;
let user_handle = call.arguments.this(scope);
let mut user = *user_handle;
let address = user.grab(|u| { &u.address });
let args: Vec<Handle<JsNumber>> = vec![];
Ok(JsAddress::construct(scope, args)?)
}
OK here's an RFC for the convenience forms--feedback welcome!
neon-bindings/rfcs#17
@dherman you've closed that RFC - is there any alternative API for this now, or should I consider restructuring my code?
@antonok-edm this RFC supersedes it: https://github.com/neon-bindings/rfcs/pull/33
I don't believe there is _currently_ an alternative API for this.
The aim is to first introduce a lower-level primitive that is _only_ used for the case mentioned in this issue: wrapping an existing Rust data structure into an opaque JS value. In the future, things like the class macro could be built on top of that.
@antonok-edm There are workarounds for now. @kjvalencik documented some in these examples: https://github.com/neon-bindings/examples/tree/master/class-factory
What we're working on now is the JsBox RFC, which is a much more streamlined primitive than the class macro. I'd say it's too soon to restructure your code. And one of our goals is to move the class macro into a separate library (which implements it in terms of JsBox), so people can easily migrate their code without having to restructure it before we deprecate the class macro.
Oh, I see @goto-bus-stop said something similar 馃槀