-
Notifications
You must be signed in to change notification settings - Fork 285
Neon 0.2 Migration Guide
Neon 0.2 makes some backwards-incompatible changes, in order to get us closer to an API that we feel comfortable stabilizing on for 1.0. We don’t intend to make many such incompatible changes, but there will probably be a few more before we reach 1.0. In the meantime, this migration guide should provide all the information you need to upgrade a project from the Neon 0.1.x series to Neon 0.2.
Following the module reorganization RFC, Neon’s APIs are organized differently from the 0.1.x series. Fortunately, for the vast majority of cases, you should now be able to radically simplify all of your Neon imports down to a single line:
use neon::prelude::*;
If you’d like more detailed information, check out the latest API documentation.
The single biggest change in 0.2, both conceptually and to the API syntax, is the replacement of the 0.1.x scopes abstraction with the concept of execution contexts. The major differences are:
Where your Neon functions used to look like:
fn my_neon_function(call: Call) -> JsResult<JsString> {
let scope = call.scope;
let x = call.arguments.require(0)?.check::<JsNumber>()?;
... some_neon_api(scope, ...) ...
}
They now look like:
fn my_neon_function(cx: FunctionContext) -> JsResult<JsString> {
let x = cx.argument::<JsNumber>(0)?;
... some_neon_api(&mut cx, ...) ...
}
Notice that instead of passing a scope to various Neon APIs, you now pass a mutable reference to the context. Also notice that argument extraction has gotten a little more expressive, which helps eliminate some common annoying boilerplate.
In Neon 0.1.x, you use the Lock
trait and its grab()
method to get access to the internals of a JavaScript object. In Neon 0.2, you lock the JavaScript engine by calling the execution context’s cx.lock()
method, and you use the Borrow
(or BorrowMut
) trait to get access to the internals of an object. The Borrow::borrow()
and BorrowMut::borrow_mut()
methods require a Lock
object, which is returned from cx.lock()
.
As a shortcut, if you only need to borrow a single object’s internals at a time (which is very common), you can use the context’s cx.borrow()
or cx.borrow_mut()
methods.
For more details, check out the execution context API docs.
Allocating a JavaScript value is a little more convenient now with new convenience methods of execution contexts. For example, instead of:
JsString::new(&mut cx, "hello world")
You can call a method of the cx
itself:
cx.string("hello world")
You can find all the convenience methods in the execution context API docs.
Casting a JavaScript value to another type used to be performed with the handle.check::<T>()
method, but for safety, causing a failed cast to throw a JavaScript exception has to take a reference to an execution context. The new syntax is:
x.downcast::<T>().or_throw(&mut cx)
See the handle API docs for more details.
Previously, the JsBuffer
and JsArrayBuffer
provide access to their internals as a CMutSlice
. In Neon 0.2, borrowing a binary buffer provides a reference to a BinaryData
object, from which you can safely get various typed views:
let mut b = cx.argument::<JsArrayBuffer>(0)?;
let (a, b, c) = cx.borrow_mut(&mut b, |data| {
let slice = data.as_mut_slice::<f64>();
slice[0] = 17.3;
(slice[1], slice[2], slice[3])
});
See the JsArrayBuffer
API docs for more details.
Creating errors is more convenient now. Instead of:
JsError::new(scope, Kind::TypeError, "undefined is not a function")
Each different error type has a construction method in JsError
:
JsError::type_error(&mut cx, "undefined is not a function")
Alternatively, you can use the shorthand method of cx
:
cx.type_error("undefined is not a function")
As an additional convenience, cx
has a shorthand method for the common case of immediately throwing a new error object:
cx.throw_type_error("undefined is not a function")
See the JsError
API docs and the execution context API docs for more details.
String creation (JsString::new()
and cx.string()
) no longer returns an Option
by default. In the rare case that a string is too long, this will panic (which results in throwing an exception back into Node). Otherwise this method never fails.
If you are working with strings coming from an untrusted source (such as from the filesystem, the network, or user input) and you want to defensively check for string overflow in your Rust code without triggering a JavaScript exception, use the new JsString::try_new()
method.
The Key
trait has been renamed to PropertyKey
, and its methods have been renamed. You should almost never need to import this trait directly, so this is unlikely to affect any code in practice. The benefit of this change is to improve the quality of Rust type errors when users forget to import the Object
trait.
This exposed a low-level implementation detail of V8 and isn’t future-proof for other JS engines like Chakra. For most use cases, you can simply replace JsInteger
with JsNumber
.
This was an experimental type to allow the use of Rust’s pattern matching syntax for doing runtime type testing of JavaScript values. But it had some significant design flaws and didn’t turn out to be a successful experiment.
If you want to do a sequence of type tests, you can use Rust’s if let
form to achieve something similar. For example:
if let Ok(s) = x.downcast::<JsString>() {
...
} else if let Ok(a) = x.downcast::<JsArray>() {
...
} // etc...
This trait was confusing, poorly named, and not serving much purpose. Generally if you have an API that takes a ToJsString
, you should just change it to take a JsString
(or a generic V: Value
, which you could convert to a JsString
).
These types are not supported by N-API, so we are removing them until and unless they become a standard part of the Node platform.
This environment variable was no longer actually doing anything, so it shouldn’t affect anyone.
By default, neon build
will build a debug
profile instead of release
. This makes it match the Cargo defaults. You can perform a release build with neon build -r
or neon build --release
.
If you have any build/CI scripts, make sure they use the appropriate flags.
In Neon 0.1.x, you could select the Rust toolchain with the -r
or --rust
flag. In Neon 0.2, toolchain selection matches the Cargo syntax: you can optionally insert a first argument of the form +<toolchain>
where <toolchain>
is the name of the Rust toolchain to use.