diff --git a/src/context/internal.rs b/src/context/internal.rs index cf69c49f9..ee862d5cc 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -4,8 +4,8 @@ use std::os::raw::c_void; use neon_runtime; use neon_runtime::raw; use neon_runtime::scope::Root; -use value::JsObject; -use value::mem::Handle; +use types::JsObject; +use handle::Handle; use object::class::ClassMap; use result::NeonResult; use super::ModuleContext; diff --git a/src/context/mod.rs b/src/context/mod.rs index 40b201d69..f81d62834 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -1,4 +1,4 @@ -//! Types and traits that represent _execution contexts_, which manage access to the JavaScript engine. +//! Node _execution contexts_, which manage access to the JavaScript engine at various points in the Node.js runtime lifecycle. pub(crate) mod internal; @@ -11,13 +11,13 @@ use neon_runtime; use neon_runtime::raw; use borrow::{Ref, RefMut, Borrow, BorrowMut}; use borrow::internal::Ledger; -use value::{JsResult, JsValue, Value, JsObject, JsArray, JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; -use value::mem::{Managed, Handle}; -use value::binary::{JsArrayBuffer, JsBuffer}; -use value::error::JsError; +use handle::{Managed, Handle}; +use types::{JsValue, Value, JsObject, JsArray, JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; +use types::binary::{JsArrayBuffer, JsBuffer}; +use types::error::JsError; use object::{Object, This}; use object::class::Class; -use result::{NeonResult, Throw, ResultExt}; +use result::{NeonResult, JsResult, Throw}; use self::internal::{ContextInternal, Scope, ScopeMetadata}; #[repr(C)] @@ -468,7 +468,7 @@ impl<'a, T: This> CallContext<'a, T> { /// Produces the `i`th argument and casts it to the type `V`, or throws an exception if `i` is greater than or equal to `self.len()` or cannot be cast to `V`. pub fn argument(&mut self, i: i32) -> JsResult<'a, V> { let a = self.info.require(self, i)?; - a.downcast().unwrap_or_throw(self) + a.downcast_or_throw(self) } /// Produces a handle to the `this`-binding. diff --git a/src/handle/internal.rs b/src/handle/internal.rs new file mode 100644 index 000000000..384606053 --- /dev/null +++ b/src/handle/internal.rs @@ -0,0 +1,5 @@ +use types::Value; + +pub trait SuperType { + fn upcast_internal(T) -> Self; +} diff --git a/src/value/mem.rs b/src/handle/mod.rs similarity index 81% rename from src/value/mem.rs rename to src/handle/mod.rs index b3f5c3ac7..88aece4ba 100644 --- a/src/value/mem.rs +++ b/src/handle/mod.rs @@ -1,4 +1,6 @@ -//! Types encapsulating _handles_ to managed JavaScript memory. +//! Safe _handles_ to managed JavaScript memory. + +pub(crate) mod internal; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; @@ -6,10 +8,10 @@ use std::error::Error; use std::fmt::{self, Debug, Display}; use neon_runtime; use neon_runtime::raw; -use value::{JsResult, Value}; -use value::internal::SuperType; +use types::Value; use context::Context; -use result::ResultExt; +use result::{JsResult, JsResultExt}; +use self::internal::SuperType; /// The trait of data that is managed by the JS garbage collector and can only be accessed via handles. pub trait Managed: Copy { @@ -82,8 +84,8 @@ impl Error for DowncastError { /// The result of a call to `Handle::downcast()`. pub type DowncastResult<'a, F, T> = Result, DowncastError>; -impl<'a, F: Value, T: Value> ResultExt<'a, T> for DowncastResult<'a, F, T> { - fn unwrap_or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> { +impl<'a, F: Value, T: Value> JsResultExt<'a, T> for DowncastResult<'a, F, T> { + fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> { match self { Ok(v) => Ok(v), Err(e) => cx.throw_type_error(&e.description) @@ -118,7 +120,10 @@ impl<'a, T: Value> Handle<'a, T> { U::is_typeof(self.value) } - /// Attempts to downcast a handle to another type, which may fail. + /// Attempts to downcast a handle to another type, which may fail. A failure + /// to downcast **does not** throw a JavaScript exception, so it's OK to + /// continue interacting with the JS engine if this method produces an `Err` + /// result. pub fn downcast(&self) -> DowncastResult<'a, T, U> { match U::downcast(self.value) { Some(v) => Ok(Handle::new_internal(v)), @@ -126,6 +131,13 @@ impl<'a, T: Value> Handle<'a, T> { } } + /// Attempts to downcast a handle to another type, raising a JavaScript `TypeError` + /// exception on failure. This method is a convenient shorthand, equivalent to + /// `self.downcast::().or_throw::(cx)`. + pub fn downcast_or_throw<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> JsResult<'a, U> { + self.downcast().or_throw(cx) + } + } impl<'a, T: Managed> Deref for Handle<'a, T> { diff --git a/src/lib.rs b/src/lib.rs index f33d51d3d..38b3ac01d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API. +//! The [Neon](https://www.neon-bindings.com/) crate provides bindings for writing Node.js plugins with a safe and fast Rust API. extern crate neon_runtime; extern crate cslice; @@ -12,7 +12,8 @@ extern crate rustc_version; extern crate lazy_static; pub mod context; -pub mod value; +pub mod handle; +pub mod types; pub mod object; pub mod borrow; pub mod result; @@ -60,9 +61,9 @@ macro_rules! register_module { dso_handle: *mut u8, filename: *const u8, register_func: Option, *mut u8, *mut u8)>, + $crate::handle::Handle<$crate::types::JsObject>, *mut u8, *mut u8)>, context_register_func: Option, *mut u8, *mut u8, *mut u8)>, + $crate::handle::Handle<$crate::types::JsObject>, *mut u8, *mut u8, *mut u8)>, modname: *const u8, priv_data: *mut u8, link: *mut __NodeModule @@ -81,7 +82,7 @@ macro_rules! register_module { }; extern "C" fn __register_neon_module( - m: $crate::value::Handle<$crate::value::JsObject>, _: *mut u8, _: *mut u8) { + m: $crate::handle::Handle<$crate::types::JsObject>, _: *mut u8, _: *mut u8) { $crate::macro_internal::initialize_module(m, __init_neon_module); } @@ -112,7 +113,7 @@ macro_rules! class_definition { $cname ; $typ ; { - fn _______allocator_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$crate::value::JsUndefined>) -> $crate::result::NeonResult<$typ> { + fn _______allocator_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$crate::types::JsUndefined>) -> $crate::result::NeonResult<$typ> { $body } @@ -134,7 +135,7 @@ macro_rules! class_definition { $new_ctor ; ($($mname)* $name) ; ($($mdef)* { - fn _______method_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$cls>) -> $crate::value::JsResult<$crate::value::JsValue> { + fn _______method_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$cls>) -> $crate::result::JsResult<$crate::types::JsValue> { $body } @@ -150,7 +151,7 @@ macro_rules! class_definition { $allocator ; $call_ctor ; ({ - fn _______constructor_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$cls>) -> $crate::result::NeonResult>> { + fn _______constructor_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$cls>) -> $crate::result::NeonResult>> { $body } @@ -167,7 +168,7 @@ macro_rules! class_definition { $typ ; $allocator ; ({ - fn _______call_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$crate::value::JsValue>) -> $crate::value::JsResult<$crate::value::JsValue> { + fn _______call_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$crate::types::JsValue>) -> $crate::result::JsResult<$crate::types::JsValue> { $body } @@ -197,7 +198,7 @@ macro_rules! class_definition { #[macro_export] macro_rules! impl_managed { ($cls:ident) => { - impl $crate::value::Managed for $cls { + impl $crate::handle::Managed for $cls { fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local { let $cls(raw) = self; raw diff --git a/src/object/class/internal.rs b/src/object/class/internal.rs index 427cab0f6..b04757fc2 100644 --- a/src/object/class/internal.rs +++ b/src/object/class/internal.rs @@ -4,11 +4,12 @@ use std::ptr::null_mut; use neon_runtime; use neon_runtime::raw; use super::{Class, ClassInternal, Callback}; -use value::{JsResult, JsValue, JsObject, JsFunction, JsUndefined, Handle, Managed, build}; +use handle::{Handle, Managed}; use context::{CallbackInfo, CallContext, Context}; use context::internal::ContextInternal; -use result::{NeonResult, Throw}; -use value::error::convert_panics; +use result::{NeonResult, JsResult, Throw}; +use types::{JsValue, JsObject, JsFunction, JsUndefined, build}; +use types::error::convert_panics; #[repr(C)] pub struct MethodCallback(pub fn(CallContext) -> JsResult); diff --git a/src/object/class/mod.rs b/src/object/class/mod.rs index 159dba074..9a399ec0f 100644 --- a/src/object/class/mod.rs +++ b/src/object/class/mod.rs @@ -12,10 +12,11 @@ use neon_runtime::raw; use neon_runtime::call::CCallback; use context::{Context, Lock, CallbackInfo}; use context::internal::Isolate; -use result::{NeonResult, Throw}; +use result::{NeonResult, JsResult, Throw}; use borrow::{Borrow, BorrowMut, Ref, RefMut, LoanError}; -use value::{JsResult, Value, JsFunction, JsValue, Handle, Managed, build}; -use value::internal::ValueInternal; +use handle::{Handle, Managed}; +use types::{Value, JsFunction, JsValue, build}; +use types::internal::ValueInternal; use object::{Object, This}; use self::internal::{ClassMetadata, MethodCallback, ConstructorCallCallback, AllocateCallback, ConstructCallback}; diff --git a/src/object/mod.rs b/src/object/mod.rs index ff27ae391..bdb91d1fe 100644 --- a/src/object/mod.rs +++ b/src/object/mod.rs @@ -4,10 +4,11 @@ pub(crate) mod class; use neon_runtime; use neon_runtime::raw; -use value::{Handle, Managed, JsResult, Value, JsValue, JsArray, build}; -use value::utf8::Utf8; +use handle::{Handle, Managed}; +use types::{Value, JsValue, JsArray, build}; +use types::utf8::Utf8; use context::Context; -use result::{NeonResult, Throw}; +use result::{NeonResult, JsResult, Throw}; pub use self::class::{Class, ClassDescriptor}; diff --git a/src/prelude.rs b/src/prelude.rs index ccb599e39..68461faea 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,8 +1,9 @@ -//! The Neon "prelude," a re-exported collection of the most commonly-used Neon APIs. +//! A convenience module that re-exports the most commonly-used Neon APIs. -pub use value::{Handle, JsResult, JsBuffer, JsArrayBuffer, BinaryData, JsError, Value, JsValue, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, JsObject, JsArray, JsFunction}; +pub use handle::Handle; +pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, Value, JsValue, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, JsObject, JsArray, JsFunction}; pub use object::{Object, Class}; pub use borrow::{Borrow, BorrowMut}; pub use context::{CallKind, Context, ModuleContext, ExecuteContext, ComputeContext, CallContext, FunctionContext, MethodContext, TaskContext}; -pub use result::{NeonResult, ResultExt}; +pub use result::{NeonResult, JsResult, JsResultExt}; pub use thread::Task; diff --git a/src/result/mod.rs b/src/result/mod.rs index fb04f6999..49ce21199 100644 --- a/src/result/mod.rs +++ b/src/result/mod.rs @@ -2,7 +2,8 @@ use std::error::Error; use std::fmt::{Display, Formatter, Result as FmtResult}; -use value::{JsResult, Value}; +use handle::Handle; +use types::Value; use context::Context; /// An error sentinel type used by `NeonResult` (and `JsResult`) to indicate that the JS engine has entered into a throwing state. @@ -24,8 +25,11 @@ impl Error for Throw { /// The result of a computation that might send the JS engine into a throwing state. pub type NeonResult = Result; +/// The result of a computation that produces a JavaScript value and might send the JS engine into a throwing state. +pub type JsResult<'b, T> = NeonResult>; + /// An extension trait for `Result` values that can be converted into `JsResult` values by throwing a JavaScript /// exception in the error case. -pub trait ResultExt<'a, V: Value> { - fn unwrap_or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>; +pub trait JsResultExt<'a, V: Value> { + fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>; } diff --git a/src/thread/mod.rs b/src/thread/mod.rs index acfc8db97..429dba521 100644 --- a/src/thread/mod.rs +++ b/src/thread/mod.rs @@ -1,11 +1,12 @@ -//! Types and traits for implementing multithreaded computation in a Node plugin. +//! Asynchronous access to multithreaded computation in a Node plugin. use std::marker::{Send, Sized}; use std::mem; use std::os::raw::c_void; -use value::{JsResult, Value, JsFunction}; -use value::mem::{Handle, Managed}; +use types::{Value, JsFunction}; +use result::JsResult; +use handle::{Handle, Managed}; use context::TaskContext; use neon_runtime; use neon_runtime::raw; diff --git a/src/value/binary.rs b/src/types/binary.rs similarity index 98% rename from src/value/binary.rs rename to src/types/binary.rs index 72afa4148..be870a667 100644 --- a/src/value/binary.rs +++ b/src/types/binary.rs @@ -7,9 +7,10 @@ use std::slice; use context::{Context, Lock}; use borrow::{Borrow, BorrowMut, Ref, RefMut, LoanError}; use borrow::internal::Pointer; -use value::{JsResult, Value, Object, build}; -use value::mem::Managed; -use value::internal::ValueInternal; +use handle::Managed; +use types::{Value, Object, build}; +use types::internal::ValueInternal; +use result::JsResult; use neon_runtime; use neon_runtime::raw; diff --git a/src/value/error.rs b/src/types/error.rs similarity index 96% rename from src/value/error.rs rename to src/types/error.rs index 5bf16f961..8b8f3e51e 100644 --- a/src/value/error.rs +++ b/src/types/error.rs @@ -7,9 +7,9 @@ use neon_runtime::raw; use context::Context; use result::{NeonResult, Throw}; -use value::{Value, Object, Handle, Managed, build}; -use value::internal::ValueInternal; -use value::utf8::Utf8; +use types::{Value, Object, Handle, Managed, build}; +use types::internal::ValueInternal; +use types::utf8::Utf8; /// A JS `Error` object. #[repr(C)] diff --git a/src/value/internal.rs b/src/types/internal.rs similarity index 88% rename from src/value/internal.rs rename to src/types/internal.rs index 238c2775e..3675c1e00 100644 --- a/src/value/internal.rs +++ b/src/types/internal.rs @@ -3,10 +3,11 @@ use std::os::raw::c_void; use neon_runtime; use neon_runtime::raw; use context::{CallbackInfo, FunctionContext}; -use value::error::convert_panics; -use value::{JsObject, Handle, Managed}; +use types::error::convert_panics; +use types::{JsObject, Handle, Managed}; +use result::JsResult; use object::class::Callback; -use super::{JsResult, Value}; +use super::Value; pub trait ValueInternal: Managed + 'static { fn name() -> String; @@ -26,10 +27,6 @@ pub trait ValueInternal: Managed + 'static { } } -pub trait SuperType { - fn upcast_internal(T) -> Self; -} - #[repr(C)] pub struct FunctionCallback(pub fn(FunctionContext) -> JsResult); diff --git a/src/value/mod.rs b/src/types/mod.rs similarity index 96% rename from src/value/mod.rs rename to src/types/mod.rs index b7b1f873a..a5df16294 100644 --- a/src/value/mod.rs +++ b/src/types/mod.rs @@ -1,8 +1,7 @@ -//! Types and traits for working with JavaScript values. +//! Representations of JavaScript's core builtin types. pub(crate) mod binary; pub(crate) mod error; -pub(crate) mod mem; pub(crate) mod internal; pub(crate) mod utf8; @@ -15,18 +14,16 @@ use neon_runtime; use neon_runtime::raw; use context::{Context, FunctionContext}; use context::internal::Isolate; -use result::{NeonResult, Throw, ResultExt}; +use result::{NeonResult, JsResult, Throw, JsResultExt}; use object::{Object, This}; use object::class::Callback; -use self::internal::{ValueInternal, SuperType, FunctionCallback}; +use handle::{Handle, Managed}; +use handle::internal::SuperType; +use self::internal::{ValueInternal, FunctionCallback}; use self::utf8::Utf8; pub use self::binary::{JsBuffer, JsArrayBuffer, BinaryData, BinaryViewType}; pub use self::error::JsError; -pub use self::mem::{Handle, Managed, DowncastError, DowncastResult}; - -/// The result of a computation that produces a JS value and might send the JS engine into a throwing state. -pub type JsResult<'b, T> = NeonResult>; pub(crate) fn build<'a, T: Managed, F: FnOnce(&mut raw::Local) -> bool>(init: F) -> JsResult<'a, T> { unsafe { @@ -234,8 +231,8 @@ impl fmt::Display for StringOverflow { /// The result of constructing a new `JsString`. pub type StringResult<'a> = Result, StringOverflow>; -impl<'a> ResultExt<'a, JsString> for StringResult<'a> { - fn unwrap_or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, JsString> { +impl<'a> JsResultExt<'a, JsString> for StringResult<'a> { + fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, JsString> { match self { Ok(v) => Ok(v), Err(e) => cx.throw_range_error(&e.to_string()) diff --git a/src/value/utf8.rs b/src/types/utf8.rs similarity index 100% rename from src/value/utf8.rs rename to src/types/utf8.rs diff --git a/test/dynamic/native/src/js/functions.rs b/test/dynamic/native/src/js/functions.rs index 77bbe3e6f..351c6f400 100644 --- a/test/dynamic/native/src/js/functions.rs +++ b/test/dynamic/native/src/js/functions.rs @@ -14,16 +14,16 @@ pub fn call_js_function(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; let args: Vec> = vec![cx.number(16.0)]; let null = cx.null(); - f.call(&mut cx, null, args)?.downcast::().unwrap_or_throw(&mut cx) + f.call(&mut cx, null, args)?.downcast::().or_throw(&mut cx) } pub fn construct_js_function(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; let zero = cx.number(0.0); let o = f.construct(&mut cx, vec![zero])?; - let get_utc_full_year_method = o.get(&mut cx, "getUTCFullYear")?.downcast::().unwrap_or_throw(&mut cx)?; + let get_utc_full_year_method = o.get(&mut cx, "getUTCFullYear")?.downcast::().or_throw(&mut cx)?; let args: Vec> = vec![]; - get_utc_full_year_method.call(&mut cx, o.upcast::(), args)?.downcast::().unwrap_or_throw(&mut cx) + get_utc_full_year_method.call(&mut cx, o.upcast::(), args)?.downcast::().or_throw(&mut cx) } trait CheckArgument<'a> { @@ -62,7 +62,7 @@ pub fn return_this(mut cx: FunctionContext) -> JsResult { pub fn require_object_this(mut cx: FunctionContext) -> JsResult { let this = cx.this(); - let this = this.downcast::().unwrap_or_throw(&mut cx)?; + let this = this.downcast::().or_throw(&mut cx)?; let t = cx.boolean(true); this.set(&mut cx, "modified", t)?; Ok(cx.undefined()) diff --git a/test/static/tests/compile-fail/example_compile_error.rs b/test/static/tests/compile-fail/example_compile_error.rs index 8077e6713..002fc5988 100644 --- a/test/static/tests/compile-fail/example_compile_error.rs +++ b/test/static/tests/compile-fail/example_compile_error.rs @@ -1,6 +1,6 @@ extern crate neon; -use neon::value::JsNumber; +use neon::types::JsNumber; fn main() { JsNumber::new(cx, "9000")