diff --git a/crates/nanny-sys/src/lib.rs b/crates/nanny-sys/src/lib.rs index d88d49ed2..eef878459 100644 --- a/crates/nanny-sys/src/lib.rs +++ b/crates/nanny-sys/src/lib.rs @@ -5,6 +5,22 @@ use std::os::raw::c_void; use raw::{FunctionCallbackInfo, EscapableHandleScope, Isolate, Local}; use buf::Buf; +// analog C enum `tag_t` defined in nanny.h +#[repr(C)] +#[derive(PartialEq, Eq)] +pub enum Tag { + Null, + Undefined, + Boolean, + Integer, + Number, + String, + Object, + Array, + Function, + Other +} + extern "system" { pub fn Nan_FunctionCallbackInfo_SetReturnValue(info: &FunctionCallbackInfo, value: Local); pub fn Nan_FunctionCallbackInfo_GetIsolate(info: &FunctionCallbackInfo) -> &Isolate; @@ -30,6 +46,9 @@ extern "system" { pub fn Nan_NewArray(out: &mut Local, isolate: *mut Isolate, length: u32); pub fn Node_ArraySet(array: &mut Local, index: u32, value: Local) -> bool; pub fn Nan_Get_Index(out: &mut Local, object: &mut Local, index: u32) -> bool; + pub fn Nanny_Set_Index(out: &mut bool, object: &mut Local, index: u32, val: &mut Local) -> bool; + pub fn Nanny_Get_Bytes(out: &mut Local, object: &mut Local, key: *const u8, len: i32) -> bool; + pub fn Nanny_Set_Bytes(out: &mut bool, object: &mut Local, key: *const u8, len: i32, val: &mut Local) -> bool; pub fn Nan_Get(out: &mut Local, object: &mut Local, key: &mut Local) -> bool; pub fn Nan_Set(out: &mut bool, object: &mut Local, key: &mut Local, val: &Local) -> bool; pub fn Node_ArrayLength(array: &Local) -> u32; @@ -50,4 +69,19 @@ extern "system" { pub fn Nanny_FunctionKernel(obj: &Local) -> *mut c_void; pub fn Nanny_NewFunction(out: &mut Local, isolate: *mut c_void, callback: *mut c_void, kernel: *mut c_void) -> bool; + pub fn Nanny_TagOf(val: &Local) -> Tag; + pub fn Nanny_IsUndefined(val: &Local) -> bool; + pub fn Nanny_IsNull(val: &Local) -> bool; + pub fn Nanny_IsInteger(val: &Local) -> bool; + pub fn Nanny_IsNumber(val: &Local) -> bool; + pub fn Nanny_IsBoolean(val: &Local) -> bool; + pub fn Nanny_IsString(val: &Local) -> bool; + pub fn Nanny_IsObject(val: &Local) -> bool; + pub fn Nanny_IsArray(val: &Local) -> bool; + pub fn Nanny_IsFunction(val: &Local) -> bool; + pub fn Nanny_IsTypeError(val: &Local) -> bool; + + pub fn Nanny_ThrowAny(val: &Local); + pub fn Nanny_NewTypeError(out: &mut Local, msg: *const u8) -> bool; + pub fn Nanny_ThrowTypeError(msg: *const u8); } diff --git a/crates/nanny-sys/src/nanny.cc b/crates/nanny-sys/src/nanny.cc index 4e35f25d1..ce1ec543a 100644 --- a/crates/nanny-sys/src/nanny.cc +++ b/crates/nanny-sys/src/nanny.cc @@ -91,6 +91,34 @@ extern "C" bool Nan_Get_Index(v8::Local *out, v8::Local * return maybe.ToLocal(out); } +extern "C" bool Nanny_Set_Index(bool *out, v8::Local *object, uint32_t index, v8::Local *val) { + Nan::Maybe maybe = Nan::Set(*object, index, *val); + return maybe.IsJust() && (*out = maybe.FromJust(), true); +} + +extern "C" bool Nanny_Get_Bytes(v8::Local *out, v8::Local *obj, const uint8_t *data, int32_t len) { + Nan::HandleScope scope; + Nan::MaybeLocal maybe_key = v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), data, v8::NewStringType::kNormal, len); + v8::Local key; + if (!maybe_key.ToLocal(&key)) { + return false; + } + Nan::MaybeLocal maybe = Nan::Get(*obj, key); + return maybe.ToLocal(out); +} + +extern "C" bool Nanny_Set_Bytes(bool *out, v8::Local *obj, const uint8_t *data, int32_t len, v8::Local *val) { + // FIXME: abstract the key construction logic to avoid duplication with ^^ + Nan::HandleScope scope; + Nan::MaybeLocal maybe_key = v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), data, v8::NewStringType::kNormal, len); + v8::Local key; + if (!maybe_key.ToLocal(&key)) { + return false; + } + Nan::Maybe maybe = Nan::Set(*obj, key, *val); + return maybe.IsJust() && (*out = maybe.FromJust(), true); +} + extern "C" bool Nan_Get(v8::Local *out, v8::Local *obj, v8::Local *key) { Nan::MaybeLocal maybe = Nan::Get(*obj, *key); return maybe.ToLocal(out); @@ -190,3 +218,81 @@ extern "C" bool Nanny_NewFunction(v8::Local *out, v8::Isolate *iso extern "C" void *Nanny_FunctionKernel(v8::Local *obj) { return Nan::ObjectWrap::Unwrap(*obj)->GetKernel(); } + +extern "C" tag_t Nanny_TagOf(v8::Local *p) { + v8::Local val = *p; + return val->IsNull() ? tag_null + : val->IsUndefined() ? tag_undefined + : (val->IsTrue() || val->IsFalse()) ? tag_boolean + : (val->IsInt32() || val->IsUint32()) ? tag_integer // FIXME: this isn't right for large int64s + : val->IsNumber() ? tag_number + : val->IsString() ? tag_string + : val->IsArray() ? tag_array + : val->IsFunction() ? tag_function + : val->IsObject() ? tag_object + : tag_other; +} + +extern "C" bool Nanny_IsUndefined(v8::Local *p) { + v8::Local val = *p; + return val->IsUndefined(); +} + +extern "C" bool Nanny_IsNull(v8::Local *p) { + v8::Local val = *p; + return val->IsNull(); +} + +extern "C" bool Nanny_IsInteger(v8::Local *p) { + v8::Local val = *p; + return val->IsInt32() || val->IsUint32(); +} + +extern "C" bool Nanny_IsNumber(v8::Local *p) { + v8::Local val = *p; + return val->IsNumber(); +} + +extern "C" bool Nanny_IsBoolean(v8::Local *p) { + v8::Local val = *p; + return val->IsBoolean(); +} + +extern "C" bool Nanny_IsString(v8::Local *p) { + v8::Local val = *p; + return val->IsString(); +} + +extern "C" bool Nanny_IsObject(v8::Local *p) { + v8::Local val = *p; + // FIXME: is the null check superfluous? + return val->IsObject() && !val->IsNull(); +} + +extern "C" bool Nanny_IsArray(v8::Local *p) { + v8::Local val = *p; + return val->IsArray(); +} + +extern "C" bool Nanny_IsFunction(v8::Local *p) { + v8::Local val = *p; + return val->IsFunction(); +} + +extern "C" bool Nanny_IsTypeError(v8::Local *p) { + v8::Local val = *p; + return false; // FIXME: implement this +} + +extern "C" void Nanny_ThrowAny(v8::Local *val) { + Nan::ThrowError(*val); +} + +extern "C" bool Nanny_NewTypeError(v8::Local *out, const char *msg) { + *out = Nan::TypeError(msg); + return true; +} + +extern "C" void Nanny_ThrowTypeError(const char *msg) { + Nan::ThrowTypeError(msg); +} diff --git a/crates/nanny-sys/src/nanny.h b/crates/nanny-sys/src/nanny.h index 8397cc612..d358fd4a6 100644 --- a/crates/nanny-sys/src/nanny.h +++ b/crates/nanny-sys/src/nanny.h @@ -3,10 +3,24 @@ #include typedef struct { - void* data; - size_t len; + void* data; + size_t len; } buf_t; +// analog Rust enum `Tag` defined in lib.rs +typedef enum { + tag_null, + tag_undefined, + tag_boolean, + tag_integer, + tag_number, + tag_string, + tag_object, + tag_array, + tag_function, + tag_other +} tag_t; + extern "C" { void Nan_FunctionCallbackInfo_SetReturnValue(Nan::FunctionCallbackInfo *info, v8::Local value); @@ -35,6 +49,9 @@ extern "C" { bool Node_ArraySet(v8::Local *array, uint32_t index, v8::Local value); uint32_t Node_ArrayLength(v8::Local *array); bool Nan_Get_Index(v8::Local *out, v8::Local *object, uint32_t index); + bool Nanny_Set_Index(bool *out, v8::Local *object, uint32_t index, v8::Local *val); + bool Nanny_Get_Bytes(v8::Local *out, v8::Local *object, const uint8_t *key, int32_t len); + bool Nanny_Set_Bytes(bool *out, v8::Local *object, const uint8_t *key, int32_t len, v8::Local *val); bool Nan_Get(v8::Local *out, v8::Local *object, v8::Local *key); bool Nan_Set(bool *out, v8::Local *obj, v8::Local *key, v8::Local *val); @@ -61,4 +78,20 @@ extern "C" { bool Nanny_NewFunction(v8::Local *out, v8::Isolate *isolate, Nan::FunctionCallback callback, void *kernel); void *Nanny_FunctionKernel(v8::Local *obj); + + tag_t Nanny_TagOf(v8::Local *val); + bool Nanny_IsUndefined(v8::Local *val); + bool Nanny_IsNull(v8::Local *val); + bool Nanny_IsBoolean(v8::Local *val); + bool Nanny_IsInteger(v8::Local *val); + bool Nanny_IsNumber(v8::Local *val); + bool Nanny_IsString(v8::Local *val); + bool Nanny_IsObject(v8::Local *val); + bool Nanny_IsArray(v8::Local *val); + bool Nanny_IsFunction(v8::Local *val); + bool Nanny_IsTypeError(v8::Local *val); + + void Nanny_ThrowAny(v8::Local *val); + bool Nanny_NewTypeError(v8::Local *out, const char *msg); + void Nanny_ThrowTypeError(const char *msg); } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 000000000..a192c1c60 --- /dev/null +++ b/src/error.rs @@ -0,0 +1 @@ +pub use internal::error::{throw, TypeError}; diff --git a/src/internal/buffer.rs b/src/internal/buffer.rs index af7df5e2d..544165dcb 100644 --- a/src/internal/buffer.rs +++ b/src/internal/buffer.rs @@ -3,10 +3,11 @@ use std::str; use std::str::Utf8Error; use vm::Throw; -use internal::value::{Value, Object, ObjectInternal, Tagged, TaggedInternal}; +use internal::error::TypeError; +use internal::value::{SomeObject, Any, AnyInternal, Object, build}; use internal::mem::Handle; use nanny_sys::raw; -use nanny_sys::{Nan_NewBuffer, Node_Buffer_Data, Node_Buffer_Value_HasInstance, Node_Buffer_Object_HasInstance}; +use nanny_sys::{Nan_NewBuffer, Node_Buffer_Data, Node_Buffer_Value_HasInstance}; use scope::Scope; use nanny_sys::buf::Buf; @@ -28,8 +29,8 @@ impl IndexMut for Buffer { } impl Buffer { - pub fn new<'a, T: Scope<'a>>(_: &mut T, size: u32) -> Option> { - Object::build_opt(|out| { unsafe { Nan_NewBuffer(out, size) } }) + pub fn new<'a, T: Scope<'a>>(_: &mut T, size: u32) -> Result, Throw> { + build(|out| { unsafe { Nan_NewBuffer(out, size) } }) } pub fn data(&self) -> Buf { @@ -46,40 +47,12 @@ impl Buffer { pub fn check_str(&self) -> Result<&str, Throw> { self.as_str().map_err(|_| { - // FIXME: throw a type error - Throw + TypeError::throw::<()>("buffer contents are invalid UTF-8").err().unwrap() }) } } -impl Value { - pub fn as_buffer<'a, T: Scope<'a>>(&self, _: &mut T) -> Option> { - if unsafe { Node_Buffer_Value_HasInstance(self.to_raw_ref()) } { - Some(self.cast(Buffer)) - } else { - None - } - } -} - -impl Object { - pub fn as_buffer<'a, T: Scope<'a>>(&self, _: &mut T) -> Option> { - if unsafe { Node_Buffer_Object_HasInstance(self.to_raw_ref()) } { - Some(self.cast(Buffer)) - } else { - None - } - } - - pub fn check_buffer<'a, T: Scope<'a>>(&self, scope: &mut T) -> Result, Throw> { - self.as_buffer(scope).ok_or_else(|| { - // FIXME: throw a type error - Throw - }) - } -} - -impl TaggedInternal for Buffer { +impl AnyInternal for Buffer { fn to_raw_mut_ref(&mut self) -> &mut raw::Local { let &mut Buffer(ref mut local) = self; local @@ -89,6 +62,14 @@ impl TaggedInternal for Buffer { let &Buffer(ref local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Buffer(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Node_Buffer_Value_HasInstance(other.to_raw_ref()) } + } } -impl Tagged for Buffer { } +impl Any for Buffer { } + +impl Object for Buffer { } diff --git a/src/internal/error.rs b/src/internal/error.rs new file mode 100644 index 000000000..8733c1238 --- /dev/null +++ b/src/internal/error.rs @@ -0,0 +1,63 @@ +use std::mem; +use std::ffi::CString; + +use nanny_sys::{Nanny_ThrowAny, Nanny_NewTypeError, Nanny_IsTypeError, Nanny_ThrowTypeError}; +use nanny_sys::raw; + +use internal::vm::{Throw, Result}; +use internal::value::{SomeObject, Any, AnyInternal, Object, build}; +use internal::mem::Handle; +use scope::Scope; + +pub fn throw<'a, T: Any, U>(v: Handle<'a, T>) -> Result { + unsafe { + Nanny_ThrowAny(v.to_raw_ref()); + } + Err(Throw) +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct TypeError(raw::Local); + +impl AnyInternal for TypeError { + fn to_raw_mut_ref(&mut self) -> &mut raw::Local { + let &mut TypeError(ref mut local) = self; + local + } + + fn to_raw_ref(&self) -> &raw::Local { + let &TypeError(ref local) = self; + local + } + + fn from_raw(h: raw::Local) -> Self { TypeError(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsTypeError(other.to_raw_ref()) } + } +} + +impl Any for TypeError { } + +impl Object for TypeError { } + +fn message(msg: &str) -> CString { + CString::new(msg).ok().unwrap_or_else(|| { CString::new("").ok().unwrap() }) +} + +impl TypeError { + // FIXME: use an overload trait to allow either &str or value::String + pub fn new<'a, T: Scope<'a>>(_: &mut T, msg: &str) -> Result> { + let msg = &message(msg); + build(|out| { unsafe { Nanny_NewTypeError(out, mem::transmute(msg.as_ptr())) } }) + } + + pub fn throw(msg: &str) -> Result { + let msg = &message(msg); + unsafe { + Nanny_ThrowTypeError(mem::transmute(msg.as_ptr())); + } + Err(Throw) + } +} diff --git a/src/internal/mem.rs b/src/internal/mem.rs index 7a39c3dc2..d386f59ad 100644 --- a/src/internal/mem.rs +++ b/src/internal/mem.rs @@ -1,21 +1,23 @@ use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use nanny_sys::raw; -use internal::value::{Tagged, TaggedInternal, Value, ValueInternal}; +use internal::value::{Any, AnyInternal, SuperType}; +use internal::error::TypeError; +use internal::vm::JS; #[repr(C)] #[derive(Clone, Copy)] -pub struct Handle<'a, T: Tagged + 'a> { +pub struct Handle<'a, T: Any + 'a> { value: T, phantom: PhantomData<&'a T> } -pub trait HandleInternal<'a, T: Tagged + 'a> { +pub trait HandleInternal<'a, T: Any + 'a> { fn new(value: T) -> Handle<'a, T>; fn to_raw_mut_ref(&mut self) -> &mut raw::Local; } -impl<'a, T: Tagged + 'a> HandleInternal<'a, T> for Handle<'a, T> { +impl<'a, T: Any + 'a> HandleInternal<'a, T> for Handle<'a, T> { fn new(value: T) -> Handle<'a, T> { Handle { value: value, @@ -32,20 +34,34 @@ impl<'a, T: Tagged + 'a> HandleInternal<'a, T> for Handle<'a, T> { } } -impl<'a, T: Tagged> Handle<'a, T> { - pub fn upcast(&self) -> Handle<'a, Value> { - Value::new_internal(self.value.to_raw()) +impl<'a, T: Any> Handle<'a, T> { + // This method does not require a scope because it only copies a handle. + pub fn upcast>(&self) -> Handle<'a, U> { + Handle::new(SuperType::upcast_internal(self.value)) } } -impl<'a, T: Tagged> Deref for Handle<'a, T> { +impl<'a, T: Any> Handle<'a, T> { + pub fn downcast(&self) -> Option> { + U::downcast(self.value).map(Handle::new) + } + + pub fn check(&self) -> JS<'a, U> { + match U::downcast(self.value) { + Some(v) => Ok(Handle::new(v)), + None => TypeError::throw("type error") + } + } +} + +impl<'a, T: Any> Deref for Handle<'a, T> { type Target = T; fn deref<'b>(&'b self) -> &'b T { &self.value } } -impl<'a, T: Tagged> DerefMut for Handle<'a, T> { +impl<'a, T: Any> DerefMut for Handle<'a, T> { fn deref_mut<'b>(&'b mut self) -> &'b mut T { &mut self.value } diff --git a/src/internal/mod.rs b/src/internal/mod.rs index a9d2ab6e9..42ecfefa5 100644 --- a/src/internal/mod.rs +++ b/src/internal/mod.rs @@ -3,3 +3,4 @@ pub mod value; pub mod mem; pub mod buffer; pub mod vm; +pub mod error; diff --git a/src/internal/scope.rs b/src/internal/scope.rs index 131d25b86..62854fceb 100644 --- a/src/internal/scope.rs +++ b/src/internal/scope.rs @@ -5,7 +5,7 @@ use std::cell::{RefCell, UnsafeCell}; use nanny_sys::raw; use nanny_sys::{Nan_Nested, Nan_Chained, Nan_EscapableHandleScope_Escape}; use internal::mem::{Handle, HandleInternal}; -use internal::value::Tagged; +use internal::value::Any; use internal::vm::Isolate; pub trait ScopeInternal: Sized { @@ -45,7 +45,7 @@ pub struct ChainedScope<'a, 'outer> { } impl<'a, 'outer> ChainedScope<'a, 'outer> { - pub fn escape(&self, local: Handle<'a, T>) -> Handle<'outer, T> { + pub fn escape(&self, local: Handle<'a, T>) -> Handle<'outer, T> { let result: UnsafeCell> = UnsafeCell::new(Handle::new(unsafe { mem::zeroed() })); unsafe { Nan_EscapableHandleScope_Escape((*result.get()).to_raw_mut_ref(), self.v8, local.to_raw()); diff --git a/src/internal/value.rs b/src/internal/value.rs index a3ab62249..4fa6dc6a2 100644 --- a/src/internal/value.rs +++ b/src/internal/value.rs @@ -2,12 +2,12 @@ use std::mem; use std::os::raw::c_void; use std::ffi::{CString, CStr}; use nanny_sys::raw; -use nanny_sys::{Nan_NewObject, Nan_NewUndefined, Nan_NewNull, Nan_NewBoolean, Nan_NewInteger, Nan_NewString, Nan_NewNumber, Nan_NewArray, Node_ArraySet, Node_ArrayLength, Nan_String_Utf8Length, Nan_Value_ToString, Nan_Value_ToObject, Nan_GetOwnPropertyNames, Nan_Get_Index, Nan_Get, Nan_Set, Nanny_NewFunction, Nanny_FunctionKernel, Nan_FunctionCallbackInfo_GetIsolate}; +use nanny_sys::{Nan_NewObject, Nan_NewUndefined, Nan_NewNull, Nan_NewBoolean, Nan_NewInteger, Nan_NewString, Nan_NewNumber, Nan_NewArray, Node_ArrayLength, Nan_String_Utf8Length, Nan_Value_ToString, Nan_GetOwnPropertyNames, Nan_Get_Index, Nanny_Set_Index, Nan_Get, Nanny_Get_Bytes, Nanny_Set_Bytes, Nan_Set, Nanny_NewFunction, Nanny_FunctionKernel, Nan_FunctionCallbackInfo_GetIsolate, Nanny_IsUndefined, Nanny_IsNull, Nanny_IsInteger, Nanny_IsNumber, Nanny_IsString, Nanny_IsBoolean, Nanny_IsObject, Nanny_IsArray, Nanny_IsFunction, Nanny_TagOf, Tag}; use internal::mem::{Handle, HandleInternal}; use internal::scope::{Scope, RootScope, RootScopeInternal}; use internal::vm::{Result, Throw, JS, Isolate, CallbackInfo, Call, exec_function_body}; -pub trait TaggedInternal: Copy { +pub trait AnyInternal: Copy { fn to_raw_mut_ref(&mut self) -> &mut raw::Local; fn to_raw_ref(&self) -> &raw::Local; @@ -16,32 +16,85 @@ pub trait TaggedInternal: Copy { self.to_raw_ref().clone() } - fn cast<'a, 'b, T: Tagged, F: FnOnce(raw::Local) -> T>(&'a self, f: F) -> Handle<'b, T> { + fn is_typeof(other: Other) -> bool; + + fn downcast(other: Other) -> Option { + if Self::is_typeof(other) { + Some(Self::from_raw(other.to_raw())) + } else { + None + } + } + + fn cast<'a, 'b, T: Any, F: FnOnce(raw::Local) -> T>(&'a self, f: F) -> Handle<'b, T> { Handle::new(f(self.to_raw_ref().clone())) } + + fn from_raw(h: raw::Local) -> Self; } -pub trait Tagged: TaggedInternal { - fn to_string<'a, T: Scope<'a>>(&mut self, _: &mut T) -> JS<'a, String> { - // FIXME: String could use a build_opt abstraction too - unsafe { - let mut result = Handle::new(String(mem::zeroed())); - if Nan_Value_ToString(result.to_raw_mut_ref(), self.to_raw_mut_ref()) { - Ok(result) - } else { - Err(Throw) - } +pub unsafe fn zeroed<'a, T: Any>() -> Handle<'a, T> { + Handle::new(T::from_raw(mem::zeroed())) +} + +pub fn build<'a, T: Any, F: FnOnce(&mut raw::Local) -> bool>(init: F) -> JS<'a, T> { + unsafe { + let mut result = zeroed::(); + if init(result.to_raw_mut_ref()) { + Ok(result) + } else { + Err(Throw) } } } +pub trait SuperType { + fn upcast_internal(T) -> Self; +} + +impl SuperType for Value { + fn upcast_internal(v: T) -> Value { + Value(v.to_raw()) + } +} + +impl SuperType for SomeObject { + fn upcast_internal(v: T) -> SomeObject { + SomeObject(v.to_raw()) + } +} + +pub trait Any: AnyInternal { + fn to_string<'a, T: Scope<'a>>(&mut self, _: &mut T) -> JS<'a, String> { + build(|out| { unsafe { Nan_Value_ToString(out, self.to_raw_mut_ref()) } }) + } + + fn value<'a, T: Scope<'a>>(&self, _: &mut T) -> Handle<'a, Value> { + Value::new_internal(self.to_raw()) + } +} + +pub enum Variant<'a> { + Null(Handle<'a, Null>), + Undefined(Handle<'a, Undefined>), + Boolean(Handle<'a, Boolean>), + Integer(Handle<'a, Integer>), + Number(Handle<'a, Number>), + String(Handle<'a, String>), + Object(Handle<'a, SomeObject>), + Array(Handle<'a, Array>), + Function(Handle<'a, Function>), + Other(Handle<'a, Value>) +} + + #[repr(C)] #[derive(Clone, Copy)] pub struct Value(raw::Local); -impl Tagged for Value { } +impl Any for Value { } -impl TaggedInternal for Value { +impl AnyInternal for Value { fn to_raw_ref(&self) -> &raw::Local { let &Value(ref local) = self; local @@ -51,35 +104,39 @@ impl TaggedInternal for Value { let &mut Value(ref mut local) = self; local } -} -impl Value { - pub fn as_object<'a, T: Scope<'a>>(&self, _: &mut T) -> Option> { - Object::build_opt(|out| { unsafe { Nan_Value_ToObject(out, self.to_raw_ref()) } }) + fn from_raw(h: raw::Local) -> Self { Value(h) } + + fn is_typeof(_: Other) -> bool { + true } +} - pub fn check_object<'a, T: Scope<'a>>(&self, _: &mut T) -> JS<'a, Object> { - Object::build_opt(|out| { unsafe { Nan_Value_ToObject(out, self.to_raw_ref()) } }) - .ok_or_else(|| { - // FIXME: throw a type error - Throw - }) +impl<'a> Handle<'a, Value> { + pub fn variant(&self) -> Variant<'a> { + match unsafe { Nanny_TagOf(self.to_raw_ref()) } { + Tag::Null => Variant::Null(Null::new()), + Tag::Undefined => Variant::Undefined(Undefined::new()), + Tag::Boolean => Variant::Boolean(Handle::new(Boolean(self.to_raw()))), + Tag::Integer => Variant::Integer(Handle::new(Integer(self.to_raw()))), + Tag::Number => Variant::Number(Handle::new(Number(self.to_raw()))), + Tag::String => Variant::String(Handle::new(String(self.to_raw()))), + Tag::Object => Variant::Object(Handle::new(SomeObject(self.to_raw()))), + Tag::Array => Variant::Array(Handle::new(Array(self.to_raw()))), + Tag::Function => Variant::Function(Handle::new(Function(self.to_raw()))), + Tag::Other => Variant::Other(self.clone()) + } } } pub trait ValueInternal { fn new_internal<'a>(value: raw::Local) -> Handle<'a, Value>; - unsafe fn zero_internal<'a>() -> Handle<'a, Value>; } impl ValueInternal for Value { fn new_internal<'a>(value: raw::Local) -> Handle<'a, Value> { Handle::new(Value(value)) } - - unsafe fn zero_internal<'a>() -> Handle<'a, Value> { - Handle::new(Value(mem::zeroed())) - } } #[repr(C)] @@ -87,14 +144,14 @@ impl ValueInternal for Value { pub struct Undefined(raw::Local); impl Undefined { - pub fn new<'a, T: Scope<'a>>(_: &mut T) -> Handle<'a, Undefined> { + pub fn new<'a>() -> Handle<'a, Undefined> { Undefined::new_internal() } } -impl Tagged for Undefined { } +impl Any for Undefined { } -impl TaggedInternal for Undefined { +impl AnyInternal for Undefined { fn to_raw_ref(&self) -> &raw::Local { let &Undefined(ref local) = self; local @@ -104,6 +161,12 @@ impl TaggedInternal for Undefined { let &mut Undefined(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Undefined(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsUndefined(other.to_raw_ref()) } + } } pub trait UndefinedInternal { @@ -112,7 +175,7 @@ pub trait UndefinedInternal { impl UndefinedInternal for Undefined { fn new_internal<'a>() -> Handle<'a, Undefined> { - let mut result = Handle::new(Undefined(unsafe { mem::zeroed() })); + let mut result = unsafe { zeroed::() }; unsafe { Nan_NewUndefined(result.to_raw_mut_ref()); } @@ -125,14 +188,14 @@ impl UndefinedInternal for Undefined { pub struct Null(raw::Local); impl Null { - pub fn new<'a, T: Scope<'a>>(_: &mut T) -> Handle<'a, Null> { + pub fn new<'a>() -> Handle<'a, Null> { Null::new_internal() } } -impl Tagged for Null { } +impl Any for Null { } -impl TaggedInternal for Null { +impl AnyInternal for Null { fn to_raw_ref(&self) -> &raw::Local { let &Null(ref local) = self; local @@ -142,6 +205,12 @@ impl TaggedInternal for Null { let &mut Null(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Null(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsNull(other.to_raw_ref()) } + } } pub trait NullInternal { @@ -150,7 +219,7 @@ pub trait NullInternal { impl NullInternal for Null { fn new_internal<'a>() -> Handle<'a, Null> { - let mut result = Handle::new(Null(unsafe { mem::zeroed() })); + let mut result = unsafe { zeroed::() }; unsafe { Nan_NewNull(result.to_raw_mut_ref()); } @@ -168,9 +237,9 @@ impl Boolean { } } -impl Tagged for Boolean { } +impl Any for Boolean { } -impl TaggedInternal for Boolean { +impl AnyInternal for Boolean { fn to_raw_ref(&self) -> &raw::Local { let &Boolean(ref local) = self; local @@ -180,6 +249,12 @@ impl TaggedInternal for Boolean { let &mut Boolean(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Boolean(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsBoolean(other.to_raw_ref()) } + } } pub trait BooleanInternal { @@ -188,7 +263,7 @@ pub trait BooleanInternal { impl BooleanInternal for Boolean { fn new_internal<'a>(b: bool) -> Handle<'a, Boolean> { - let mut result = Handle::new(Boolean(unsafe { mem::zeroed() })); + let mut result = unsafe { zeroed::() }; unsafe { Nan_NewBoolean(result.to_raw_mut_ref(), b); } @@ -200,9 +275,9 @@ impl BooleanInternal for Boolean { #[derive(Clone, Copy)] pub struct String(raw::Local); -impl Tagged for String { } +impl Any for String { } -impl TaggedInternal for String { +impl AnyInternal for String { fn to_raw_ref(&self) -> &raw::Local { let &String(ref local) = self; local @@ -212,6 +287,12 @@ impl TaggedInternal for String { let &mut String(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { String(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsString(other.to_raw_ref()) } + } } impl String { @@ -230,13 +311,39 @@ pub trait StringInternal { fn new_internal<'a>(isolate: *mut Isolate, val: &CStr) -> Option>; } +// Lower a &CStr to the types expected by Node: a const *uint8_t buffer and an int32_t length. +fn lower_cstr(cs: &CStr) -> Option<(*const u8, i32)> { + // V8 currently refuses to allocate strings longer than `(1 << 20) - 16` bytes, + // but in case this changes over time, just ensure the buffer isn't longer than + // the largest positive signed integer, and delegate the tighter bounds checks + // to V8. + let len = cs.to_bytes().len(); + if len > (::std::i32::MAX as usize) { + return None; + } + Some((unsafe { mem::transmute(cs.as_ptr()) }, len as i32)) +} + +fn lower_cstr_unwrap(cs: &CStr) -> (*const u8, i32) { + lower_cstr(cs).unwrap_or_else(|| { + panic!("{} < i32::MAX", cs.to_bytes().len()) + }) +} + +fn lower_str_unwrap(s: &str) -> (*const u8, i32) { + lower_cstr_unwrap(&CString::new(s).ok().unwrap()) +} + impl StringInternal for String { fn new_internal<'a>(isolate: *mut Isolate, val: &CStr) -> Option> { + let (ptr, len) = match lower_cstr(val) { + Some(pair) => pair, + None => { return None; } + }; unsafe { - let mut result = Handle::new(String(mem::zeroed())); + let mut result = zeroed::(); // FIXME: this is currently traversing the string twice (see the note in the CStr::as_ptr docs) - // FIXME: range check on length? - if Nan_NewString(result.to_raw_mut_ref(), mem::transmute(isolate), mem::transmute(val.as_ptr()), val.to_bytes().len() as i32) { + if Nan_NewString(result.to_raw_mut_ref(), mem::transmute(isolate), ptr, len) { Some(result) } else { None @@ -256,9 +363,9 @@ impl Integer { } } -impl Tagged for Integer { } +impl Any for Integer { } -impl TaggedInternal for Integer { +impl AnyInternal for Integer { fn to_raw_ref(&self) -> &raw::Local { let &Integer(ref local) = self; local @@ -268,6 +375,12 @@ impl TaggedInternal for Integer { let &mut Integer(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Integer(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsInteger(other.to_raw_ref()) } + } } pub trait IntegerInternal { @@ -276,7 +389,7 @@ pub trait IntegerInternal { impl IntegerInternal for Integer { fn new_internal<'a>(isolate: *mut Isolate, i: i32) -> Handle<'a, Integer> { - let mut result = Handle::new(Integer(unsafe { mem::zeroed() })); + let mut result = unsafe { zeroed::() }; unsafe { Nan_NewInteger(result.to_raw_mut_ref(), mem::transmute(isolate), i); } @@ -294,9 +407,9 @@ impl Number { } } -impl Tagged for Number { } +impl Any for Number { } -impl TaggedInternal for Number { +impl AnyInternal for Number { fn to_raw_ref(&self) -> &raw::Local { let &Number(ref local) = self; local @@ -306,6 +419,12 @@ impl TaggedInternal for Number { let &mut Number(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Number(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsNumber(other.to_raw_ref()) } + } } pub trait NumberInternal { @@ -314,7 +433,7 @@ pub trait NumberInternal { impl NumberInternal for Number { fn new_internal<'a>(isolate: *mut Isolate, v: f64) -> Handle<'a, Number> { - let mut result = Handle::new(Number(unsafe { mem::zeroed() })); + let mut result = unsafe { zeroed::() }; unsafe { Nan_NewNumber(result.to_raw_mut_ref(), mem::transmute(isolate), v); } @@ -324,100 +443,77 @@ impl NumberInternal for Number { #[repr(C)] #[derive(Clone, Copy)] -pub struct Object(raw::Local); +pub struct SomeObject(raw::Local); -impl Object { - // FIXME: shouldn't this be fallible? - pub fn new<'a, T: Scope<'a>>(_: &mut T) -> Handle<'a, Object> { - Object::new_internal() - } - - pub fn get_own_property_names<'a, T: Scope<'a>>(&self, _: &mut T) -> JS<'a, Array> { - // FIXME: Array could use a build_opt abstraction too - unsafe { - let mut result = Handle::new(Array(mem::zeroed())); - if Nan_GetOwnPropertyNames(result.to_raw_mut_ref(), self.to_raw_ref()) { - Ok(result) - } else { - Err(Throw) - } - } - } -} +impl Any for SomeObject { } -impl Tagged for Object { } - -impl TaggedInternal for Object { +impl AnyInternal for SomeObject { fn to_raw_ref(&self) -> &raw::Local { - let &Object(ref local) = self; + let &SomeObject(ref local) = self; local } fn to_raw_mut_ref(&mut self) -> &mut raw::Local { - let &mut Object(ref mut local) = self; + let &mut SomeObject(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { SomeObject(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsObject(other.to_raw_ref()) } + } } -pub trait ObjectInternal { - fn new_internal<'a>() -> Handle<'a, Object>; - unsafe fn zero_internal<'a>() -> Handle<'a, Object>; - fn build<'a, F: FnOnce(&mut raw::Local)>(init: F) -> Handle<'a, Object>; - fn build_opt<'a, F: FnOnce(&mut raw::Local) -> bool>(init: F) -> Option>; +trait PropertyName { + unsafe fn get(self, out: &mut raw::Local, obj: &mut raw::Local) -> bool; + unsafe fn set(self, out: &mut bool, key: &mut raw::Local, val: &mut raw::Local) -> bool; } -impl ObjectInternal for Object { - unsafe fn zero_internal<'a>() -> Handle<'a, Object> { - Handle::new(Object(mem::zeroed())) +impl PropertyName for u32 { + unsafe fn get(self, out: &mut raw::Local, obj: &mut raw::Local) -> bool { + Nan_Get_Index(out, obj, self) } - fn new_internal<'a>() -> Handle<'a, Object> { - Object::build(|out| { unsafe { Nan_NewObject(out) } }) + unsafe fn set(self, out: &mut bool, obj: &mut raw::Local, val: &mut raw::Local) -> bool { + Nanny_Set_Index(out, obj, self, val) } +} - fn build<'a, F: FnOnce(&mut raw::Local)>(init: F) -> Handle<'a, Object> { - unsafe { - let mut result = Object::zero_internal(); - init(result.to_raw_mut_ref()); - result - } +impl<'a, K: Any> PropertyName for Handle<'a, K> { + unsafe fn get(mut self, out: &mut raw::Local, obj: &mut raw::Local) -> bool { + Nan_Get(out, obj, self.to_raw_mut_ref()) } - fn build_opt<'a, F: FnOnce(&mut raw::Local) -> bool>(init: F) -> Option> { - unsafe { - let mut result = Object::zero_internal(); - if init(result.to_raw_mut_ref()) { - Some(result) - } else { - None - } - } + unsafe fn set(mut self, out: &mut bool, obj: &mut raw::Local, val: &mut raw::Local) -> bool { + Nan_Set(out, obj, self.to_raw_mut_ref(), val) } } +impl<'a> PropertyName for &'a str { + unsafe fn get(self, out: &mut raw::Local, obj: &mut raw::Local) -> bool { + let (ptr, len) = lower_str_unwrap(self); + Nanny_Get_Bytes(out, obj, ptr, len) + } -impl Object { - // FIXME: make get/set overloadable with a `PropertyName` trait that has private unsafe get/set methods - // FIXME: make it generic instead of Value - pub fn get<'a, T: Scope<'a>, K: Tagged>(&mut self, _: &mut T, mut key: Handle) -> JS<'a, Value> { - unsafe { - // FIXME: could use a Value build_opt - let mut result = Value::zero_internal(); - if Nan_Get(result.to_raw_mut_ref(), self.to_raw_mut_ref(), key.to_raw_mut_ref()) { - Ok(result) - } else { - Err(Throw) - } - } + unsafe fn set(self, out: &mut bool, obj: &mut raw::Local, val: &mut raw::Local) -> bool { + let (ptr, len) = lower_str_unwrap(self); + Nanny_Set_Bytes(out, obj, ptr, len, val) + } +} + +pub trait Object: Any { + fn get<'a, T: Scope<'a>, K: PropertyName>(&mut self, _: &mut T, key: K) -> Result> { + build(|out| { unsafe { key.get(out, self.to_raw_mut_ref()) } }) } - // FIXME: overloadable with a `PropertyName` trait - // FIXME: make it generic instead of Value - // FIXME: kill the scope argument here? - pub fn set<'a, T: Scope<'a>, V: Tagged>(&mut self, scope: &mut T, key: &str, val: Handle) -> Result { - let mut key = try!(String::new(scope, key).ok_or(Throw)); + fn get_own_property_names<'a, T: Scope<'a>>(&self, _: &mut T) -> JS<'a, Array> { + build(|out| { unsafe { Nan_GetOwnPropertyNames(out, self.to_raw_ref()) } }) + } + + fn set(&mut self, key: K, mut val: Handle) -> Result { let mut result = false; - if unsafe { Nan_Set(&mut result, self.to_raw_mut_ref(), key.to_raw_mut_ref(), val.to_raw_ref()) } { + if unsafe { key.set(&mut result, self.to_raw_mut_ref(), val.to_raw_mut_ref()) } { Ok(result) } else { Err(Throw) @@ -425,7 +521,33 @@ impl Object { } } -// FIXME: replace `upcast` with infallible to_object, to_value methods +impl Object for SomeObject { } + +pub trait SomeObjectInternal { + fn new_internal<'a>() -> Handle<'a, SomeObject>; + fn build<'a, F: FnOnce(&mut raw::Local)>(init: F) -> Handle<'a, SomeObject>; +} + +impl SomeObjectInternal for SomeObject { + fn new_internal<'a>() -> Handle<'a, SomeObject> { + SomeObject::build(|out| { unsafe { Nan_NewObject(out) } }) + } + + fn build<'a, F: FnOnce(&mut raw::Local)>(init: F) -> Handle<'a, SomeObject> { + unsafe { + let mut result = zeroed::(); + init(result.to_raw_mut_ref()); + result + } + } +} + + +impl SomeObject { + pub fn new<'a, T: Scope<'a>>(_: &mut T) -> Handle<'a, SomeObject> { + SomeObject::new_internal() + } +} #[repr(C)] #[derive(Clone, Copy)] @@ -437,9 +559,9 @@ impl Array { } } -impl Tagged for Array { } +impl Any for Array { } -impl TaggedInternal for Array { +impl AnyInternal for Array { fn to_raw_ref(&self) -> &raw::Local { let &Array(ref local) = self; local @@ -449,6 +571,12 @@ impl TaggedInternal for Array { let &mut Array(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Array(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsArray(other.to_raw_ref()) } + } } pub trait ArrayInternal { @@ -457,7 +585,7 @@ pub trait ArrayInternal { impl ArrayInternal for Array { fn new_internal<'a>(isolate: *mut Isolate, len: u32) -> Handle<'a, Array> { - let mut result = Handle::new(Array(unsafe { mem::zeroed() })); + let mut result = unsafe { zeroed::() }; unsafe { Nan_NewArray(result.to_raw_mut_ref(), mem::transmute(isolate), len); } @@ -466,24 +594,6 @@ impl ArrayInternal for Array { } impl Array { - pub fn set<'a, T: Tagged>(&mut self, index: u32, value: Handle<'a, T>) -> bool { - unsafe { - Node_ArraySet(self.to_raw_mut_ref(), index, value.to_raw()) - } - } - - pub fn get_index<'a, T: Scope<'a>>(&mut self, _: &mut T, index: u32) -> Option> { - unsafe { - // FIXME: could use a Value build_opt - let mut result = Value::zero_internal(); - if Nan_Get_Index(result.to_raw_mut_ref(), self.to_raw_mut_ref(), index) { - Some(result) - } else { - None - } - } - } - pub fn to_vec<'a, T: Scope<'a>>(&mut self, scope: &mut T) -> Result>> { let mut result = Vec::with_capacity(self.len() as usize); let mut i = 0; @@ -493,10 +603,7 @@ impl Array { if i >= self.len() { return Ok(result); } - match self.get_index(scope, i) { - Some(val) => { result.push(val); } - None => { return Err(Throw); } - } + result.push(try!(self.get(scope, i))); i += 1; } } @@ -508,38 +615,27 @@ impl Array { } } +impl Object for Array { } + #[repr(C)] #[derive(Clone, Copy)] pub struct Function(raw::Local); impl Function { - pub fn new<'a, T: Scope<'a>, U: Tagged>(scope: &mut T, f: fn(Call) -> JS) -> Option> { - unsafe { - let mut result = Function::zero_internal(); - let isolate: *mut c_void = mem::transmute(scope.isolate()); - let callback: extern "C" fn(&CallbackInfo) = invoke_nanny_function::; - let callback: *mut c_void = mem::transmute(callback); - let kernel: *mut c_void = mem::transmute(f); - if Nanny_NewFunction(result.to_raw_mut_ref(), isolate, callback, kernel) { - Some(result) - } else { - None + pub fn new<'a, T: Scope<'a>, U: Any>(scope: &mut T, f: fn(Call) -> JS) -> JS<'a, Function> { + build(|out| { + unsafe { + let isolate: *mut c_void = mem::transmute(scope.isolate()); + let callback: extern "C" fn(&CallbackInfo) = invoke_nanny_function::; + let callback: *mut c_void = mem::transmute(callback); + let kernel: *mut c_void = mem::transmute(f); + Nanny_NewFunction(out, isolate, callback, kernel) } - } + }) } } -pub trait FunctionInternal { - unsafe fn zero_internal<'a>() -> Handle<'a, Function>; -} - -impl FunctionInternal for Function { - unsafe fn zero_internal<'a>() -> Handle<'a, Function> { - Handle::new(Function(mem::zeroed())) - } -} - -extern "C" fn invoke_nanny_function(info: &CallbackInfo) { +extern "C" fn invoke_nanny_function(info: &CallbackInfo) { let mut scope = RootScope::new(unsafe { mem::transmute(Nan_FunctionCallbackInfo_GetIsolate(mem::transmute(info))) }); exec_function_body(info, &mut scope, |call| { let data = info.data(); @@ -550,9 +646,9 @@ extern "C" fn invoke_nanny_function(info: &CallbackInfo) { }); } -impl Tagged for Function { } +impl Any for Function { } -impl TaggedInternal for Function { +impl AnyInternal for Function { fn to_raw_ref(&self) -> &raw::Local { let &Function(ref local) = self; local @@ -562,4 +658,10 @@ impl TaggedInternal for Function { let &mut Function(ref mut local) = self; local } + + fn from_raw(h: raw::Local) -> Self { Function(h) } + + fn is_typeof(other: Other) -> bool { + unsafe { Nanny_IsFunction(other.to_raw_ref()) } + } } diff --git a/src/internal/vm.rs b/src/internal/vm.rs index b5be6a6dd..f47336031 100644 --- a/src/internal/vm.rs +++ b/src/internal/vm.rs @@ -4,7 +4,7 @@ use std::os::raw::c_void; use nanny_sys::raw; use nanny_sys::{Nanny_ExecFunctionBody, Nanny_ExecModuleBody, Nan_FunctionCallbackInfo_Data, Nan_FunctionCallbackInfo_SetReturnValue, Nan_FunctionCallbackInfo_Get, Nan_FunctionCallbackInfo_Length, Nan_Object_GetIsolate, Nan_FunctionCallbackInfo_IsConstructCall, Nan_FunctionCallbackInfo_This, Nan_FunctionCallbackInfo_Callee}; use internal::scope::{Scope, RootScope, RootScopeInternal}; -use internal::value::{Value, ValueInternal, Tagged, TaggedInternal, Object, ObjectInternal, Function, FunctionInternal}; +use internal::value::{Value, Any, AnyInternal, Object, SomeObject, Function, zeroed}; use internal::mem::{Handle, HandleInternal}; pub struct Throw; @@ -22,13 +22,13 @@ pub struct CallbackInfo { impl CallbackInfo { pub fn data<'a>(&self) -> Handle<'a, Value> { unsafe { - let mut result = Value::zero_internal(); + let mut result = zeroed::(); Nan_FunctionCallbackInfo_Data(&self.info, result.to_raw_mut_ref()); result } } - pub fn set_return<'a, 'b, T: Tagged>(&'a self, value: Handle<'b, T>) { + pub fn set_return<'a, 'b, T: Any>(&'a self, value: Handle<'b, T>) { unsafe { Nan_FunctionCallbackInfo_SetReturnValue(&self.info, value.to_raw()) } @@ -36,12 +36,12 @@ impl CallbackInfo { } pub struct Module<'a> { - pub exports: &'a mut Handle<'a, Object>, + pub exports: &'a mut Handle<'a, SomeObject>, pub scope: &'a mut RootScope<'a> } impl<'a> Module<'a> { - pub fn initialize(exports: &mut Handle, init: fn(Module) -> Result<()>) { + pub fn initialize(exports: &mut Handle, init: fn(Module) -> Result<()>) { let mut scope = RootScope::new(unsafe { mem::transmute(Nan_Object_GetIsolate(exports.to_raw_ref())) }); unsafe { let kernel: *mut c_void = mem::transmute(init); @@ -54,14 +54,14 @@ impl<'a> Module<'a> { } impl<'a> Module<'a> { - pub fn export(&mut self, key: &str, f: fn(Call) -> JS) -> Result<()> { - let value = try!(Function::new(self.scope, f).ok_or(Throw)).upcast(); - try!(self.exports.set(self.scope, key, value)); + pub fn export(&mut self, key: &str, f: fn(Call) -> JS) -> Result<()> { + let value = try!(Function::new(self.scope, f)).upcast::(); + try!(self.exports.set(key, value)); Ok(()) } } -extern "C" fn module_body_callback<'a>(body: fn(Module) -> Result<()>, exports: &'a mut Handle<'a, Object>, scope: &'a mut RootScope<'a>) { +extern "C" fn module_body_callback<'a>(body: fn(Module) -> Result<()>, exports: &'a mut Handle<'a, SomeObject>, scope: &'a mut RootScope<'a>) { let _ = body(Module { exports: exports, scope: scope @@ -88,9 +88,9 @@ impl<'a> Call<'a> { } } - pub fn this<'b, T: Scope<'b>>(&self, _: &mut T) -> Handle<'b, Object> { + pub fn this<'b, T: Scope<'b>>(&self, _: &mut T) -> Handle<'b, SomeObject> { unsafe { - let mut result = Object::zero_internal(); + let mut result = zeroed::(); Nan_FunctionCallbackInfo_This(mem::transmute(self.info), result.to_raw_mut_ref()); result } @@ -98,7 +98,7 @@ impl<'a> Call<'a> { pub fn callee<'b, T: Scope<'b>>(&self, _: &mut T) -> Handle<'b, Function> { unsafe { - let mut result = Function::zero_internal(); + let mut result = zeroed::(); Nan_FunctionCallbackInfo_Callee(mem::transmute(self.info), result.to_raw_mut_ref()); result } @@ -122,7 +122,7 @@ impl<'a> Arguments<'a> { return None; } unsafe { - let mut result = Value::zero_internal(); + let mut result = zeroed::(); Nan_FunctionCallbackInfo_Get(&self.info, i, result.to_raw_mut_ref()); Some(result) } @@ -134,7 +134,7 @@ impl<'a> Arguments<'a> { return Err(Throw); } unsafe { - let mut result = Value::zero_internal(); + let mut result = zeroed::(); Nan_FunctionCallbackInfo_Get(&self.info, i, result.to_raw_mut_ref()); Ok(result) } diff --git a/src/lib.rs b/src/lib.rs index f1b8675a5..08a7321dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,13 +5,14 @@ pub mod mem; pub mod vm; pub mod scope; pub mod value; +pub mod error; pub mod buffer; use internal::vm::{Module, Throw}; use internal::mem::Handle; -use internal::value::Object; +use internal::value::SomeObject; #[no_mangle] -pub extern "C" fn nanny_init(mut module: Handle, init: fn(Module) -> Result<(), Throw>) { +pub extern "C" fn nanny_init(mut module: Handle, init: fn(Module) -> Result<(), Throw>) { Module::initialize(&mut module, init); } diff --git a/src/value.rs b/src/value.rs index fce191f08..2932c7efb 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1 +1 @@ -pub use internal::value::{Tagged, Value, Undefined, Null, Boolean, Integer, Number, String, Object, Array, Function}; +pub use internal::value::{Any, Variant, Object, Value, Undefined, Null, Boolean, Integer, Number, String, SomeObject, Array, Function};