From 34ede8c655ef30b7dc5271459cde4c7256b18b11 Mon Sep 17 00:00:00 2001 From: David Herman Date: Mon, 30 Jul 2018 23:13:50 -0700 Subject: [PATCH 01/11] WIP: Add a `HandleArena` to every context, and proof of concept with `JsUndefined::new_thin()` and `cx.undefined_thin()`. --- src/context/internal.rs | 78 ++++++++++++++++++++++++++++++++++++++--- src/context/mod.rs | 27 +++++++++++++- src/types/mod.rs | 9 +++++ 3 files changed, 109 insertions(+), 5 deletions(-) diff --git a/src/context/internal.rs b/src/context/internal.rs index ee862d5cc..26c9f3274 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -1,5 +1,8 @@ use std; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; +use std::collections::VecDeque; +use std::marker::PhantomData; +use std::mem; use std::os::raw::c_void; use neon_runtime; use neon_runtime::raw; @@ -52,7 +55,68 @@ pub struct ScopeMetadata { pub struct Scope<'a, R: Root + 'static> { pub metadata: ScopeMetadata, - pub handle_scope: &'a mut R + pub handle_scope: &'a mut R, + pub handle_arena: HandleArena<'a> +} + +const CHUNK_SIZE: usize = 16; + +type Chunk = [raw::Local; CHUNK_SIZE]; + +pub struct HandleArena<'a> { + chunks: VecDeque>, + chunk_allocated: usize, + phantom: PhantomData<&'a ()> +} + +impl<'a> HandleArena<'a> { + fn new() -> Self { + let mut chunks = VecDeque::with_capacity(16); + + chunks.push_back(Box::new(unsafe { mem::uninitialized() })); + + HandleArena { + chunks, + chunk_allocated: 0, + phantom: PhantomData + } + } + + pub unsafe fn alloc(&mut self) -> *mut raw::Local { + if self.chunk_allocated >= CHUNK_SIZE { + let mut chunk: Box = Box::new(mem::uninitialized()); + let p: *mut raw::Local = &mut chunk[0]; + self.chunks.push_back(chunk); + self.chunk_allocated = 1; + p + } else { + let chunk: &mut Box = self.chunks.back_mut().unwrap(); + let p: *mut raw::Local = &mut chunk[self.chunk_allocated]; + self.chunk_allocated += 1; + p + } + } +/* + fn alloc(&mut self, init: raw::Local) -> &'a raw::Local { + let p = if self.chunk_allocated >= CHUNK_SIZE { + let mut chunk: Box = Box::new(unsafe { mem::uninitialized() }); + chunk[0] = init; + let p: *const raw::Local = &chunk[0]; + self.chunks.push_back(chunk); + self.chunk_allocated = 1; + p + } else { + let chunk: &mut Box = self.chunks.back_mut().unwrap(); + chunk[self.chunk_allocated] = init; + let p: *const raw::Local = &chunk[self.chunk_allocated]; + self.chunk_allocated += 1; + p + }; + + unsafe { mem::transmute(p) } + } +*/ + } impl<'a, R: Root + 'static> Scope<'a, R> { @@ -68,7 +132,8 @@ impl<'a, R: Root + 'static> Scope<'a, R> { isolate, active: Cell::new(true) }, - handle_scope: &mut handle_scope + handle_scope: &mut handle_scope, + handle_arena: HandleArena::new() }; f(scope) }; @@ -80,7 +145,8 @@ impl<'a, R: Root + 'static> Scope<'a, R> { } pub trait ContextInternal<'a>: Sized { - fn scope_metadata(&self) -> &ScopeMetadata; + fn scope_metadata(&self) -> &ScopeMetadata; + fn handle_arena(&mut self) -> &mut HandleArena<'a>; fn isolate(&self) -> Isolate { self.scope_metadata().isolate @@ -98,6 +164,10 @@ pub trait ContextInternal<'a>: Sized { fn activate(&self) { self.scope_metadata().active.set(true); } fn deactivate(&self) { self.scope_metadata().active.set(false); } + + unsafe fn alloc(&mut self) -> *mut raw::Local { + self.handle_arena().alloc() + } } pub fn initialize_module(exports: Handle, init: fn(ModuleContext) -> NeonResult<()>) { diff --git a/src/context/mod.rs b/src/context/mod.rs index f81d62834..4788b8949 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -18,7 +18,7 @@ use types::error::JsError; use object::{Object, This}; use object::class::Class; use result::{NeonResult, JsResult, Throw}; -use self::internal::{ContextInternal, Scope, ScopeMetadata}; +use self::internal::{ContextInternal, Scope, ScopeMetadata, HandleArena}; #[repr(C)] pub(crate) struct CallbackInfo { @@ -259,6 +259,11 @@ pub trait Context<'a>: ContextInternal<'a> { JsUndefined::new() } + /// Convenience method for creating a `JsUndefined` value. + fn undefined_thin(&mut self) -> &'a JsUndefined { + JsUndefined::new_thin(self) + } + /// Convenience method for creating an empty `JsObject` value. fn empty_object(&mut self) -> Handle<'a, JsObject> { JsObject::new(self) @@ -380,6 +385,10 @@ impl<'a> ContextInternal<'a> for ModuleContext<'a> { fn scope_metadata(&self) -> &ScopeMetadata { &self.scope.metadata } + + fn handle_arena(&mut self) -> &mut HandleArena<'a> { + &mut self.scope.handle_arena + } } impl<'a> Context<'a> for ModuleContext<'a> { } @@ -401,6 +410,10 @@ impl<'a> ContextInternal<'a> for ExecuteContext<'a> { fn scope_metadata(&self) -> &ScopeMetadata { &self.scope.metadata } + + fn handle_arena(&mut self) -> &mut HandleArena<'a> { + &mut self.scope.handle_arena + } } impl<'a> Context<'a> for ExecuteContext<'a> { } @@ -428,6 +441,10 @@ impl<'a, 'b> ContextInternal<'a> for ComputeContext<'a, 'b> { fn scope_metadata(&self) -> &ScopeMetadata { &self.scope.metadata } + + fn handle_arena(&mut self) -> &mut HandleArena<'a> { + &mut self.scope.handle_arena + } } impl<'a, 'b> Context<'a> for ComputeContext<'a, 'b> { } @@ -481,6 +498,10 @@ impl<'a, T: This> ContextInternal<'a> for CallContext<'a, T> { fn scope_metadata(&self) -> &ScopeMetadata { &self.scope.metadata } + + fn handle_arena(&mut self) -> &mut HandleArena<'a> { + &mut self.scope.handle_arena + } } impl<'a, T: This> Context<'a> for CallContext<'a, T> { } @@ -510,6 +531,10 @@ impl<'a> ContextInternal<'a> for TaskContext<'a> { fn scope_metadata(&self) -> &ScopeMetadata { &self.scope.metadata } + + fn handle_arena(&mut self) -> &mut HandleArena<'a> { + &mut self.scope.handle_arena + } } impl<'a> Context<'a> for TaskContext<'a> { } diff --git a/src/types/mod.rs b/src/types/mod.rs index a5df16294..09c684761 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -8,6 +8,7 @@ pub(crate) mod utf8; use std; use std::fmt; +use std::mem; use std::os::raw::c_void; use std::marker::PhantomData; use neon_runtime; @@ -98,6 +99,14 @@ impl JsValue { pub struct JsUndefined(raw::Local); impl JsUndefined { + pub fn new_thin<'a, C: Context<'a>>(cx: &mut C) -> &'a JsUndefined { + unsafe { + let local = cx.alloc(); + neon_runtime::primitive::undefined(mem::transmute(local)); + mem::transmute(local) + } + } + pub fn new<'a>() -> Handle<'a, JsUndefined> { JsUndefined::new_internal() } From ee856bdb14aa495caaf215c84752cefd171f1026 Mon Sep 17 00:00:00 2001 From: David Herman Date: Thu, 24 Jan 2019 16:16:14 -0800 Subject: [PATCH 02/11] Got the basic type hierarchy working, with a few manual smoke tests working. Still a good amount of stubbed code left to finish... --- Cargo.toml | 1 + crates/neon-runtime/src/array.rs | 8 +- crates/neon-runtime/src/arraybuffer.rs | 11 +- crates/neon-runtime/src/buffer.rs | 14 +- crates/neon-runtime/src/call.rs | 15 +- crates/neon-runtime/src/class.rs | 8 +- crates/neon-runtime/src/error.rs | 24 +- crates/neon-runtime/src/fun.rs | 20 +- crates/neon-runtime/src/mem.rs | 14 +- crates/neon-runtime/src/neon.cc | 386 +++++++++++++++++---- crates/neon-runtime/src/neon.h | 79 +++-- crates/neon-runtime/src/object.rs | 28 +- crates/neon-runtime/src/primitive.rs | 26 +- crates/neon-runtime/src/raw.rs | 47 +++ crates/neon-runtime/src/string.rs | 8 +- crates/neon-runtime/src/tag.rs | 30 +- src/context/internal.rs | 57 ++- src/context/mod.rs | 167 +++++---- src/handle/internal.rs | 5 - src/handle/mod.rs | 154 -------- src/lib.rs | 25 +- src/object/class/internal.rs | 41 ++- src/object/class/mod.rs | 47 ++- src/object/mod.rs | 63 ++-- src/prelude.rs | 7 +- src/result/mod.rs | 12 +- src/task/mod.rs | 14 +- src/types/binary.rs | 70 ++-- src/types/error.rs | 43 ++- src/types/internal.rs | 20 +- src/types/mod.rs | 463 +++++++++++++------------ 31 files changed, 1134 insertions(+), 773 deletions(-) delete mode 100644 src/handle/internal.rs delete mode 100644 src/handle/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 39cdcf5d9..b96441f93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ lazy_static = "0.2.8" [dependencies] cslice = "0.2" semver = "0.9.0" +typed-arena = "1.4.1" neon-runtime = { version = "=0.2.0", path = "crates/neon-runtime" } [workspace] diff --git a/crates/neon-runtime/src/array.rs b/crates/neon-runtime/src/array.rs index 4982c990b..cda08da7e 100644 --- a/crates/neon-runtime/src/array.rs +++ b/crates/neon-runtime/src/array.rs @@ -1,6 +1,6 @@ //! Facilities for working with `v8::Array`s. -use raw::{Local, Isolate}; +use raw::{Local, Isolate, Persistent}; extern "C" { @@ -8,8 +8,12 @@ extern "C" { #[link_name = "Neon_Array_New"] pub fn new(out: &mut Local, isolate: *mut Isolate, length: u32); + /// Initializes the `out` argument provided to refer to a newly created `v8::Array`. + #[link_name = "Neon_Array_Init"] + pub fn init(out: &Persistent, isolate: *mut Isolate, length: u32); + /// Gets the length of an `v8::Array`. #[link_name = "Neon_Array_Length"] - pub fn len(array: Local) -> u32; + pub fn len(array: &Persistent) -> u32; } diff --git a/crates/neon-runtime/src/arraybuffer.rs b/crates/neon-runtime/src/arraybuffer.rs index 825806594..e2f20f962 100644 --- a/crates/neon-runtime/src/arraybuffer.rs +++ b/crates/neon-runtime/src/arraybuffer.rs @@ -1,10 +1,17 @@ //! Facilities for working with `v8::ArrayBuffer`s. -use raw::Local; +use raw::{Isolate, Local, Persistent}; use std::os::raw::c_void; +// FIXME: rename init_xxx functions back to new_xxx + extern "C" { + /// Initializes the `out` argument provided to refer to a newly created `v8::ArrayBuffer` object. + /// Returns `false` if the value couldn't be created. + #[link_name = "Neon_ArrayBuffer_Init"] + pub fn init(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; + /// Mutates the `out` argument provided to refer to a newly created `v8::ArrayBuffer` object. /// Returns `false` if the value couldn't be created. #[link_name = "Neon_ArrayBuffer_New"] @@ -12,5 +19,5 @@ extern "C" { /// Mutates the `base_out` and `size_out` arguments to access the data of a `v8::ArrayBuffer` object. #[link_name = "Neon_ArrayBuffer_Data"] - pub fn data<'a, 'b>(base_out: &'a mut *mut c_void, size_out: &'a mut usize, obj: Local); + pub fn data<'a, 'b>(base_out: &'a mut *mut c_void, size_out: &'a mut usize, obj: &Persistent); } diff --git a/crates/neon-runtime/src/buffer.rs b/crates/neon-runtime/src/buffer.rs index ede808537..152e7afa4 100644 --- a/crates/neon-runtime/src/buffer.rs +++ b/crates/neon-runtime/src/buffer.rs @@ -1,8 +1,10 @@ //! Facilities for working with `node::Buffer`s. -use raw::Local; +use raw::{Isolate, Local, Persistent}; use std::os::raw::c_void; +// FIXME: rename init_xxx functions back to new_xxx + extern "C" { /// Mutates the `out` argument provided to refer to a newly created and zero-filled `node::Buffer` object. @@ -10,6 +12,14 @@ extern "C" { #[link_name = "Neon_Buffer_New"] pub fn new(out: &mut Local, size: u32) -> bool; + /// Initializes the `out` argumnent with a newly created `v8::Buffer` using the safe constructor. + #[link_name = "Neon_Buffer_Init_Safe"] + pub fn init_safe(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; + + /// Initializes the `out` argumnent with a newly created `v8::Buffer` using the unsafe constructor. + #[link_name = "Neon_Buffer_Init_Unsafe"] + pub fn init_unsafe(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; + /// Mutates the `out` argument provided to refer to a newly created `node::Buffer` object. /// Returns `false` if the value couldn't be created. #[link_name = "Neon_Buffer_Uninitialized"] @@ -17,6 +27,6 @@ extern "C" { /// Mutates the `base_out` and `size_out` arguments to access the data of a `node::Buffer` object. #[link_name = "Neon_Buffer_Data"] - pub fn data<'a, 'b>(base_out: &'a mut *mut c_void, size_out: &'a mut usize, obj: Local); + pub fn data<'a, 'b>(base_out: &'a mut *mut c_void, size_out: &'a mut usize, obj: &Persistent); } diff --git a/crates/neon-runtime/src/call.rs b/crates/neon-runtime/src/call.rs index 36166964f..3111fe2e1 100644 --- a/crates/neon-runtime/src/call.rs +++ b/crates/neon-runtime/src/call.rs @@ -2,7 +2,7 @@ use std::os::raw::c_void; use std::ptr::null_mut; -use raw::{FunctionCallbackInfo, Isolate, Local}; +use raw::{FunctionCallbackInfo, Isolate, Local, Persistent}; #[repr(C)] pub struct CCallback { @@ -25,6 +25,10 @@ extern "C" { #[link_name = "Neon_Call_SetReturn"] pub fn set_return(info: &FunctionCallbackInfo, value: Local); + /// Sets the return value of the function call. + #[link_name = "Neon_Call_SetReturnThin"] + pub fn set_return_thin(info: &FunctionCallbackInfo, value: &Persistent); + /// Gets the isolate of the function call. #[link_name = "Neon_Call_GetIsolate"] pub fn get_isolate(info: &FunctionCallbackInfo) -> *mut Isolate; @@ -47,6 +51,11 @@ extern "C" { #[link_name = "Neon_Call_Data"] pub fn data(info: &FunctionCallbackInfo, out: &mut Local); + /// Initializes the `out` argument provided to refer to the value of the + /// `v8::FunctionCallbackInfo` `Data`. + #[link_name = "Neon_Call_InitData"] + pub fn init_data(info: &FunctionCallbackInfo, isolate: *mut Isolate, out: &Persistent); + /// Gets the number of arguments passed to the function. #[link_name = "Neon_Call_Length"] pub fn len(info: &FunctionCallbackInfo) -> i32; @@ -56,4 +65,8 @@ extern "C" { #[link_name = "Neon_Call_Get"] pub fn get(info: &FunctionCallbackInfo, i: i32, out: &mut Local); + /// Initializes the `out` argument provided to refer to the `i`th argument passed to the function. + #[link_name = "Neon_Call_InitGet"] + pub fn init_get(info: &FunctionCallbackInfo, isolate: *mut Isolate, i: i32, out: &Persistent); + } diff --git a/crates/neon-runtime/src/class.rs b/crates/neon-runtime/src/class.rs index 5462336f0..c7747d479 100644 --- a/crates/neon-runtime/src/class.rs +++ b/crates/neon-runtime/src/class.rs @@ -1,6 +1,6 @@ use std::os::raw::c_void; use call::CCallback; -use raw::{Isolate, Local}; +use raw::{Isolate, Local, Persistent}; extern "C" { @@ -38,13 +38,13 @@ extern "C" { // FIXME: get rid of all the "kernel" nomenclature #[link_name = "Neon_Class_GetAllocateKernel"] - pub fn get_allocate_kernel(obj: Local) -> *mut c_void; + pub fn get_allocate_kernel(obj: &Persistent) -> *mut c_void; #[link_name = "Neon_Class_GetConstructKernel"] - pub fn get_construct_kernel(obj: Local) -> *mut c_void; + pub fn get_construct_kernel(obj: &Persistent) -> *mut c_void; #[link_name = "Neon_Class_GetCallKernel"] - pub fn get_call_kernel(obj: Local) -> *mut c_void; + pub fn get_call_kernel(obj: &Persistent) -> *mut c_void; #[link_name = "Neon_Class_Constructor"] pub fn constructor(out: &mut Local, ft: Local) -> bool; diff --git a/crates/neon-runtime/src/error.rs b/crates/neon-runtime/src/error.rs index aa8c47fc1..f592a5bc9 100644 --- a/crates/neon-runtime/src/error.rs +++ b/crates/neon-runtime/src/error.rs @@ -1,24 +1,38 @@ //! Facilities for creating and throwing JS errors. -use raw::Local; +use raw::{Isolate, Local, Persistent}; + +// FIXME: rename init_xxx functions back to new_xxx extern "C" { /// Throws an `Error` object in the current context. #[link_name = "Neon_Error_Throw"] - pub fn throw(val: Local); + pub fn throw(val: &Persistent); /// Mutates the `out` argument provided to refer to a newly created `Error` object. #[link_name = "Neon_Error_NewError"] - pub fn new_error(out: &mut Local, msg: Local); + pub fn new_error(out: &mut Local, msg: &Persistent); + + /// Initializes the `out` argument provided to refer to a newly created `Error` object. + #[link_name = "Neon_Error_InitError"] + pub fn init_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); + + /// Initializes the `out` argument provided to refer to a newly created `Error` object. + #[link_name = "Neon_Error_InitTypeError"] + pub fn init_type_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); + + /// Initializes the `out` argument provided to refer to a newly created `Error` object. + #[link_name = "Neon_Error_InitRangeError"] + pub fn init_range_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); /// Mutates the `out` argument provided to refer to a newly created `TypeError` object. #[link_name = "Neon_Error_NewTypeError"] - pub fn new_type_error(out: &mut Local, msg: Local); + pub fn new_type_error(out: &mut Local, msg: &Persistent); /// Mutates the `out` argument provided to refer to a newly created `RangeError` object. #[link_name = "Neon_Error_NewRangeError"] - pub fn new_range_error(out: &mut Local, msg: Local); + pub fn new_range_error(out: &mut Local, msg: &Persistent); /// Throws an `Error` object in the current context. #[link_name = "Neon_Error_ThrowErrorFromUtf8"] diff --git a/crates/neon-runtime/src/fun.rs b/crates/neon-runtime/src/fun.rs index ca8432f08..3d66f1daf 100644 --- a/crates/neon-runtime/src/fun.rs +++ b/crates/neon-runtime/src/fun.rs @@ -2,7 +2,7 @@ use std::os::raw::c_void; use call::CCallback; -use raw::Local; +use raw::{Local, Persistent}; extern "C" { @@ -11,6 +11,11 @@ extern "C" { #[link_name = "Neon_Fun_New"] pub fn new(out: &mut Local, isolate: *mut c_void, callback: CCallback) -> bool; + /// Initializes the `out` argument provided to refer to a newly created `v8::Function`. Returns + /// `false` if the value couldn't be created. + #[link_name = "Neon_Fun_Init"] + pub fn init(out: &Persistent, isolate: *mut c_void, callback: CCallback) -> bool; + /// Mutates the `out` argument provided to refer to a newly created `v8::FunctionTemplate`. /// Returns `false` if the value couldn't be created. #[link_name = "Neon_Fun_Template_New"] @@ -18,17 +23,28 @@ extern "C" { /// Gets the reference to the `v8::Local` handle provided. #[link_name = "Neon_Fun_GetDynamicCallback"] - pub fn get_dynamic_callback(obj: Local) -> *mut c_void; + pub fn get_dynamic_callback(obj: &Persistent) -> *mut c_void; /// Calls the function provided (`fun`) and mutates the `out` argument provided to refer to the /// result of the function call. Returns `false` if the result of the call was empty. #[link_name = "Neon_Fun_Call"] pub fn call(out: &mut Local, isolate: *mut c_void, fun: Local, this: Local, argc: i32, argv: *mut c_void) -> bool; + /// Calls the function provided (`fun`) and mutates the `out` argument provided to refer to the + /// result of the function call. Returns `false` if the result of the call was empty. + #[link_name = "Neon_Fun_CallThin"] + pub fn call_thin(out: &Persistent, isolate: *mut c_void, fun: &Persistent, this: &Persistent, argc: i32, argv: *mut c_void) -> bool; + /// Makes a constructor call to with the function provided (`fun`) and mutates the `out` /// argument provided to refer to the result of the constructor call. Returns `false` if the /// result of the call was empty. #[link_name = "Neon_Fun_Construct"] pub fn construct(out: &mut Local, isolate: *mut c_void, fun: Local, argc: i32, argv: *mut c_void) -> bool; + /// Makes a constructor call to with the function provided (`fun`) and mutates the `out` + /// argument provided to refer to the result of the constructor call. Returns `false` if the + /// result of the call was empty. + #[link_name = "Neon_Fun_ConstructThin"] + pub fn construct_thin(out: &Persistent, isolate: *mut c_void, fun: &Persistent, argc: i32, argv: *mut c_void) -> bool; + } diff --git a/crates/neon-runtime/src/mem.rs b/crates/neon-runtime/src/mem.rs index f77e6195c..f48f3c663 100644 --- a/crates/neon-runtime/src/mem.rs +++ b/crates/neon-runtime/src/mem.rs @@ -1,5 +1,5 @@ //! A helper function for comparing `v8::Local` handles. -use raw::Local; +use raw::{Local, Persistent}; extern "C" { @@ -7,4 +7,16 @@ extern "C" { #[link_name = "Neon_Mem_SameHandle"] pub fn same_handle(h1: Local, h2: Local) -> bool; + /// Initializes a pointer as a `v8::Persistent`. + #[link_name = "Neon_Mem_NewPersistent"] + pub fn new_persistent(out: &mut Persistent); + + /// Deallocates a `v8::Persistent`. + #[link_name = "Neon_Mem_DropPersistent"] + pub fn drop_persistent(p: &mut Persistent); + + /// Resets a `v8::Persistent` to the given handle. + #[link_name = "Neon_Mem_ResetPersistent"] + pub fn reset_persistent(p: &Persistent, h: Local); + } diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index 63b2f350d..e4aa5a5ab 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -13,6 +13,10 @@ extern "C" void Neon_Call_SetReturn(v8::FunctionCallbackInfo *info, v info->GetReturnValue().Set(value); } +extern "C" void Neon_Call_SetReturnThin(v8::FunctionCallbackInfo *info, v8::Persistent *value) { + info->GetReturnValue().Set(*value); +} + extern "C" void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo *info) { return (void *)info->GetIsolate(); } @@ -39,6 +43,13 @@ extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Lo *out = info->Data(); } +extern "C" void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, v8::Persistent *out) { + Nan::HandleScope scope; + v8::Local data = info->Data(); + out->Reset(isolate, data); +} + + extern "C" int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info) { return info->Length(); } @@ -47,13 +58,31 @@ extern "C" void Neon_Call_Get(v8::FunctionCallbackInfo *info, int32_t *out = (*info)[i]; } +extern "C" void Neon_Call_InitGet(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out) { + Nan::HandleScope scope; + v8::Local local = (*info)[i]; + out->Reset(isolate, local); +} + extern "C" void Neon_Object_New(v8::Local *out) { *out = Nan::New(); } -extern "C" bool Neon_Object_GetOwnPropertyNames(v8::Local *out, v8::Local obj) { - Nan::MaybeLocal maybe = Nan::GetOwnPropertyNames(obj); - return maybe.ToLocal(out); +extern "C" void Neon_Object_Init(v8::Persistent *out, v8::Isolate *isolate) { + Nan::HandleScope scope; + v8::Local local = Nan::New(); + out->Reset(isolate, local); +} + +extern "C" bool Neon_Object_GetOwnPropertyNames(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *obj) { + Nan::HandleScope scope; + v8::Local lobj = Nan::New(*obj); + v8::Local larr; + Nan::MaybeLocal maybe = Nan::GetOwnPropertyNames(lobj); + if (!maybe.ToLocal(&larr)) { + return false; + } + out->Reset(isolate, larr); } extern "C" void *Neon_Object_GetIsolate(v8::Local obj) { @@ -64,24 +93,37 @@ extern "C" void Neon_Primitive_Undefined(v8::Local *out) { *out = Nan::Undefined(); } -extern "C" void Neon_Primitive_Null(v8::Local *out) { - *out = Nan::Null(); +extern "C" void Neon_Primitive_InitUndefined(v8::Persistent *out, v8::Isolate *isolate) { + Nan::HandleScope scope; + out->Reset(isolate, Nan::Undefined()); } -extern "C" void Neon_Primitive_Boolean(v8::Local *out, bool b) { - *out = b ? Nan::True() : Nan::False(); +extern "C" void Neon_Primitive_InitNull(v8::Persistent *out, v8::Isolate *isolate) { + Nan::HandleScope scope; + out->Reset(isolate, Nan::Null()); } -extern "C" bool Neon_Primitive_BooleanValue(v8::Local p) { - return p->Value(); +extern "C" void Neon_Primitive_InitBoolean(v8::Persistent *out, v8::Isolate *isolate, bool b) { + Nan::HandleScope scope; + out->Reset(isolate, b ? Nan::True() : Nan::False()); } -extern "C" void Neon_Primitive_Number(v8::Local *out, v8::Isolate *isolate, double value) { - *out = v8::Number::New(isolate, value); +extern "C" bool Neon_Primitive_BooleanValue(v8::Persistent *p) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*p); + return local->Value(); } -extern "C" double Neon_Primitive_NumberValue(v8::Local n) { - return n->Value(); +extern "C" double Neon_Primitive_NumberValue(v8::Persistent *n) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*n); + return local->Value(); +} + +extern "C" void Neon_Primitive_InitNumber(v8::Persistent *out, v8::Isolate *isolate, double value) { + Nan::HandleScope scope; + v8::Local n = v8::Number::New(isolate, value); + out->Reset(isolate, n); } extern "C" bool Neon_Primitive_IsUint32(v8::Local p) { @@ -122,6 +164,22 @@ extern "C" bool Neon_Object_Get_String(v8::Local *out, v8::Local *p_out, v8::Persistent *p_obj, const uint8_t *data, int32_t len) { + Nan::HandleScope scope; + v8::Local key; + if (!Neon_ASCII_Key(&key, data, len)) { + return false; + } + v8::Local obj = Nan::New(*p_obj); + Nan::MaybeLocal maybe = Nan::Get(obj, key); + v8::Local result; + if (!maybe.ToLocal(&result)) { + return false; + } + p_out->Reset(v8::Isolate::GetCurrent(), result); + return true; +} + extern "C" bool Neon_Object_Set_String(bool *out, v8::Local obj, const uint8_t *data, int32_t len, v8::Local val) { Nan::HandleScope scope; v8::Local key; @@ -132,11 +190,38 @@ extern "C" bool Neon_Object_Set_String(bool *out, v8::Local obj, con return maybe.IsJust() && (*out = maybe.FromJust(), true); } +extern "C" bool Neon_Object_Set_StringThin(bool *out, v8::Persistent *p_obj, const uint8_t *data, int32_t len, v8::Persistent *p_val) { + Nan::HandleScope scope; + v8::Local key; + if (!Neon_ASCII_Key(&key, data, len)) { + return false; + } + v8::Local obj = Nan::New(*p_obj); + v8::Local val = Nan::New(*p_val); + Nan::Maybe maybe = Nan::Set(obj, key, val); + return maybe.IsJust() && (*out = maybe.FromJust(), true); +} + extern "C" bool Neon_Object_Get(v8::Local *out, v8::Local obj, v8::Local key) { Nan::MaybeLocal maybe = Nan::Get(obj, key); return maybe.ToLocal(out); } +extern "C" bool Neon_Object_GetThin(v8::Persistent *p_out, v8::Persistent *p_obj, v8::Persistent *p_key) { + Nan::HandleScope scope; + // FIXME: pass in the isolate + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local object = Nan::New(*p_obj); + v8::Local key = Nan::New(*p_key); + Nan::MaybeLocal maybe = Nan::Get(object, key); + v8::Local value; + if (!maybe.ToLocal(&value)) { + return false; + } + p_out->Reset(isolate, value); + return true; +} + extern "C" bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local key, v8::Local val) { Nan::Maybe maybe = Nan::Set(obj, key, val); if (maybe.IsJust()) { @@ -146,25 +231,56 @@ extern "C" bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local< return false; } +extern "C" bool Neon_Object_SetThin(bool *out, v8::Persistent *p_obj, v8::Persistent *p_key, v8::Persistent *p_val) { + Nan::HandleScope scope; + v8::Local object = Nan::New(*p_obj); + v8::Local key = Nan::New(*p_key); + v8::Local value = Nan::New(*p_val); + Nan::Maybe maybe = Nan::Set(object, key, value); + if (maybe.IsJust()) { + *out = maybe.FromJust(); + return true; + } + return false; +} + +extern "C" void Neon_Array_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t length) { + Nan::HandleScope scope; + v8::Local local = v8::Array::New(isolate, length); + out->Reset(isolate, local); +} + extern "C" void Neon_Array_New(v8::Local *out, v8::Isolate *isolate, uint32_t length) { *out = v8::Array::New(isolate, length); } -extern "C" uint32_t Neon_Array_Length(v8::Local array) { - return array->Length(); +extern "C" uint32_t Neon_Array_Length(v8::Persistent *array) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*array); + return local->Length(); } -extern "C" bool Neon_String_New(v8::Local *out, v8::Isolate *isolate, const uint8_t *data, int32_t len) { +extern "C" bool Neon_String_New(v8::Persistent *out, v8::Isolate *isolate, const uint8_t *data, int32_t len) { + Nan::HandleScope scope; Nan::MaybeLocal maybe = v8::String::NewFromUtf8(isolate, (const char*)data, v8::NewStringType::kNormal, len); - return maybe.ToLocal(out); + v8::Local local; + if (!maybe.ToLocal(&local)) { + return false; + } + out->Reset(isolate, local); + return true; } -extern "C" int32_t Neon_String_Utf8Length(v8::Local str) { - return str->Utf8Length(); +extern "C" int32_t Neon_String_Utf8Length(v8::Persistent *str) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*str); + return local->Utf8Length(); } -extern "C" size_t Neon_String_Data(char *out, size_t len, v8::Local str) { - return Nan::DecodeWrite(out, len, str, Nan::UTF8); +extern "C" size_t Neon_String_Data(char *out, size_t len, v8::Persistent *str) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*str); + return Nan::DecodeWrite(out, len, local, Nan::UTF8); } extern "C" bool Neon_Convert_ToString(v8::Local *out, v8::Local value) { @@ -177,6 +293,30 @@ extern "C" bool Neon_Convert_ToObject(v8::Local *out, v8::Local *out, v8::Isolate *isolate, uint32_t len) { + Nan::HandleScope scope; + Nan::MaybeLocal maybe = Nan::NewBuffer(len); + v8::Local buffer; + if (!maybe.ToLocal(&buffer)) { + return false; + } + void *data = node::Buffer::Data(buffer); + memset(data, 0, len); + out->Reset(isolate, buffer); + return true; +} + +extern "C" bool Neon_Buffer_Init_Unsafe(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { + Nan::HandleScope scope; + Nan::MaybeLocal maybe = Nan::NewBuffer(len); + v8::Local buffer; + if (!maybe.ToLocal(&buffer)) { + return false; + } + out->Reset(isolate, buffer); + return true; +} + extern "C" bool Neon_Buffer_New(v8::Local *out, uint32_t size) { Nan::MaybeLocal maybe = Nan::NewBuffer(size); if (!maybe.ToLocal(out)) { @@ -193,13 +333,24 @@ extern "C" bool Neon_Buffer_Uninitialized(v8::Local *out, uint32_t s return maybe.ToLocal(out); } -extern "C" void Neon_Buffer_Data(void **base_out, size_t *len_out, v8::Local obj) { - *base_out = node::Buffer::Data(obj); - *len_out = node::Buffer::Length(obj); +extern "C" void Neon_Buffer_Data(void **base_out, size_t *len_out, v8::Persistent *obj) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*obj); + *base_out = node::Buffer::Data(local); + *len_out = node::Buffer::Length(local); +} + +extern "C" bool Neon_Tag_IsBuffer(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return node::Buffer::HasInstance(local); } -extern "C" bool Neon_Tag_IsBuffer(v8::Local obj) { - return node::Buffer::HasInstance(obj); +extern "C" bool Neon_ArrayBuffer_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { + Nan::HandleScope scope; + v8::Local local = v8::ArrayBuffer::New(isolate, len); + out->Reset(isolate, local); + return true; } extern "C" bool Neon_ArrayBuffer_New(v8::Local *out, v8::Isolate *isolate, uint32_t size) { @@ -207,15 +358,18 @@ extern "C" bool Neon_ArrayBuffer_New(v8::Local *out, v8::Isolat return true; } -extern "C" void Neon_ArrayBuffer_Data(void **base_out, size_t *len_out, v8::Local buffer) { - v8::ArrayBuffer::Contents contents = buffer->GetContents(); +extern "C" void Neon_ArrayBuffer_Data(void **base_out, size_t *len_out, v8::Persistent *buffer) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*buffer); + v8::ArrayBuffer::Contents contents = local->GetContents(); *base_out = contents.Data(); *len_out = contents.ByteLength(); } - -extern "C" bool Neon_Tag_IsArrayBuffer(v8::Local value) { - return value->IsArrayBuffer(); +extern "C" bool Neon_Tag_IsArrayBuffer(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsArrayBuffer(); } extern "C" void Neon_Scope_Escape(v8::Local *out, Nan::EscapableHandleScope *scope, v8::Local value) { @@ -322,18 +476,24 @@ extern "C" void Neon_Class_SetClassMap(v8::Isolate *isolate, void *map, Neon_Dro node::AtExit(cleanup_class_map, holder); } -extern "C" void *Neon_Class_GetCallKernel(v8::Local wrapper) { - neon::ClassMetadata *metadata = static_cast(wrapper->Value()); +extern "C" void *Neon_Class_GetCallKernel(v8::Persistent *wrapper) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*wrapper); + neon::ClassMetadata *metadata = static_cast(local->Value()); return metadata->GetCallKernel(); } -extern "C" void *Neon_Class_GetConstructKernel(v8::Local wrapper) { - neon::ClassMetadata *metadata = static_cast(wrapper->Value()); +extern "C" void *Neon_Class_GetConstructKernel(v8::Persistent *wrapper) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*wrapper); + neon::ClassMetadata *metadata = static_cast(local->Value()); return metadata->GetConstructKernel(); } -extern "C" void *Neon_Class_GetAllocateKernel(v8::Local wrapper) { - neon::BaseClassMetadata *metadata = static_cast(wrapper->Value()); +extern "C" void *Neon_Class_GetAllocateKernel(v8::Persistent *wrapper) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*wrapper); + neon::BaseClassMetadata *metadata = static_cast(local->Value()); return metadata->GetAllocateKernel(); } @@ -424,8 +584,27 @@ extern "C" bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, return maybe_result.ToLocal(out); } -extern "C" void *Neon_Fun_GetDynamicCallback(v8::Local data) { - return data->Value(); +extern "C" bool Neon_Fun_Init(v8::Persistent *out, v8::Isolate *isolate, callback_t callback) { + Nan::HandleScope scope; + v8::Local wrapper = v8::External::New(isolate, callback.dynamic_callback); + if (wrapper.IsEmpty()) { + return false; + } + + v8::FunctionCallback static_callback = reinterpret_cast(callback.static_callback); + v8::MaybeLocal maybe_result = v8::Function::New(isolate->GetCurrentContext(), static_callback, wrapper); + v8::Local f; + if (!maybe_result.ToLocal(&f)) { + return false; + } + out->Reset(isolate, f); + return true; +} + +extern "C" void *Neon_Fun_GetDynamicCallback(v8::Persistent *data) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*data); + return local->Value(); } extern "C" bool Neon_Fun_Call(v8::Local *out, v8::Isolate *isolate, v8::Local fun, v8::Local self, int32_t argc, v8::Local argv[]) { @@ -433,61 +612,135 @@ extern "C" bool Neon_Fun_Call(v8::Local *out, v8::Isolate *isolate, v return maybe_result.ToLocal(out); } +extern "C" bool Neon_Fun_CallThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]) { +/* + v8::MaybeLocal maybe_result = fun->Call(isolate->GetCurrentContext(), self, argc, argv); + return maybe_result.ToLocal(out); +*/ + // FIXME: implement me + return false; +} + extern "C" bool Neon_Fun_Construct(v8::Local *out, v8::Isolate *isolate, v8::Local fun, int32_t argc, v8::Local argv[]) { v8::MaybeLocal maybe_result = fun->NewInstance(isolate->GetCurrentContext(), argc, argv); return maybe_result.ToLocal(out); } +extern "C" bool Neon_Fun_ConstructThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, int32_t argc, v8::Persistent *argv[]) { + /* + v8::MaybeLocal maybe_result = fun->NewInstance(isolate->GetCurrentContext(), argc, argv); + return maybe_result.ToLocal(out); + */ + // FIXME: implement me + return false; +} + extern "C" bool Neon_Tag_IsUndefined(v8::Local val) { return val->IsUndefined(); } -extern "C" bool Neon_Tag_IsNull(v8::Local val) { - return val->IsNull(); +extern "C" bool Neon_Tag_IsUndefinedThin(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsUndefined(); } -extern "C" bool Neon_Tag_IsNumber(v8::Local val) { - return val->IsNumber(); +extern "C" bool Neon_Tag_IsNull(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsNull(); } -extern "C" bool Neon_Tag_IsBoolean(v8::Local val) { - return val->IsBoolean(); +extern "C" bool Neon_Tag_IsNumber(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsNumber(); } -extern "C" bool Neon_Tag_IsString(v8::Local val) { - return val->IsString(); +extern "C" bool Neon_Tag_IsBoolean(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsBoolean(); +} + +extern "C" bool Neon_Tag_IsString(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsString(); } extern "C" bool Neon_Tag_IsObject(v8::Local val) { return val->IsObject(); } -extern "C" bool Neon_Tag_IsArray(v8::Local val) { - return val->IsArray(); +extern "C" bool Neon_Tag_IsObjectThin(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsObject(); +} + +extern "C" bool Neon_Tag_IsArray(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsArray(); } extern "C" bool Neon_Tag_IsFunction(v8::Local val) { return val->IsFunction(); } -extern "C" bool Neon_Tag_IsError(v8::Local val) { - return val->IsNativeError(); +extern "C" bool Neon_Tag_IsFunctionThin(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsFunction(); +} + +extern "C" bool Neon_Tag_IsError(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + return local->IsNativeError(); +} + +extern "C" void Neon_Error_Throw(v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*val); + Nan::ThrowError(local); +} + +extern "C" void Neon_Error_InitError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { + Nan::HandleScope scope; + v8::Local lmsg = Nan::New(*msg); + v8::Local lerr = v8::Exception::Error(lmsg); + out->Reset(isolate, lerr); } -extern "C" void Neon_Error_Throw(v8::Local val) { - Nan::ThrowError(val); +extern "C" void Neon_Error_InitTypeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { + Nan::HandleScope scope; + v8::Local lmsg = Nan::New(*msg); + v8::Local lerr = v8::Exception::TypeError(lmsg); + out->Reset(isolate, lerr); } -extern "C" void Neon_Error_NewError(v8::Local *out, v8::Local msg) { - *out = v8::Exception::Error(msg); +extern "C" void Neon_Error_InitRangeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { + Nan::HandleScope scope; + v8::Local lmsg = Nan::New(*msg); + v8::Local lerr = v8::Exception::RangeError(lmsg); + out->Reset(isolate, lerr); } -extern "C" void Neon_Error_NewTypeError(v8::Local *out, v8::Local msg) { - *out = v8::Exception::TypeError(msg); +extern "C" void Neon_Error_NewError(v8::Local *out, v8::Persistent *msg) { + v8::Local local = Nan::New(*msg); + *out = v8::Exception::Error(local); } -extern "C" void Neon_Error_NewRangeError(v8::Local *out, v8::Local msg) { - *out = v8::Exception::RangeError(msg); +extern "C" void Neon_Error_NewTypeError(v8::Local *out, v8::Persistent *msg) { + v8::Local local = Nan::New(*msg); + *out = v8::Exception::TypeError(local); +} + +extern "C" void Neon_Error_NewRangeError(v8::Local *out, v8::Persistent *msg) { + v8::Local local = Nan::New(*msg); + *out = v8::Exception::RangeError(local); } extern "C" void Neon_Error_ThrowErrorFromUtf8(const uint8_t *data, int32_t len) { @@ -508,6 +761,21 @@ extern "C" bool Neon_Mem_SameHandle(v8::Local v1, v8::Local *out) { + ::new (out) v8::Persistent(); +} + +extern "C" void Neon_Mem_DropPersistent(v8::Persistent *p) { + // FIXME: can we change the traits of the persistent to Reset automatically in the destructor? + p->Reset(); + p->Persistent::~Persistent(); +} + +extern "C" void Neon_Mem_ResetPersistent(v8::Persistent *p, v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + p->Reset(isolate, h); +} + extern "C" void Neon_Task_Schedule(void *task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, v8::Local callback) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); neon::Task *internal_task = new neon::Task(isolate, task, perform, complete, callback); diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index f84775b22..b1fb00d75 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -14,47 +14,60 @@ typedef struct { extern "C" { void Neon_Call_SetReturn(v8::FunctionCallbackInfo *info, v8::Local value); + void Neon_Call_SetReturnThin(v8::FunctionCallbackInfo *info, v8::Persistent *value); void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo *info); void *Neon_Call_CurrentIsolate(); bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info); void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Local *out); void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out); + void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, v8::Persistent *out); int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info); void Neon_Call_Get(v8::FunctionCallbackInfo *info, int32_t i, v8::Local *out); + void Neon_Call_InitGet(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out); - void Neon_Primitive_Number(v8::Local *out, v8::Isolate *isolate, double value); + void Neon_Primitive_InitNumber(v8::Persistent *out, v8::Isolate *isolate, double value); void Neon_Primitive_Undefined(v8::Local *out); - void Neon_Primitive_Null(v8::Local *out); - void Neon_Primitive_Boolean(v8::Local *out, bool b); + void Neon_Primitive_InitUndefinedThin(v8::Persistent *out, v8::Isolate *isolate); + void Neon_Primitive_Init_Null(v8::Persistent *out, v8::Isolate *isolate); + void Neon_Primitive_InitBoolean(v8::Persistent *out, v8::Isolate *isolate, bool b); bool Neon_Primitive_IsUint32(v8::Local p); bool Neon_Primitive_IsInt32(v8::Local p); void Neon_Object_New(v8::Local *out); - bool Neon_Object_GetOwnPropertyNames(v8::Local *out, v8::Local obj); + void Neon_Object_Init(v8::Persistent *out, v8::Isolate *isolate); + bool Neon_Object_GetOwnPropertyNames(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *obj); void *Neon_Object_GetIsolate(v8::Local obj); bool Neon_Object_Get_Index(v8::Local *out, v8::Local object, uint32_t index); bool Neon_Object_Set_Index(bool *out, v8::Local object, uint32_t index, v8::Local val); bool Neon_Object_Get_String(v8::Local *out, v8::Local object, const uint8_t *key, int32_t len); + bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Persistent *object, const uint8_t *key, int32_t len); bool Neon_Object_Set_String(bool *out, v8::Local object, const uint8_t *key, int32_t len, v8::Local val); + bool Neon_Object_Set_StringThin(bool *out, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); bool Neon_Object_Get(v8::Local *out, v8::Local object, v8::Local key); + bool Neon_Object_GetThin(v8::Persistent *out, v8::Persistent *object, v8::Persistent *key); bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local key, v8::Local val); + bool Neon_Object_SetThin(bool *out, v8::Persistent *obj, v8::Persistent *key, v8::Persistent *val); void Neon_Array_New(v8::Local *out, v8::Isolate *isolate, uint32_t length); - uint32_t Neon_Array_Length(v8::Local array); + void Neon_Array_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t length); + uint32_t Neon_Array_Length(v8::Persistent *array); - bool Neon_String_New(v8::Local *out, v8::Isolate *isolate, const uint8_t *data, int32_t len); - int32_t Neon_String_Utf8Length(v8::Local str); - size_t Neon_String_Data(char *out, size_t len, v8::Local str); + bool Neon_String_New(v8::Persistent *out, v8::Isolate *isolate, const uint8_t *data, int32_t len); + int32_t Neon_String_Utf8Length(v8::Persistent *str); + size_t Neon_String_Data(char *out, size_t len, v8::Persistent *str); bool Neon_Convert_ToString(v8::Local *out, v8::Local value); bool Neon_Convert_ToObject(v8::Local *out, v8::Local *value); bool Neon_Buffer_New(v8::Local *out, uint32_t size); - void Neon_Buffer_Data(void **base_out, size_t *len_out, v8::Local obj); + void Neon_Buffer_Data(void **base_out, size_t *len_out, v8::Persistent *obj); + bool Neon_Buffer_Init_Safe(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); + bool Neon_Buffer_Init_Unsafe(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); bool Neon_ArrayBuffer_New(v8::Local *out, v8::Isolate *isolate, uint32_t size); + bool Neon_ArrayBuffer_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); bool Neon_ArrayBuffer_Uninitialized(v8::Local *out, v8::Isolate *isolate, uint32_t size); - void Neon_ArrayBuffer_Data(void **base_out, size_t *len_out, v8::Local buffer); + void Neon_ArrayBuffer_Data(void **base_out, size_t *len_out, v8::Persistent *buffer); typedef void(*Neon_ChainedScopeCallback)(void *, void *, void *, void *); typedef void(*Neon_NestedScopeCallback)(void *, void *, void *); @@ -74,10 +87,13 @@ extern "C" { void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Local *out); bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); + bool Neon_Fun_Init(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); bool Neon_Fun_Template_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); - void *Neon_Fun_GetDynamicCallback(v8::Local obj); + void *Neon_Fun_GetDynamicCallback(v8::Persistent *obj); bool Neon_Fun_Call(v8::Local *out, v8::Isolate *isolate, v8::Local fun, v8::Local self, int32_t argc, v8::Local argv[]); + bool Neon_Fun_CallThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]); bool Neon_Fun_Construct(v8::Local *out, v8::Isolate *isolate, v8::Local fun, int32_t argc, v8::Local argv[]); + bool Neon_Fun_ConstructThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, int32_t argc, v8::Persistent *argv[]); typedef void *(*Neon_AllocateCallback)(const v8::FunctionCallbackInfo *info); typedef bool (*Neon_ConstructCallback)(const v8::FunctionCallbackInfo *info); @@ -95,9 +111,9 @@ extern "C" { callback_t call, Neon_DropCallback drop); // FIXME: get rid of all the "kernel" nomenclature - void *Neon_Class_GetCallKernel(v8::Local wrapper); - void *Neon_Class_GetConstructKernel(v8::Local wrapper); - void *Neon_Class_GetAllocateKernel(v8::Local wrapper); + void *Neon_Class_GetCallKernel(v8::Persistent *wrapper); + void *Neon_Class_GetConstructKernel(v8::Persistent *wrapper); + void *Neon_Class_GetAllocateKernel(v8::Persistent *wrapper); bool Neon_Class_Constructor(v8::Local *out, v8::Local ft); bool Neon_Class_HasInstance(void *metadata, v8::Local v); bool Neon_Class_SetName(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length); @@ -110,24 +126,33 @@ extern "C" { uint32_t Neon_Module_GetVersion(); bool Neon_Tag_IsUndefined(v8::Local val); - bool Neon_Tag_IsNull(v8::Local val); - bool Neon_Tag_IsBoolean(v8::Local val); - bool Neon_Tag_IsNumber(v8::Local val); - bool Neon_Tag_IsString(v8::Local val); + bool Neon_Tag_IsUndefinedThin(v8::Persistent *val); + bool Neon_Tag_IsNull(v8::Persistent *val); + bool Neon_Tag_IsBoolean(v8::Persistent *val); + bool Neon_Tag_IsNumber(v8::Persistent *val); + bool Neon_Tag_IsString(v8::Persistent *val); bool Neon_Tag_IsObject(v8::Local val); - bool Neon_Tag_IsArray(v8::Local val); + bool Neon_Tag_IsObjectThin(v8::Persistent *val); + bool Neon_Tag_IsArray(v8::Persistent *val); bool Neon_Tag_IsFunction(v8::Local val); - bool Neon_Tag_IsBuffer(v8::Local obj); - bool Neon_Tag_IsArrayBuffer(v8::Local obj); - bool Neon_Tag_IsError(v8::Local val); - - void Neon_Error_NewError(v8::Local *out, v8::Local msg); - void Neon_Error_NewTypeError(v8::Local *out, v8::Local msg); - void Neon_Error_NewRangeError(v8::Local *out, v8::Local msg); - void Neon_Error_Throw(v8::Local val); + bool Neon_Tag_IsFunctionThin(v8::Persistent *val); + bool Neon_Tag_IsBuffer(v8::Persistent *val); + bool Neon_Tag_IsArrayBuffer(v8::Persistent *val); + bool Neon_Tag_IsError(v8::Persistent *val); + + void Neon_Error_InitError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); + void Neon_Error_InitTypeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); + void Neon_Error_InitRangeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); + void Neon_Error_NewError(v8::Local *out, v8::Persistent *msg); + void Neon_Error_NewTypeError(v8::Local *out, v8::Persistent *msg); + void Neon_Error_NewRangeError(v8::Local *out, v8::Persistent *msg); + void Neon_Error_Throw(v8::Persistent *val); void Neon_Error_ThrowErrorFromUtf8(const uint8_t *data, int32_t len); bool Neon_Mem_SameHandle(v8::Local v1, v8::Local v2); + void Neon_Mem_NewPersistent(v8::Persistent *out); + void Neon_Mem_DropPersistent(v8::Persistent *p); + void Neon_Mem_ResetPersistent(v8::Persistent *p, v8::Local h); typedef void* (*Neon_TaskPerformCallback)(void *); typedef void (*Neon_TaskCompleteCallback)(void *, void *, v8::Local *out); diff --git a/crates/neon-runtime/src/object.rs b/crates/neon-runtime/src/object.rs index 163371972..9b9dc3bcf 100644 --- a/crates/neon-runtime/src/object.rs +++ b/crates/neon-runtime/src/object.rs @@ -1,6 +1,6 @@ //! Facilities for working with `v8::Object`s. -use raw::{Isolate, Local}; +use raw::{Isolate, Local, Persistent}; extern "C" { @@ -8,10 +8,14 @@ extern "C" { #[link_name = "Neon_Object_New"] pub fn new(out: &mut Local); + /// Initializes the `out` argumnent with a newly created `v8::Object`. + #[link_name = "Neon_Object_Init"] + pub fn init(out: &Persistent, isolate: *mut Isolate); + /// Mutates the `out` argument provided to refer to a newly created `v8::Array` containing the /// names of the `v8::Object`'s own property names. Returns `false` if the result is empty. #[link_name = "Neon_Object_GetOwnPropertyNames"] - pub fn get_own_property_names(out: &mut Local, object: Local) -> bool; + pub fn get_own_property_names(out: &Persistent, isolate: *mut Isolate, object: &Persistent) -> bool; /// Gets the `v8::Isolate` of a `v8::Object`. #[link_name = "Neon_Object_GetIsolate"] @@ -33,19 +37,39 @@ extern "C" { #[link_name = "Neon_Object_Get_String"] pub fn get_string(out: &mut Local, object: Local, key: *const u8, len: i32) -> bool; + /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `v8::String`'s + /// underlying content. Returns `false` if the value couldn't be retrieved. + #[link_name = "Neon_Object_Get_StringThin"] + pub fn get_string_thin(out: &Persistent, object: &Persistent, key: *const u8, len: i32) -> bool; + /// Sets the underlying content of a `v8::String` object. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. #[link_name = "Neon_Object_Set_String"] pub fn set_string(out: &mut bool, object: Local, key: *const u8, len: i32, val: Local) -> bool; + /// Sets the underlying content of a `v8::String` object. Also mutates the `out` argument + /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. + #[link_name = "Neon_Object_Set_StringThin"] + pub fn set_string_thin(out: &mut bool, object: &Persistent, key: *const u8, len: i32, val: &Persistent) -> bool; + /// Mutates the `out` argument provided to refer to the `v8::Local` value at the `key` /// provided. Returns `false` if the result couldn't be retrieved. #[link_name = "Neon_Object_Get"] pub fn get(out: &mut Local, object: Local, key: Local) -> bool; + /// Mutates the `out` argument provided to refer to the property value at the `key` + /// provided. Returns `false` if the result couldn't be retrieved. + #[link_name = "Neon_Object_GetThin"] + pub fn get_thin(out: &Persistent, object: &Persistent, key: &Persistent) -> bool; + /// Sets the key value of a `v8::Object` at the `key` provided. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. #[link_name = "Neon_Object_Set"] pub fn set(out: &mut bool, object: Local, key: Local, val: Local) -> bool; + /// Sets the key value of a `v8::Object` at the `key` provided. Also mutates the `out` argument + /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. + #[link_name = "Neon_Object_SetThin"] + pub fn set_thin(out: &mut bool, object: &Persistent, key: &Persistent, val: &Persistent) -> bool; + } diff --git a/crates/neon-runtime/src/primitive.rs b/crates/neon-runtime/src/primitive.rs index 3ac6c7071..8ef8fe73c 100644 --- a/crates/neon-runtime/src/primitive.rs +++ b/crates/neon-runtime/src/primitive.rs @@ -1,6 +1,6 @@ //! Facilities for working with primitive values. -use raw::{Local, Isolate}; +use raw::{Local, Isolate, Persistent}; extern "C" { @@ -8,17 +8,21 @@ extern "C" { #[link_name = "Neon_Primitive_Undefined"] pub fn undefined(out: &mut Local); + /// Initializes the `out` argument with a newly created `v8::Undefined` object. + #[link_name = "Neon_Primitive_InitUndefined"] + pub fn init_undefined(out: &Persistent, isolate: *mut Isolate); + /// Mutates the `out` argument provided to refer to the `v8::Null` object. - #[link_name = "Neon_Primitive_Null"] - pub fn null(out: &mut Local); + #[link_name = "Neon_Primitive_InitNull"] + pub fn init_null(out: &Persistent, isolate: *mut Isolate); - /// Mutates the `out` argument provided to refer to the `v8::Boolean` object. - #[link_name = "Neon_Primitive_Boolean"] - pub fn boolean(out: &mut Local, b: bool); + /// Initializes the `out` argument with a newly created `v8::Boolean` object. + #[link_name = "Neon_Primitive_InitBoolean"] + pub fn init_boolean(out: &Persistent, isolate: *mut Isolate, b: bool); /// Gets the underlying value of a `v8::Boolean` object. #[link_name = "Neon_Primitive_BooleanValue"] - pub fn boolean_value(p: Local) -> bool; + pub fn boolean_value(p: &Persistent) -> bool; // DEPRECATE(0.2) /// Mutates the `out` argument provided to refer to a newly created `v8::Integer` object. @@ -38,11 +42,11 @@ extern "C" { #[link_name = "Neon_Primitive_IntegerValue"] pub fn integer_value(p: Local) -> i64; - /// Mutates the `out` argument provided to refer to a newly created `v8::Number` object. - #[link_name = "Neon_Primitive_Number"] - pub fn number(out: &mut Local, isolate: *mut Isolate, v: f64); + /// Initializes the `out` argument with a newly created `v8::Number` object. + #[link_name = "Neon_Primitive_InitNumber"] + pub fn init_number(out: &Persistent, isolate: *mut Isolate, v: f64); /// Gets the underlying value of a `v8::Number` object. #[link_name = "Neon_Primitive_NumberValue"] - pub fn number_value(p: Local) -> f64; + pub fn number_value(p: &Persistent) -> f64; } diff --git a/crates/neon-runtime/src/raw.rs b/crates/neon-runtime/src/raw.rs index ee1291294..f015523ee 100644 --- a/crates/neon-runtime/src/raw.rs +++ b/crates/neon-runtime/src/raw.rs @@ -3,6 +3,8 @@ use std::os::raw::c_void; use std::mem; +use ::mem::{drop_persistent, new_persistent, reset_persistent}; + /// A V8 `Local` handle. /// /// `Local` handles get associated to a V8 `HandleScope` container. Note: Node.js creates a @@ -13,6 +15,51 @@ pub struct Local { pub handle: *mut c_void } +/// A V8 `Persistent` handle. +/// +/// A `Persistent` handle cannot be cloned or copied, it can only be moved. +#[repr(C)] +pub struct Persistent { + pub handle: *mut c_void +} + +impl Persistent { + pub fn new() -> Box { + let mut boxed = Box::new(unsafe { mem::zeroed() }); + + { + let persistent: &mut Persistent = &mut boxed; + unsafe { + new_persistent(persistent); + } + } + + boxed + } + + pub fn from_local(h: Local) -> Box { + let p = Persistent::new(); + + unsafe { + reset_persistent(&p, h); + } + + p + } + + pub unsafe fn placement_new(persistent: *mut Persistent) { + new_persistent(mem::transmute(persistent)); + } +} + +impl Drop for Persistent { + fn drop(&mut self) { + unsafe { + drop_persistent(self); + } + } +} + /// Represents the details of how the function was called from JavaScript. /// /// It contains the arguments used to invoke the function, the isolate reference, the `this` object diff --git a/crates/neon-runtime/src/string.rs b/crates/neon-runtime/src/string.rs index ede9ad645..199f41702 100644 --- a/crates/neon-runtime/src/string.rs +++ b/crates/neon-runtime/src/string.rs @@ -1,20 +1,20 @@ //! Facilities for working with `v8::String`s. -use raw::{Local, Isolate}; +use raw::{Isolate, Persistent}; extern "C" { /// Mutates the `out` argument provided to refer to a newly created `v8::String`. Returns /// `false` if the value couldn't be created. #[link_name = "Neon_String_New"] - pub fn new(out: &mut Local, isolate: *mut Isolate, data: *const u8, len: i32) -> bool; + pub fn new(out: &Persistent, isolate: *mut Isolate, data: *const u8, len: i32) -> bool; /// Gets the length of a `v8::String`. #[link_name = "Neon_String_Utf8Length"] - pub fn utf8_len(str: Local) -> isize; + pub fn utf8_len(str: &Persistent) -> isize; /// Writes data to a `v8::String` and returns the number of bytes writen. #[link_name = "Neon_String_Data"] - pub fn data(out: *mut u8, len: isize, str: Local) -> isize; + pub fn data(out: *mut u8, len: isize, str: &Persistent) -> isize; } diff --git a/crates/neon-runtime/src/tag.rs b/crates/neon-runtime/src/tag.rs index 8aedadab9..aac819a1b 100644 --- a/crates/neon-runtime/src/tag.rs +++ b/crates/neon-runtime/src/tag.rs @@ -1,6 +1,6 @@ //! Facilities for identifying the type of a `v8::Local` handle. -use raw::Local; +use raw::{Local, Persistent}; extern "C" { @@ -8,44 +8,56 @@ extern "C" { #[link_name = "Neon_Tag_IsUndefined"] pub fn is_undefined(val: Local) -> bool; + /// Indicates if the value type is `Undefined`. + #[link_name = "Neon_Tag_IsUndefinedThin"] + pub fn is_undefined_thin(val: &Persistent) -> bool; + /// Indicates if the value type is `Null`. #[link_name = "Neon_Tag_IsNull"] - pub fn is_null(val: Local) -> bool; + pub fn is_null(val: &Persistent) -> bool; /// Indicates if the value type is `Number`. #[link_name = "Neon_Tag_IsNumber"] - pub fn is_number(val: Local) -> bool; + pub fn is_number(val: &Persistent) -> bool; /// Indicates if the value type is `Boolean`. #[link_name = "Neon_Tag_IsBoolean"] - pub fn is_boolean(val: Local) -> bool; + pub fn is_boolean(val: &Persistent) -> bool; /// Indicates if the value type is `String`. #[link_name = "Neon_Tag_IsString"] - pub fn is_string(val: Local) -> bool; + pub fn is_string(val: &Persistent) -> bool; /// Indicates if the value type is `Object`. #[link_name = "Neon_Tag_IsObject"] pub fn is_object(val: Local) -> bool; + /// Indicates if the value type is `Object`. + #[link_name = "Neon_Tag_IsObjectThin"] + pub fn is_object_thin(val: &Persistent) -> bool; + /// Indicates if the value type is `Array`. #[link_name = "Neon_Tag_IsArray"] - pub fn is_array(val: Local) -> bool; + pub fn is_array(val: &Persistent) -> bool; /// Indicates if the value type is `Function`. #[link_name = "Neon_Tag_IsFunction"] pub fn is_function(val: Local) -> bool; + /// Indicates if the value type is `Function`. + #[link_name = "Neon_Tag_IsFunctionThin"] + pub fn is_function_thin(val: &Persistent) -> bool; + /// Indicates if the value type is `Error`. #[link_name = "Neon_Tag_IsError"] - pub fn is_error(val: Local) -> bool; + pub fn is_error(val: &Persistent) -> bool; /// Indicates if the value type is `Buffer`. #[link_name = "Neon_Tag_IsBuffer"] - pub fn is_buffer(obj: Local) -> bool; + pub fn is_buffer(val: &Persistent) -> bool; /// Indicates if the value type is `ArrayBuffer`. #[link_name = "Neon_Tag_IsArrayBuffer"] - pub fn is_arraybuffer(obj: Local) -> bool; + pub fn is_arraybuffer(val: &Persistent) -> bool; } diff --git a/src/context/internal.rs b/src/context/internal.rs index 26c9f3274..2f4eee311 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -1,14 +1,14 @@ use std; use std::cell::{Cell, RefCell}; -use std::collections::VecDeque; +use std::collections::LinkedList; use std::marker::PhantomData; use std::mem; use std::os::raw::c_void; use neon_runtime; use neon_runtime::raw; use neon_runtime::scope::Root; -use types::JsObject; -use handle::Handle; +use typed_arena::Arena; +use types::{JsObject, Managed}; use object::class::ClassMap; use result::NeonResult; use super::ModuleContext; @@ -56,7 +56,30 @@ pub struct ScopeMetadata { pub struct Scope<'a, R: Root + 'static> { pub metadata: ScopeMetadata, pub handle_scope: &'a mut R, - pub handle_arena: HandleArena<'a> + pub handle_arena: HandleArena<'a>, + pub persistent_arena: &'a PersistentArena, +} + +pub struct PersistentArena { + handles: Arena, +} + +impl PersistentArena { + fn new() -> Self { + PersistentArena { + handles: Arena::with_capacity(16), + } + } + + pub fn alloc(&self) -> &raw::Persistent { + unsafe { + let ptr = self.handles.alloc_uninitialized(1); + let ptr = ptr as *mut raw::Persistent; + raw::Persistent::placement_new(ptr); + let ptr = ptr as *const raw::Persistent; + mem::transmute(ptr) + } + } } const CHUNK_SIZE: usize = 16; @@ -64,16 +87,16 @@ const CHUNK_SIZE: usize = 16; type Chunk = [raw::Local; CHUNK_SIZE]; pub struct HandleArena<'a> { - chunks: VecDeque>, - chunk_allocated: usize, + chunks: Vec>, + pub(crate) chunk_allocated: usize, phantom: PhantomData<&'a ()> } impl<'a> HandleArena<'a> { fn new() -> Self { - let mut chunks = VecDeque::with_capacity(16); + let mut chunks = Vec::with_capacity(16); - chunks.push_back(Box::new(unsafe { mem::uninitialized() })); + chunks.push(Box::new(unsafe { mem::uninitialized() })); HandleArena { chunks, @@ -86,11 +109,11 @@ impl<'a> HandleArena<'a> { if self.chunk_allocated >= CHUNK_SIZE { let mut chunk: Box = Box::new(mem::uninitialized()); let p: *mut raw::Local = &mut chunk[0]; - self.chunks.push_back(chunk); + self.chunks.push(chunk); self.chunk_allocated = 1; p } else { - let chunk: &mut Box = self.chunks.back_mut().unwrap(); + let chunk: &mut Box = self.chunks.last_mut().unwrap(); let p: *mut raw::Local = &mut chunk[self.chunk_allocated]; self.chunk_allocated += 1; p @@ -122,6 +145,7 @@ impl<'a> HandleArena<'a> { impl<'a, R: Root + 'static> Scope<'a, R> { pub fn with FnOnce(Scope<'b, R>) -> T>(f: F) -> T { let mut handle_scope: R = unsafe { R::allocate() }; + let persistent_arena = PersistentArena::new(); let isolate = Isolate::current(); unsafe { handle_scope.enter(isolate.to_raw()); @@ -133,7 +157,8 @@ impl<'a, R: Root + 'static> Scope<'a, R> { active: Cell::new(true) }, handle_scope: &mut handle_scope, - handle_arena: HandleArena::new() + handle_arena: HandleArena::new(), + persistent_arena: &persistent_arena, }; f(scope) }; @@ -147,6 +172,7 @@ impl<'a, R: Root + 'static> Scope<'a, R> { pub trait ContextInternal<'a>: Sized { fn scope_metadata(&self) -> &ScopeMetadata; fn handle_arena(&mut self) -> &mut HandleArena<'a>; + fn persistent_arena(&self) -> &'a PersistentArena; fn isolate(&self) -> Isolate { self.scope_metadata().isolate @@ -168,10 +194,15 @@ pub trait ContextInternal<'a>: Sized { unsafe fn alloc(&mut self) -> *mut raw::Local { self.handle_arena().alloc() } + + unsafe fn alloc_persistent(&mut self) -> &'a raw::Persistent { + self.persistent_arena().alloc() + } } -pub fn initialize_module(exports: Handle, init: fn(ModuleContext) -> NeonResult<()>) { - ModuleContext::with(exports, |cx| { +pub fn initialize_module(exports: raw::Local, init: fn(ModuleContext) -> NeonResult<()>) { + let persistent = raw::Persistent::from_local(exports); + ModuleContext::with(JsObject::from_raw(&persistent), |cx| { let _ = init(cx); }); } diff --git a/src/context/mod.rs b/src/context/mod.rs index 4788b8949..99caac813 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod internal; +use std::ffi::c_void; use std; use std::cell::RefCell; use std::convert::Into; @@ -11,14 +12,13 @@ use neon_runtime; use neon_runtime::raw; use borrow::{Ref, RefMut, Borrow, BorrowMut}; use borrow::internal::Ledger; -use handle::{Managed, Handle}; -use types::{JsValue, Value, JsObject, JsArray, JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; +use types::{Value, JsValue, JsObject, /*JsArray,*/ JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined, build_infallible}; use types::binary::{JsArrayBuffer, JsBuffer}; use types::error::JsError; use object::{Object, This}; use object::class::Class; -use result::{NeonResult, JsResult, Throw}; -use self::internal::{ContextInternal, Scope, ScopeMetadata, HandleArena}; +use result::{NeonResult, Throw}; +use self::internal::{ContextInternal, Scope, ScopeMetadata, HandleArena, PersistentArena}; #[repr(C)] pub(crate) struct CallbackInfo { @@ -26,21 +26,22 @@ pub(crate) struct CallbackInfo { } impl CallbackInfo { - pub fn data<'a>(&self) -> Handle<'a, JsValue> { - unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::call::data(&self.info, &mut local); - Handle::new_internal(JsValue::from_raw(local)) - } + + pub fn data<'a, C: Context<'a>>(&self, cx: &mut C) -> &'a JsValue { + let isolate = { cx.isolate().to_raw() }; + build_infallible(cx, |out| unsafe { + neon_runtime::call::init_data(&self.info, isolate, out) + }) } pub unsafe fn with_cx FnOnce(CallContext<'a, T>) -> U>(&self, f: F) -> U { CallContext::::with(self, f) } - pub fn set_return<'a, 'b, T: Value>(&'a self, value: Handle<'b, T>) { + pub fn set_return<'a, 'b, T: Value>(&'a self, value: &'b T) { unsafe { - neon_runtime::call::set_return(&self.info, value.to_raw()) + // FIXME: Value should have a conversion function like to_raw() + neon_runtime::call::set_return_thin(&self.info, value.to_raw()); } } @@ -58,25 +59,27 @@ impl CallbackInfo { } } - pub fn get<'b, C: Context<'b>>(&self, _: &mut C, i: i32) -> Option> { + pub fn get<'b, C: Context<'b>>(&self, cx: &mut C, i: i32) -> Option<&'b JsValue> { if i < 0 || i >= self.len() { return None; } + let isolate = { cx.isolate().to_raw() }; unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::call::get(&self.info, i, &mut local); - Some(Handle::new_internal(JsValue::from_raw(local))) + Some(build_infallible(cx, |out| { + neon_runtime::call::init_get(&self.info, isolate, i, out) + })) } } - pub fn require<'b, C: Context<'b>>(&self, cx: &mut C, i: i32) -> JsResult<'b, JsValue> { + pub fn require<'b, C: Context<'b>>(&self, cx: &mut C, i: i32) -> NeonResult<&'b JsValue> { if i < 0 || i >= self.len() { return cx.throw_type_error("not enough arguments"); } + let isolate = { cx.isolate().to_raw() }; unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::call::get(&self.info, i, &mut local); - Ok(Handle::new_internal(JsValue::from_raw(local))) + Ok(build_infallible(cx, |out| { + neon_runtime::call::init_get(&self.info, isolate, i, out) + })) } } @@ -132,20 +135,14 @@ pub trait Context<'a>: ContextInternal<'a> { /// /// ```no_run /// # use neon::prelude::*; - /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult { - /// let b: Handle = cx.argument(0)?; - /// let x: u32 = cx.borrow(&b, |data| { data.as_slice()[0] }); - /// let n: Handle = cx.number(x); + /// # fn my_neon_function(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + /// let b: &JsArrayBuffer = cx.argument(0)?; + /// let x: u32 = cx.borrow(b, |data| { data.as_slice()[0] }); + /// let n: &JsNumber = cx.number(x); /// # Ok(n) /// # } /// ``` - /// - /// Note: the borrowed value is required to be a reference to a handle instead of a handle - /// as a workaround for a [Rust compiler bug](https://github.com/rust-lang/rust/issues/29997). - /// We may be able to generalize this compatibly in the future when the Rust bug is fixed, - /// but while the extra `&` is a small ergonomics regression, this API is still a nice - /// convenience. - fn borrow<'c, V, T, F>(&self, v: &'c Handle, f: F) -> T + fn borrow<'c, V, T, F>(&self, v: &'c V, f: F) -> T where V: Value, &'c V: Borrow, F: for<'b> FnOnce(Ref<'b, <&'c V as Borrow>::Target>) -> T @@ -162,30 +159,25 @@ pub trait Context<'a>: ContextInternal<'a> { /// ```no_run /// # use neon::prelude::*; /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult { - /// let mut b: Handle = cx.argument(0)?; - /// cx.borrow_mut(&mut b, |data| { + /// let mut b: &JsArrayBuffer = cx.argument(0)?; + /// cx.borrow_mut(&b, |data| { /// let slice = data.as_mut_slice::(); /// slice[0] += 1; /// }); /// # Ok(cx.undefined()) /// # } /// ``` - /// - /// Note: the borrowed value is required to be a reference to a handle instead of a handle - /// as a workaround for a [Rust compiler bug](https://github.com/rust-lang/rust/issues/29997). - /// We may be able to generalize this compatibly in the future when the Rust bug is fixed, - /// but while the extra `&mut` is a small ergonomics regression, this API is still a nice - /// convenience. - fn borrow_mut<'c, V, T, F>(&self, v: &'c mut Handle, f: F) -> T + fn borrow_mut<'c, V, T, F>(&self, v: &'c V, f: F) -> T where V: Value, - &'c mut V: BorrowMut, - F: for<'b> FnOnce(RefMut<'b, <&'c mut V as Borrow>::Target>) -> T + &'c V: BorrowMut, + F: for<'b> FnOnce(RefMut<'b, <&'c V as Borrow>::Target>) -> T { let lock = self.lock(); let contents = v.borrow_mut(&lock); f(contents) } +/* /// Executes a computation in a new memory management scope. /// /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape. @@ -224,21 +216,22 @@ pub trait Context<'a>: ContextInternal<'a> { self.activate(); result } +*/ /// Convenience method for creating a `JsBoolean` value. - fn boolean(&mut self, b: bool) -> Handle<'a, JsBoolean> { + fn boolean(&mut self, b: bool) -> &'a JsBoolean { JsBoolean::new(self, b) } /// Convenience method for creating a `JsNumber` value. - fn number>(&mut self, x: T) -> Handle<'a, JsNumber> { - JsNumber::new(self, x.into()) + fn number>(&mut self, x: T) -> &'a JsNumber { + JsNumber::new(self, x) } /// Convenience method for creating a `JsString` value. /// /// If the string exceeds the limits of the JS engine, this method panics. - fn string>(&mut self, s: S) -> Handle<'a, JsString> { + fn string>(&mut self, s: S) -> &'a JsString { JsString::new(self, s) } @@ -250,51 +243,49 @@ pub trait Context<'a>: ContextInternal<'a> { } /// Convenience method for creating a `JsNull` value. - fn null(&mut self) -> Handle<'a, JsNull> { - JsNull::new() - } - - /// Convenience method for creating a `JsUndefined` value. - fn undefined(&mut self) -> Handle<'a, JsUndefined> { - JsUndefined::new() + fn null(&mut self) -> &'a JsNull { + JsNull::new(self) } /// Convenience method for creating a `JsUndefined` value. - fn undefined_thin(&mut self) -> &'a JsUndefined { - JsUndefined::new_thin(self) + fn undefined(&mut self) -> &'a JsUndefined { + JsUndefined::new(self) } /// Convenience method for creating an empty `JsObject` value. - fn empty_object(&mut self) -> Handle<'a, JsObject> { + fn empty_object(&mut self) -> &'a JsObject { JsObject::new(self) } +/* /// Convenience method for creating an empty `JsArray` value. - fn empty_array(&mut self) -> Handle<'a, JsArray> { + fn empty_array(&mut self) -> &'a JsArray { JsArray::new(self, 0) } +*/ /// Convenience method for creating an empty `JsArrayBuffer` value. - fn array_buffer(&mut self, size: u32) -> JsResult<'a, JsArrayBuffer> { + fn array_buffer(&mut self, size: u32) -> NeonResult<&'a JsArrayBuffer> { JsArrayBuffer::new(self, size) } /// Convenience method for creating an empty `JsBuffer` value. - fn buffer(&mut self, size: u32) -> JsResult<'a, JsBuffer> { + fn buffer(&mut self, size: u32) -> NeonResult<&'a JsBuffer> { JsBuffer::new(self, size) } /// Produces a handle to the JavaScript global object. - fn global(&mut self) -> Handle<'a, JsObject> { - JsObject::build(|out| { + fn global(&mut self) -> &'a JsObject { + let isolate = self.isolate().to_raw(); + JsObject::build(self, |out| { unsafe { - neon_runtime::scope::get_global(self.isolate().to_raw(), out); + neon_runtime::scope::get_global(isolate, out); } }) } /// Throws a JS value. - fn throw<'b, T: Value, U>(&mut self, v: Handle<'b, T>) -> NeonResult { + fn throw<'b, T: Value, U>(&mut self, v: &'b T) -> NeonResult { unsafe { neon_runtime::error::throw(v.to_raw()); } @@ -302,17 +293,17 @@ pub trait Context<'a>: ContextInternal<'a> { } /// Creates a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class. - fn error>(&mut self, msg: S) -> JsResult<'a, JsError> { + fn error>(&mut self, msg: S) -> NeonResult<&'a JsError> { JsError::error(self, msg) } /// Creates an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class. - fn type_error>(&mut self, msg: S) -> JsResult<'a, JsError> { + fn type_error>(&mut self, msg: S) -> NeonResult<&'a JsError> { JsError::type_error(self, msg) } /// Creates an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class. - fn range_error>(&mut self, msg: S) -> JsResult<'a, JsError> { + fn range_error>(&mut self, msg: S) -> NeonResult<&'a JsError> { JsError::range_error(self, msg) } @@ -338,13 +329,13 @@ pub trait Context<'a>: ContextInternal<'a> { /// A view of the JS engine in the context of top-level initialization of a Neon module. pub struct ModuleContext<'a> { scope: Scope<'a, raw::HandleScope>, - exports: Handle<'a, JsObject> + exports: &'a JsObject, } impl<'a> UnwindSafe for ModuleContext<'a> { } impl<'a> ModuleContext<'a> { - pub(crate) fn with FnOnce(ModuleContext<'b>) -> T>(exports: Handle<'a, JsObject>, f: F) -> T { + pub(crate) fn with FnOnce(ModuleContext<'b>) -> T>(exports: &'a JsObject, f: F) -> T { debug_assert!(unsafe { neon_runtime::scope::size() } <= std::mem::size_of::()); debug_assert!(unsafe { neon_runtime::scope::alignment() } <= std::mem::align_of::()); Scope::with(|scope| { @@ -356,27 +347,31 @@ impl<'a> ModuleContext<'a> { } /// Convenience method for exporting a Neon function from a module. - pub fn export_function(&mut self, key: &str, f: fn(FunctionContext) -> JsResult) -> NeonResult<()> { - let value = JsFunction::new(self, f)?.upcast::(); + pub fn export_function(&mut self, key: &str, f: fn(FunctionContext) -> NeonResult<&T>) -> NeonResult<()> { + let value = JsFunction::new(self, f)?; self.exports.set(self, key, value)?; Ok(()) } /// Convenience method for exporting a Neon class constructor from a module. pub fn export_class(&mut self, key: &str) -> NeonResult<()> { + // FIXME: implement this + /* let constructor = T::constructor(self)?; self.exports.set(self, key, constructor)?; Ok(()) + */ + unimplemented!() } /// Exports a JavaScript value from a Neon module. - pub fn export_value(&mut self, key: &str, val: Handle) -> NeonResult<()> { + pub fn export_value(&mut self, key: &str, val: &T) -> NeonResult<()> { self.exports.set(self, key, val)?; Ok(()) } /// Produces a handle to a module's exports object. - pub fn exports_object(&mut self) -> JsResult<'a, JsObject> { + pub fn exports_object(&mut self) -> NeonResult<&'a JsObject> { Ok(self.exports) } } @@ -389,10 +384,15 @@ impl<'a> ContextInternal<'a> for ModuleContext<'a> { fn handle_arena(&mut self) -> &mut HandleArena<'a> { &mut self.scope.handle_arena } + + fn persistent_arena(&self) -> &'a PersistentArena { + self.scope.persistent_arena + } } impl<'a> Context<'a> for ModuleContext<'a> { } +/* /// A view of the JS engine in the context of a scoped computation started by `Context::execute_scoped()`. pub struct ExecuteContext<'a> { scope: Scope<'a, raw::HandleScope> @@ -414,6 +414,10 @@ impl<'a> ContextInternal<'a> for ExecuteContext<'a> { fn handle_arena(&mut self) -> &mut HandleArena<'a> { &mut self.scope.handle_arena } + + fn persistent_arena(&self) -> &'a PersistentArena { + self.scope.persistent_arena + } } impl<'a> Context<'a> for ExecuteContext<'a> { } @@ -445,9 +449,14 @@ impl<'a, 'b> ContextInternal<'a> for ComputeContext<'a, 'b> { fn handle_arena(&mut self) -> &mut HandleArena<'a> { &mut self.scope.handle_arena } + + fn persistent_arena(&self) -> &'a PersistentArena { + self.scope.persistent_arena + } } impl<'a, 'b> Context<'a> for ComputeContext<'a, 'b> { } +*/ /// A view of the JS engine in the context of a function call. /// @@ -478,20 +487,22 @@ impl<'a, T: This> CallContext<'a, T> { pub fn len(&self) -> i32 { self.info.len() } /// Produces the `i`th argument, or `None` if `i` is greater than or equal to `self.len()`. - pub fn argument_opt(&mut self, i: i32) -> Option> { + pub fn argument_opt(&mut self, i: i32) -> Option<&'a JsValue> { self.info.get(self, i) } /// 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> { + pub fn argument(&mut self, i: i32) -> NeonResult<&'a V> { let a = self.info.require(self, i)?; a.downcast_or_throw(self) } +/* /// Produces a handle to the `this`-binding. pub fn this(&mut self) -> Handle<'a, T> { Handle::new_internal(T::as_this(self.info.this(self))) } +*/ } impl<'a, T: This> ContextInternal<'a> for CallContext<'a, T> { @@ -502,6 +513,10 @@ impl<'a, T: This> ContextInternal<'a> for CallContext<'a, T> { fn handle_arena(&mut self) -> &mut HandleArena<'a> { &mut self.scope.handle_arena } + + fn persistent_arena(&self) -> &'a PersistentArena { + self.scope.persistent_arena + } } impl<'a, T: This> Context<'a> for CallContext<'a, T> { } @@ -535,6 +550,10 @@ impl<'a> ContextInternal<'a> for TaskContext<'a> { fn handle_arena(&mut self) -> &mut HandleArena<'a> { &mut self.scope.handle_arena } + + fn persistent_arena(&self) -> &'a PersistentArena { + self.scope.persistent_arena + } } impl<'a> Context<'a> for TaskContext<'a> { } diff --git a/src/handle/internal.rs b/src/handle/internal.rs deleted file mode 100644 index 384606053..000000000 --- a/src/handle/internal.rs +++ /dev/null @@ -1,5 +0,0 @@ -use types::Value; - -pub trait SuperType { - fn upcast_internal(T) -> Self; -} diff --git a/src/handle/mod.rs b/src/handle/mod.rs deleted file mode 100644 index 88aece4ba..000000000 --- a/src/handle/mod.rs +++ /dev/null @@ -1,154 +0,0 @@ -//! Safe _handles_ to managed JavaScript memory. - -pub(crate) mod internal; - -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; -use std::error::Error; -use std::fmt::{self, Debug, Display}; -use neon_runtime; -use neon_runtime::raw; -use types::Value; -use context::Context; -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 { - fn to_raw(self) -> raw::Local; - - fn from_raw(h: raw::Local) -> Self; -} - -/// A safely rooted _handle_ to a JS value in memory that is managed by the garbage collector. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct Handle<'a, T: Managed + 'a> { - value: T, - phantom: PhantomData<&'a T> -} - -impl<'a, T: Managed + 'a> PartialEq for Handle<'a, T> { - fn eq(&self, other: &Self) -> bool { - unsafe { neon_runtime::mem::same_handle(self.to_raw(), other.to_raw()) } - } -} - -impl<'a, T: Managed + 'a> Eq for Handle<'a, T> { } - -impl<'a, T: Managed + 'a> Handle<'a, T> { - pub(crate) fn new_internal(value: T) -> Handle<'a, T> { - Handle { - value: value, - phantom: PhantomData - } - } -} - -/// An error representing a failed downcast. -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] -pub struct DowncastError { - phantom_from: PhantomData, - phantom_to: PhantomData, - description: String -} - -impl Debug for DowncastError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "DowncastError") - } -} - -impl DowncastError { - fn new() -> Self { - DowncastError { - phantom_from: PhantomData, - phantom_to: PhantomData, - description: format!("failed downcast to {}", T::name()) - } - } -} - -impl Display for DowncastError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{}", self.description()) - } -} - -impl Error for DowncastError { - fn description(&self) -> &str { - &self.description - } -} - -/// The result of a call to `Handle::downcast()`. -pub type DowncastResult<'a, F, T> = Result, DowncastError>; - -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) - } - } -} - -impl<'a, T: Value> Handle<'a, T> { - - /// Safely upcast a handle to a supertype. - /// - /// This method does not require an execution context because it only copies a handle. - pub fn upcast>(&self) -> Handle<'a, U> { - Handle::new_internal(SuperType::upcast_internal(self.value)) - } - - /// Tests whether this value is an instance of the given type. - /// - /// # Example: - /// - /// ```no_run - /// # use neon::prelude::*; - /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult { - /// let v: Handle = cx.number(17).upcast(); - /// v.is_a::(); // false - /// v.is_a::(); // true - /// v.is_a::(); // true - /// # Ok(cx.undefined()) - /// # } - /// ``` - pub fn is_a(&self) -> bool { - U::is_typeof(self.value) - } - - /// 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)), - None => Err(DowncastError::new()) - } - } - - /// 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> { - type Target = T; - fn deref<'b>(&'b self) -> &'b T { - &self.value - } -} - -impl<'a, T: Managed> DerefMut for Handle<'a, T> { - fn deref_mut<'b>(&'b mut self) -> &'b mut T { - &mut self.value - } -} diff --git a/src/lib.rs b/src/lib.rs index 876716333..15102f271 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ extern crate neon_runtime; extern crate cslice; extern crate semver; +extern crate typed_arena; #[cfg(test)] extern crate rustc_version; @@ -12,7 +13,6 @@ extern crate rustc_version; extern crate lazy_static; pub mod context; -pub mod handle; pub mod types; pub mod object; pub mod borrow; @@ -61,9 +61,9 @@ macro_rules! register_module { dso_handle: *mut u8, filename: *const u8, register_func: Option, *mut u8, *mut u8)>, + $crate::macro_internal::runtime::raw::Local, *mut u8, *mut u8)>, context_register_func: Option, *mut u8, *mut u8, *mut u8)>, + $crate::macro_internal::runtime::raw::Local, *mut u8, *mut u8, *mut u8)>, modname: *const u8, priv_data: *mut u8, link: *mut __NodeModule @@ -82,7 +82,7 @@ macro_rules! register_module { }; extern "C" fn __register_neon_module( - m: $crate::handle::Handle<$crate::types::JsObject>, _: *mut u8, _: *mut u8) { + m: $crate::macro_internal::runtime::raw::Local, _: *mut u8, _: *mut u8) { $crate::macro_internal::initialize_module(m, __init_neon_module); } @@ -135,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::result::JsResult<$crate::types::JsValue> { + fn _______method_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$cls>) -> $crate::result::NeonResult<&$crate::types::JsValue> { $body } @@ -151,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 } @@ -168,7 +168,7 @@ macro_rules! class_definition { $typ ; $allocator ; ({ - fn _______call_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$crate::types::JsValue>) -> $crate::result::JsResult<$crate::types::JsValue> { + fn _______call_rust_y_u_no_hygienic_items_______($cx: $crate::context::CallContext<$crate::types::JsValue>) -> $crate::result::NeonResult<&$crate::types::JsValue> { $body } @@ -198,16 +198,7 @@ macro_rules! class_definition { #[macro_export] macro_rules! impl_managed { ($cls:ident) => { - impl $crate::handle::Managed for $cls { - fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local { - let $cls(raw) = self; - raw - } - - fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self { - $cls(raw) - } - } + impl $crate::types::Managed for $cls { } } } diff --git a/src/object/class/internal.rs b/src/object/class/internal.rs index b04757fc2..b0da2de9d 100644 --- a/src/object/class/internal.rs +++ b/src/object/class/internal.rs @@ -4,18 +4,19 @@ use std::ptr::null_mut; use neon_runtime; use neon_runtime::raw; use super::{Class, ClassInternal, Callback}; -use handle::{Handle, Managed}; use context::{CallbackInfo, CallContext, Context}; use context::internal::ContextInternal; -use result::{NeonResult, JsResult, Throw}; -use types::{JsValue, JsObject, JsFunction, JsUndefined, build}; +use result::{NeonResult, Throw}; +use types::{JsFunction, JsValue, JsObject, JsUndefined, Managed}; use types::error::convert_panics; #[repr(C)] -pub struct MethodCallback(pub fn(CallContext) -> JsResult); +pub struct MethodCallback(pub fn(CallContext) -> NeonResult<&JsValue>); impl Callback<()> for MethodCallback { extern "C" fn invoke(info: &CallbackInfo) { + // FIXME: implement this + /* unsafe { info.with_cx::(|mut cx| { let data = info.data(); @@ -33,7 +34,9 @@ impl Callback<()> for MethodCallback { } }) } - } + */ + unimplemented!() + } fn as_ptr(self) -> *mut c_void { self.0 as *mut c_void @@ -41,11 +44,11 @@ impl Callback<()> for MethodCallback { } #[repr(C)] -pub struct ConstructorCallCallback(pub fn(CallContext) -> JsResult); +pub struct ConstructorCallCallback(pub fn(CallContext) -> NeonResult<&JsValue>); impl ConstructorCallCallback { pub(crate) fn default() -> Self { - fn callback(mut cx: CallContext) -> JsResult { + fn callback(mut cx: CallContext) -> NeonResult<&JsValue> { unsafe { if let Ok(metadata) = T::metadata(&mut cx) { neon_runtime::class::throw_call_error(mem::transmute(cx.isolate()), metadata.pointer); @@ -61,9 +64,9 @@ impl ConstructorCallCallback { impl Callback<()> for ConstructorCallCallback { extern "C" fn invoke(info: &CallbackInfo) { unsafe { - info.with_cx(|cx| { - let data = info.data(); - let kernel: fn(CallContext) -> JsResult = + info.with_cx(|mut cx| { + let data = info.data(&mut cx); + let kernel: fn(CallContext) -> NeonResult<&JsValue> = mem::transmute(neon_runtime::class::get_call_kernel(data.to_raw())); if let Ok(value) = convert_panics(|| { kernel(cx) }) { info.set_return(value); @@ -83,8 +86,8 @@ pub struct AllocateCallback(pub fn(CallContext) -> NeonRe impl Callback<*mut c_void> for AllocateCallback { extern "C" fn invoke(info: &CallbackInfo) -> *mut c_void { unsafe { - info.with_cx(|cx| { - let data = info.data(); + info.with_cx(|mut cx| { + let data = info.data(&mut cx); let kernel: fn(CallContext) -> NeonResult = mem::transmute(neon_runtime::class::get_allocate_kernel(data.to_raw())); if let Ok(value) = convert_panics(|| { kernel(cx) }) { @@ -103,14 +106,14 @@ impl Callback<*mut c_void> for AllocateCallback { } #[repr(C)] -pub struct ConstructCallback(pub fn(CallContext) -> NeonResult>>); +pub struct ConstructCallback(pub fn(CallContext) -> NeonResult>); impl Callback for ConstructCallback { extern "C" fn invoke(info: &CallbackInfo) -> bool { unsafe { - info.with_cx(|cx| { - let data = info.data(); - let kernel: fn(CallContext) -> NeonResult>> = + info.with_cx(|mut cx| { + let data = info.data(&mut cx); + let kernel: fn(CallContext) -> NeonResult> = mem::transmute(neon_runtime::class::get_construct_kernel(data.to_raw())); match convert_panics(|| { kernel(cx) }) { Ok(None) => true, @@ -136,10 +139,14 @@ pub struct ClassMetadata { } impl ClassMetadata { - pub unsafe fn constructor<'a, T: Class, C: Context<'a>>(&self, cx: &mut C) -> JsResult<'a, JsFunction> { + pub unsafe fn constructor<'a, T: Class, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsFunction> { + // FIXME: implement this + unimplemented!() + /* build(|out| { neon_runtime::class::metadata_to_constructor(out, mem::transmute(cx.isolate()), self.pointer) }) + */ } pub unsafe fn has_instance(&self, value: raw::Local) -> bool { diff --git a/src/object/class/mod.rs b/src/object/class/mod.rs index 9a399ec0f..48aa984e9 100644 --- a/src/object/class/mod.rs +++ b/src/object/class/mod.rs @@ -12,10 +12,9 @@ use neon_runtime::raw; use neon_runtime::call::CCallback; use context::{Context, Lock, CallbackInfo}; use context::internal::Isolate; -use result::{NeonResult, JsResult, Throw}; +use result::{NeonResult, Throw}; use borrow::{Borrow, BorrowMut, Ref, RefMut, LoanError}; -use handle::{Handle, Managed}; -use types::{Value, JsFunction, JsValue, build}; +use types::{JsFunction, JsValue, Managed, Value}; use types::internal::ValueInternal; use object::{Object, This}; use self::internal::{ClassMetadata, MethodCallback, ConstructorCallCallback, AllocateCallback, ConstructCallback}; @@ -98,18 +97,26 @@ pub trait Class: Managed + Any { fn setup<'a, C: Context<'a>>(_: &mut C) -> NeonResult>; /// Produces a handle to the constructor function for this class. - fn constructor<'a, C: Context<'a>>(cx: &mut C) -> JsResult<'a, JsFunction> { + fn constructor<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'a JsFunction> { + // FIXME: implement this +/* let metadata = Self::metadata(cx)?; unsafe { metadata.constructor(cx) } +*/ + unimplemented!() } /// Convenience method for constructing new instances of this class without having to extract the constructor function. - fn new<'a, 'b, C: Context<'a>, A, AS>(cx: &mut C, args: AS) -> JsResult<'a, Self> + fn new<'a, 'b, C: Context<'a>, A, AS>(cx: &mut C, args: AS) -> NeonResult<&'a Self> where A: Value + 'b, - AS: IntoIterator> + AS: IntoIterator { + // FIXME: implement this +/* let constructor = Self::constructor(cx)?; constructor.construct(cx, args) +*/ + unimplemented!() } #[doc(hidden)] @@ -118,11 +125,7 @@ pub trait Class: Managed + Any { } } -unsafe impl This for T { - fn as_this(h: raw::Local) -> Self { - Self::from_raw(h) - } -} +unsafe impl This for T { } impl Object for T { } @@ -169,6 +172,8 @@ pub(crate) trait ClassInternal: Class { } for (name, method) in descriptor.methods { + // FIXME: implement this with JsValue + /* let method: Handle = build(|out| { let callback = method.into_c_callback(); neon_runtime::fun::new_template(out, isolate, callback) @@ -176,6 +181,7 @@ pub(crate) trait ClassInternal: Class { if !neon_runtime::class::add_method(isolate, metadata_pointer, name.as_ptr(), name.len() as u32, method.to_raw()) { return Err(Throw); } + */ } let metadata = ClassMetadata { @@ -193,6 +199,8 @@ impl ClassInternal for T { } impl ValueInternal for T { fn name() -> String { + // FIXME: implement this + /* let mut isolate: Isolate = unsafe { mem::transmute(neon_runtime::call::current_isolate()) }; @@ -207,9 +215,13 @@ impl ValueInternal for T { String::from_utf8_lossy(slice::from_raw_parts_mut(chars, len)).to_string() } } + */ + unimplemented!() } - fn is_typeof(value: Other) -> bool { + fn is_typeof(value: &Other) -> bool { + // FIXME: implement this + /* let mut isolate: Isolate = unsafe { mem::transmute(neon_runtime::call::current_isolate()) }; @@ -220,6 +232,8 @@ impl ValueInternal for T { metadata.has_instance(value.to_raw()) } } + */ + unimplemented!() } } @@ -229,10 +243,14 @@ impl<'a, T: Class> Borrow for &'a T { type Target = &'a mut T::Internals; fn try_borrow<'b>(self, lock: &'b Lock<'b>) -> Result, LoanError> { + // FIXME: implement this + /* unsafe { let ptr: *mut c_void = neon_runtime::class::get_instance_internals(self.to_raw()); Ref::new(lock, mem::transmute(ptr)) } + */ + unimplemented!() } } @@ -246,10 +264,14 @@ impl<'a, T: Class> Borrow for &'a mut T { impl<'a, T: Class> BorrowMut for &'a mut T { fn try_borrow_mut<'b>(self, lock: &'b Lock<'b>) -> Result, LoanError> { + // FIXME: implement this + /* unsafe { let ptr: *mut c_void = neon_runtime::class::get_instance_internals(self.to_raw()); RefMut::new(lock, mem::transmute(ptr)) } + */ + unimplemented!() } } @@ -275,4 +297,5 @@ pub(crate) trait Callback: Sized { dynamic_callback: self.as_ptr() } } + } diff --git a/src/object/mod.rs b/src/object/mod.rs index bdb91d1fe..9d879fb99 100644 --- a/src/object/mod.rs +++ b/src/object/mod.rs @@ -4,63 +4,68 @@ pub(crate) mod class; use neon_runtime; use neon_runtime::raw; -use handle::{Handle, Managed}; -use types::{Value, JsValue, JsArray, build}; +use types::{JsValue, JsArray, Managed, Value, build}; use types::utf8::Utf8; use context::Context; -use result::{NeonResult, JsResult, Throw}; +use result::{NeonResult, Throw}; pub use self::class::{Class, ClassDescriptor}; /// A property key in a JavaScript object. pub trait PropertyKey { - unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool; - unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool; + unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool; + unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool; } impl PropertyKey for u32 { - unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool { - neon_runtime::object::get_index(out, obj, self) + unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { + // FIXME: implement this + // was: neon_runtime::object::get_index(out, obj, self) + unimplemented!() } - unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool { - neon_runtime::object::set_index(out, obj, self, val) + unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { + // FIXME: implement this + // was: neon_runtime::object::set_index(out, obj, self, val) + unimplemented!() } } -impl<'a, K: Value> PropertyKey for Handle<'a, K> { - unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool { - neon_runtime::object::get(out, obj, self.to_raw()) +impl<'a> PropertyKey for &'a str { + unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { + let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); + neon_runtime::object::get_string_thin(out, obj, ptr, len) } - unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool { - neon_runtime::object::set(out, obj, self.to_raw(), val) + unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { + let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); + neon_runtime::object::set_string_thin(out, obj, ptr, len, val) } } -impl<'a> PropertyKey for &'a str { - unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool { - let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); - neon_runtime::object::get_string(out, obj, ptr, len) +impl<'a, T: Value> PropertyKey for &'a T { + unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { + neon_runtime::object::get_thin(out, obj, self.to_raw()) } - unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool { - let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); - neon_runtime::object::set_string(out, obj, ptr, len, val) + unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { + neon_runtime::object::set_thin(out, obj, self.to_raw(), val) } } -/// The trait of all object types. pub trait Object: Value { - fn get<'a, C: Context<'a>, K: PropertyKey>(self, _: &mut C, key: K) -> NeonResult> { - build(|out| { unsafe { key.get_from(out, self.to_raw()) } }) + fn get<'a, C: Context<'a>, K: PropertyKey>(&self, cx: &mut C, key: K) -> NeonResult<&'a JsValue> { + build(cx, |out| { unsafe { key.get_from(out, self.to_raw()) } }) } - fn get_own_property_names<'a, C: Context<'a>>(self, _: &mut C) -> JsResult<'a, JsArray> { - build(|out| { unsafe { neon_runtime::object::get_own_property_names(out, self.to_raw()) } }) + fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsArray> { + let isolate = { cx.isolate().to_raw() }; + build(cx, |out| unsafe { + neon_runtime::object::get_own_property_names(out, isolate, self.to_raw()) + }) } - fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(self, _: &mut C, key: K, val: Handle) -> NeonResult { + fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(&self, _: &mut C, key: K, val: &W) -> NeonResult { let mut result = false; if unsafe { key.set_from(&mut result, self.to_raw(), val.to_raw()) } { Ok(result) @@ -72,5 +77,7 @@ pub trait Object: Value { /// The trait of types that can be a function's `this` binding. pub unsafe trait This: Managed { - fn as_this(h: raw::Local) -> Self; + fn as_this(h: &raw::Persistent) -> &Self { + Self::from_raw(h) + } } diff --git a/src/prelude.rs b/src/prelude.rs index 1d2296cfc..af51c3434 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,9 +1,8 @@ //! A convenience module that re-exports the most commonly-used Neon APIs. -pub use handle::Handle; -pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, Value, JsValue, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, JsObject, JsArray, JsFunction}; +pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, /*JsObject,*/ /*JsArray,*/ JsFunction, Value}; 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, JsResult, JsResultExt}; +pub use context::{CallKind, Context, ModuleContext, /*ExecuteContext, ComputeContext,*/ CallContext, FunctionContext, MethodContext, TaskContext}; +pub use result::NeonResult; pub use task::Task; diff --git a/src/result/mod.rs b/src/result/mod.rs index abb184b1c..7eff0de8f 100644 --- a/src/result/mod.rs +++ b/src/result/mod.rs @@ -1,7 +1,6 @@ //! Types and traits for working with JavaScript exceptions. use std::fmt::{Display, Formatter, Result as FmtResult}; -use handle::Handle; use types::Value; use context::Context; @@ -23,11 +22,8 @@ impl Display 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 JsResultExt<'a, V: Value> { - fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>; +/// An extension trait for `Result` values that can be converted into `NeonResult` values by +/// throwsing a JavaScript exception in the error case. +pub trait NeonResultExt<'a, V: Value> { + fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> NeonResult<&'a V>; } diff --git a/src/task/mod.rs b/src/task/mod.rs index cd37112cf..e32e2dfad 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -5,8 +5,7 @@ use std::mem; use std::os::raw::c_void; use types::{Value, JsFunction}; -use result::JsResult; -use handle::{Handle, Managed}; +use result::NeonResult; use context::TaskContext; use neon_runtime; use neon_runtime::raw; @@ -26,7 +25,7 @@ pub trait Task: Send + Sized + 'static { fn perform(&self) -> Result; /// Convert the result of the task to a JavaScript value to be passed to the asynchronous callback. This method is executed on the main thread at some point after the background task is completed. - fn complete<'a>(self, cx: TaskContext<'a>, result: Result) -> JsResult; + fn complete<'a>(self, cx: TaskContext<'a>, result: Result) -> NeonResult<&'a Self::JsEvent>; /// Schedule a task to be executed on a background thread. /// @@ -35,7 +34,9 @@ pub trait Task: Send + Sized + 'static { /// ```js /// function callback(err, value) {} /// ``` - fn schedule(self, callback: Handle) { + fn schedule(self, callback: &JsFunction) { + // FIXME: implement +/* let boxed_self = Box::new(self); let self_raw = Box::into_raw(boxed_self); let callback_raw = callback.to_raw(); @@ -45,6 +46,7 @@ pub trait Task: Send + Sized + 'static { complete_task::, callback_raw); } +*/ } } @@ -55,6 +57,9 @@ unsafe extern "C" fn perform_task(task: *mut c_void) -> *mut c_void { mem::transmute(Box::into_raw(Box::new(result))) } +// FIXME: thinify this: + +/* unsafe extern "C" fn complete_task(task: *mut c_void, result: *mut c_void, out: &mut raw::Local) { let result: Result = *Box::from_raw(mem::transmute(result)); let task: Box = Box::from_raw(mem::transmute(task)); @@ -64,3 +69,4 @@ unsafe extern "C" fn complete_task(task: *mut c_void, result: *mut c_vo } }) } +*/ diff --git a/src/types/binary.rs b/src/types/binary.rs index be870a667..06d7e8157 100644 --- a/src/types/binary.rs +++ b/src/types/binary.rs @@ -7,42 +7,42 @@ use std::slice; use context::{Context, Lock}; use borrow::{Borrow, BorrowMut, Ref, RefMut, LoanError}; use borrow::internal::Pointer; -use handle::Managed; -use types::{Value, Object, build}; +use types::{Object, Managed, Value, build}; use types::internal::ValueInternal; -use result::JsResult; +use result::NeonResult; use neon_runtime; use neon_runtime::raw; /// The Node [`Buffer`](https://nodejs.org/api/buffer.html) type. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsBuffer(raw::Local); +pub struct JsBuffer(raw::Persistent); impl JsBuffer { /// Constructs a new `Buffer` object, safely zero-filled. - pub fn new<'a, C: Context<'a>>(_: &mut C, size: u32) -> JsResult<'a, JsBuffer> { - build(|out| { unsafe { neon_runtime::buffer::new(out, size) } }) + pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { + let isolate = cx.isolate().to_raw(); + build(cx, |out| { + unsafe { neon_runtime::buffer::init_safe(out, isolate, size) } + }) } - /// Constructs a new `Buffer` object, safely zero-filled. - pub unsafe fn uninitialized<'a, C: Context<'a>>(_: &mut C, size: u32) -> JsResult<'a, JsBuffer> { - build(|out| { neon_runtime::buffer::uninitialized(out, size) }) + /// Constructs a new `Buffer` object, unsafely filled with uninitialized data. + pub unsafe fn uninitialized<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { + let isolate = cx.isolate().to_raw(); + build(cx, |out| { + unsafe { neon_runtime::buffer::init_unsafe(out, isolate, size) } + }) } } -impl Managed for JsBuffer { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsBuffer(h) } -} +impl Managed for JsBuffer { } impl ValueInternal for JsBuffer { fn name() -> String { "Buffer".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_buffer(other.to_raw()) } } } @@ -53,28 +53,26 @@ impl Object for JsBuffer { } /// The standard JS [`ArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) type. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsArrayBuffer(raw::Local); +pub struct JsArrayBuffer(raw::Persistent); impl JsArrayBuffer { /// Constructs a new `ArrayBuffer` object with the given size, in bytes. - pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> JsResult<'a, JsArrayBuffer> { - build(|out| { unsafe { neon_runtime::arraybuffer::new(out, mem::transmute(cx.isolate()), size) } }) + pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsArrayBuffer> { + let isolate = { cx.isolate().to_raw() }; + build(cx, |out| { + unsafe { neon_runtime::arraybuffer::init(out, isolate, size) } + }) } } -impl Managed for JsArrayBuffer { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsArrayBuffer(h) } -} +impl Managed for JsArrayBuffer { } impl ValueInternal for JsArrayBuffer { fn name() -> String { "ArrayBuffer".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_arraybuffer(other.to_raw()) } } } @@ -180,15 +178,7 @@ impl<'a> Borrow for &'a JsBuffer { } } -impl<'a> Borrow for &'a mut JsBuffer { - type Target = BinaryData<'a>; - - fn try_borrow<'b>(self, guard: &'b Lock<'b>) -> Result, LoanError> { - (self as &'a JsBuffer).try_borrow(guard) - } -} - -impl<'a> BorrowMut for &'a mut JsBuffer { +impl<'a> BorrowMut for &'a JsBuffer { fn try_borrow_mut<'b>(self, guard: &'b Lock<'b>) -> Result, LoanError> { let mut pointer: BinaryData = unsafe { mem::uninitialized() }; unsafe { @@ -210,15 +200,7 @@ impl<'a> Borrow for &'a JsArrayBuffer { } } -impl<'a> Borrow for &'a mut JsArrayBuffer { - type Target = BinaryData<'a>; - - fn try_borrow<'b>(self, guard: &'b Lock<'b>) -> Result, LoanError> { - (self as &'a JsArrayBuffer).try_borrow(guard) - } -} - -impl<'a> BorrowMut for &'a mut JsArrayBuffer { +impl<'a> BorrowMut for &'a JsArrayBuffer { fn try_borrow_mut<'b>(self, guard: &'b Lock<'b>) -> Result, LoanError> { let mut pointer: BinaryData = unsafe { mem::uninitialized() }; unsafe { diff --git a/src/types/error.rs b/src/types/error.rs index 8b8f3e51e..2de273d70 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -7,25 +7,19 @@ use neon_runtime::raw; use context::Context; use result::{NeonResult, Throw}; -use types::{Value, Object, Handle, Managed, build}; -use types::internal::ValueInternal; +use types::{Object, Value, ValueInternal, Managed, build}; use types::utf8::Utf8; /// A JS `Error` object. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsError(raw::Local); +pub struct JsError(raw::Persistent); -impl Managed for JsError { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsError(h) } -} +impl Managed for JsError { } impl ValueInternal for JsError { fn name() -> String { "Error".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_error(other.to_raw()) } } } @@ -35,32 +29,37 @@ impl Value for JsError { } impl Object for JsError { } impl JsError { + /// Creates a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class. - pub fn error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult> { - let msg = cx.string(msg.as_ref()); - build(|out| unsafe { - neon_runtime::error::new_error(out, msg.to_raw()); + pub fn error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { + let msg = { cx.string(msg.as_ref()).to_raw() }; + let isolate = { cx.isolate().to_raw() }; + build(cx, |out| unsafe { + neon_runtime::error::init_error(out, isolate, msg); true }) } /// Creates an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class. - pub fn type_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult> { - let msg = cx.string(msg.as_ref()); - build(|out| unsafe { - neon_runtime::error::new_type_error(out, msg.to_raw()); + pub fn type_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { + let msg = { cx.string(msg.as_ref()).to_raw() }; + let isolate = { cx.isolate().to_raw() }; + build(cx, |out| unsafe { + neon_runtime::error::init_type_error(out, isolate, msg); true }) } /// Creates an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class. - pub fn range_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult> { - let msg = cx.string(msg.as_ref()); - build(|out| unsafe { - neon_runtime::error::new_range_error(out, msg.to_raw()); + pub fn range_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { + let msg = { cx.string(msg.as_ref()).to_raw() }; + let isolate = { cx.isolate().to_raw() }; + build(cx, |out| unsafe { + neon_runtime::error::init_range_error(out, isolate, msg); true }) } + } pub(crate) fn convert_panics NeonResult>(f: F) -> NeonResult { diff --git a/src/types/internal.rs b/src/types/internal.rs index 3675c1e00..d642d70fc 100644 --- a/src/types/internal.rs +++ b/src/types/internal.rs @@ -4,38 +4,34 @@ use neon_runtime; use neon_runtime::raw; use context::{CallbackInfo, FunctionContext}; use types::error::convert_panics; -use types::{JsObject, Handle, Managed}; -use result::JsResult; +use types::{JsObject, Managed}; +use result::NeonResult; use object::class::Callback; use super::Value; pub trait ValueInternal: Managed + 'static { fn name() -> String; - fn is_typeof(other: Other) -> bool; + fn is_typeof(other: &Other) -> bool; - fn downcast(other: Other) -> Option { + fn downcast(other: &Other) -> Option<&Self> { if Self::is_typeof(other) { Some(Self::from_raw(other.to_raw())) } else { None } } - - fn cast<'a, T: Value, F: FnOnce(raw::Local) -> T>(self, f: F) -> Handle<'a, T> { - Handle::new_internal(f(self.to_raw())) - } } #[repr(C)] -pub struct FunctionCallback(pub fn(FunctionContext) -> JsResult); +pub struct FunctionCallback(pub fn(FunctionContext) -> NeonResult<&T>); impl Callback<()> for FunctionCallback { extern "C" fn invoke(info: &CallbackInfo) { unsafe { - info.with_cx::(|cx| { - let data = info.data(); - let dynamic_callback: fn(FunctionContext) -> JsResult = + info.with_cx::(|mut cx| { + let data = info.data(&mut cx); + let dynamic_callback: fn(FunctionContext) -> NeonResult<&T> = mem::transmute(neon_runtime::fun::get_dynamic_callback(data.to_raw())); if let Ok(value) = convert_panics(|| { dynamic_callback(cx) }) { info.set_return(value); diff --git a/src/types/mod.rs b/src/types/mod.rs index 09c684761..e954900f5 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -7,6 +7,7 @@ pub(crate) mod internal; pub(crate) mod utf8; use std; +use std::error::Error; use std::fmt; use std::mem; use std::os::raw::c_void; @@ -15,191 +16,240 @@ use neon_runtime; use neon_runtime::raw; use context::{Context, FunctionContext}; use context::internal::Isolate; -use result::{NeonResult, JsResult, Throw, JsResultExt}; +use result::{NeonResult, Throw, NeonResultExt}; use object::{Object, This}; use object::class::Callback; -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(crate) fn build<'a, T: Managed, F: FnOnce(&mut raw::Local) -> bool>(init: F) -> JsResult<'a, T> { +pub(crate) fn build<'a, C: Context<'a>, T: Managed, F: FnOnce(&raw::Persistent) -> bool>(cx: &mut C, init: F) -> NeonResult<&'a T> { unsafe { - let mut local: raw::Local = std::mem::zeroed(); - if init(&mut local) { - Ok(Handle::new_internal(T::from_raw(local))) + let h = cx.alloc_persistent(); + if init(h) { + Ok(T::from_raw(h)) } else { Err(Throw) } } } -impl SuperType for JsValue { - fn upcast_internal(v: T) -> JsValue { - JsValue(v.to_raw()) +pub(crate) fn build_infallible<'a, C: Context<'a>, T: Managed, F: FnOnce(&raw::Persistent)>(cx: &mut C, init: F) -> &'a T { + unsafe { + let h = cx.alloc_persistent(); + init(h); + T::from_raw(h) } } -impl SuperType for JsObject { - fn upcast_internal(v: T) -> JsObject { - JsObject(v.to_raw()) +pub unsafe trait SuperType { } + +unsafe impl SuperType for JsValue { } + +unsafe impl SuperType for JsObject { } + +/// The trait of data that is managed by the JS garbage collector and can only be accessed via handles. +pub trait Managed: Sized { + fn to_raw(&self) -> &raw::Persistent { + unsafe { + std::mem::transmute(self) + } + } + + fn from_raw(h: &raw::Persistent) -> &Self { + unsafe { + std::mem::transmute(h) + } } } -/// The trait shared by all JavaScript values. pub trait Value: ValueInternal { - fn to_string<'a, C: Context<'a>>(self, _: &mut C) -> JsResult<'a, JsString> { - build(|out| { unsafe { neon_runtime::convert::to_string(out, self.to_raw()) } }) - } - fn as_value<'a, C: Context<'a>>(self, _: &mut C) -> Handle<'a, JsValue> { - JsValue::new_internal(self.to_raw()) + /// Safely upcast a JS value to a supertype. + /// + /// This method does not require an execution context because it only reinterprets a pointer. + fn upcast>(&self) -> &U { + unsafe { + mem::transmute(self) + } } -} -/// A JavaScript value of any type. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct JsValue(raw::Local); -impl Value for JsValue { } + /// Tests whether this value is an instance of the given type. + /// + /// # Example: + /// + /// ```no_run + /// # use neon::prelude::*; + /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult { + /// let v: Handle = cx.number(17).upcast(); + /// v.is_a::(); // false + /// v.is_a::(); // true + /// v.is_a::(); // true + /// # Ok(cx.undefined()) + /// # } + /// ``` + fn is_a(&self) -> bool { + U::is_typeof(self) + } + + /// 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. + fn downcast(&self) -> DowncastResult { + if U::is_typeof(self) { + Ok(unsafe { mem::transmute(self) }) + } else { + Err(DowncastError::new()) + } + } -impl Managed for JsValue { - fn to_raw(self) -> raw::Local { self.0 } + /// 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)`. + fn downcast_or_throw<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> NeonResult<&U> { + self.downcast().or_throw(cx) + } - fn from_raw(h: raw::Local) -> Self { JsValue(h) } } -impl ValueInternal for JsValue { - fn name() -> String { "any".to_string() } +/// An error representing a failed downcast. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +pub struct DowncastError { + phantom_from: PhantomData, + phantom_to: PhantomData, + description: String +} - fn is_typeof(_: Other) -> bool { - true +impl fmt::Debug for DowncastError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "DowncastError") } } -unsafe impl This for JsValue { - fn as_this(h: raw::Local) -> Self { - JsValue(h) +impl DowncastError { + fn new() -> Self { + DowncastError { + phantom_from: PhantomData, + phantom_to: PhantomData, + description: format!("failed downcast to {}", T::name()) + } } } -impl JsValue { - pub(crate) fn new_internal<'a>(value: raw::Local) -> Handle<'a, JsValue> { - Handle::new_internal(JsValue(value)) +impl fmt::Display for DowncastError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}", self.description()) } } -/// The JavaScript `undefined` value. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct JsUndefined(raw::Local); - -impl JsUndefined { - pub fn new_thin<'a, C: Context<'a>>(cx: &mut C) -> &'a JsUndefined { - unsafe { - let local = cx.alloc(); - neon_runtime::primitive::undefined(mem::transmute(local)); - mem::transmute(local) - } +impl Error for DowncastError { + fn description(&self) -> &str { + &self.description } +} - pub fn new<'a>() -> Handle<'a, JsUndefined> { - JsUndefined::new_internal() - } +/// The result of a call to `Handle::downcast()`. +pub type DowncastResult<'a, F, T> = Result<&'a T, DowncastError>; - pub(crate) fn new_internal<'a>() -> Handle<'a, JsUndefined> { - unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::primitive::undefined(&mut local); - Handle::new_internal(JsUndefined(local)) +impl<'a, F: Value, T: Value> NeonResultExt<'a, T> for DowncastResult<'a, F, T> { + fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> NeonResult<&'a T> { + match self { + Ok(v) => Ok(v), + Err(e) => cx.throw_type_error(&e.description) } } } -impl Value for JsUndefined { } +/// A JavaScript value of any type. +#[repr(C)] +pub struct JsValue(raw::Persistent); -impl Managed for JsUndefined { - fn to_raw(self) -> raw::Local { self.0 } +impl Value for JsValue { } - fn from_raw(h: raw::Local) -> Self { JsUndefined(h) } +impl Managed for JsValue { } + +impl ValueInternal for JsValue { + fn name() -> String { "any".to_string() } + + fn is_typeof(_: &Other) -> bool { + true + } } -unsafe impl This for JsUndefined { - fn as_this(_: raw::Local) -> Self { +unsafe impl This for JsValue { } + +/// The JavaScript `undefined` value. +#[repr(C)] +pub struct JsUndefined(raw::Persistent); + +impl JsUndefined { + pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsUndefined { unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::primitive::undefined(&mut local); - JsUndefined(local) + let h = cx.alloc_persistent(); + neon_runtime::primitive::init_undefined(h, cx.isolate().to_raw()); + JsUndefined::from_raw(h) } } } +impl Managed for JsUndefined { } + impl ValueInternal for JsUndefined { fn name() -> String { "undefined".to_string() } - fn is_typeof(other: Other) -> bool { - unsafe { neon_runtime::tag::is_undefined(other.to_raw()) } + fn is_typeof(other: &Other) -> bool { + unsafe { neon_runtime::tag::is_undefined_thin(other.to_raw()) } } } +impl Value for JsUndefined { } + +unsafe impl This for JsUndefined { } + /// The JavaScript `null` value. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsNull(raw::Local); +pub struct JsNull(raw::Persistent); impl JsNull { - pub fn new<'a>() -> Handle<'a, JsNull> { - JsNull::new_internal() - } - - pub(crate) fn new_internal<'a>() -> Handle<'a, JsNull> { + pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsNull { unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::primitive::null(&mut local); - Handle::new_internal(JsNull(local)) + let h = cx.alloc_persistent(); + neon_runtime::primitive::init_null(h, cx.isolate().to_raw()); + JsNull::from_raw(h) } } } -impl Value for JsNull { } - -impl Managed for JsNull { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsNull(h) } -} +impl Managed for JsNull { } impl ValueInternal for JsNull { fn name() -> String { "null".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_null(other.to_raw()) } } } +impl Value for JsNull { } + /// A JavaScript boolean primitive value. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsBoolean(raw::Local); +pub struct JsBoolean(raw::Persistent); impl JsBoolean { - pub fn new<'a, C: Context<'a>>(_: &mut C, b: bool) -> Handle<'a, JsBoolean> { - JsBoolean::new_internal(b) - } - - pub(crate) fn new_internal<'a>(b: bool) -> Handle<'a, JsBoolean> { + pub fn new<'a, C: Context<'a>>(cx: &mut C, b: bool) -> &'a JsBoolean { unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::primitive::boolean(&mut local, b); - Handle::new_internal(JsBoolean(local)) + let h = cx.alloc_persistent(); + neon_runtime::primitive::init_boolean(h, cx.isolate().to_raw(), b); + JsBoolean::from_raw(h) } } - pub fn value(self) -> bool { + pub fn value(&self) -> bool { unsafe { neon_runtime::primitive::boolean_value(self.to_raw()) } @@ -208,24 +258,19 @@ impl JsBoolean { impl Value for JsBoolean { } -impl Managed for JsBoolean { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsBoolean(h) } -} +impl Managed for JsBoolean { } impl ValueInternal for JsBoolean { fn name() -> String { "boolean".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_boolean(other.to_raw()) } } } /// A JavaScript string primitive value. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsString(raw::Local); +pub struct JsString(raw::Persistent); /// An error produced when constructing a string that exceeds the JS engine's maximum string size. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)] @@ -238,10 +283,10 @@ impl fmt::Display for StringOverflow { } /// The result of constructing a new `JsString`. -pub type StringResult<'a> = Result, StringOverflow>; +pub type StringResult<'a> = Result<&'a JsString, StringOverflow>; -impl<'a> JsResultExt<'a, JsString> for StringResult<'a> { - fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, JsString> { +impl<'a> NeonResultExt<'a, JsString> for StringResult<'a> { + fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> NeonResult<&'a JsString> { match self { Ok(v) => Ok(v), Err(e) => cx.throw_range_error(&e.to_string()) @@ -251,16 +296,12 @@ impl<'a> JsResultExt<'a, JsString> for StringResult<'a> { impl Value for JsString { } -impl Managed for JsString { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsString(h) } -} +impl Managed for JsString { } impl ValueInternal for JsString { fn name() -> String { "string".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_string(other.to_raw()) } } } @@ -283,19 +324,19 @@ impl JsString { } } - pub fn new<'a, C: Context<'a>, S: AsRef>(cx: &mut C, val: S) -> Handle<'a, JsString> { + pub fn new<'a, C: Context<'a>, S: AsRef>(cx: &mut C, val: S) -> &'a JsString { JsString::try_new(cx, val).unwrap() } pub fn try_new<'a, C: Context<'a>, S: AsRef>(cx: &mut C, val: S) -> StringResult<'a> { let val = val.as_ref(); - match JsString::new_internal(cx.isolate(), val) { + match JsString::new_internal(cx, val) { Some(s) => Ok(s), None => Err(StringOverflow(val.len())) } } - pub(crate) fn new_internal<'a>(isolate: Isolate, val: &str) -> Option> { + fn new_internal<'a, C: Context<'a>>(cx: &mut C, val: &str) -> Option<&'a JsString> { let (ptr, len) = if let Some(small) = Utf8::from(val).into_small() { small.lower() } else { @@ -303,9 +344,9 @@ impl JsString { }; unsafe { - let mut local: raw::Local = std::mem::zeroed(); - if neon_runtime::string::new(&mut local, isolate.to_raw(), ptr, len) { - Some(Handle::new_internal(JsString(local))) + let h = cx.alloc_persistent(); + if neon_runtime::string::new(h, cx.isolate().to_raw(), ptr, len) { + Some(JsString::from_raw(h)) } else { None } @@ -315,86 +356,69 @@ impl JsString { /// A JavaScript number value. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsNumber(raw::Local); +pub struct JsNumber(raw::Persistent); impl JsNumber { - pub fn new<'a, C: Context<'a>, T: Into>(cx: &mut C, x: T) -> Handle<'a, JsNumber> { - JsNumber::new_internal(cx.isolate(), x.into()) - } - - pub(crate) fn new_internal<'a>(isolate: Isolate, v: f64) -> Handle<'a, JsNumber> { + pub fn new<'a, C: Context<'a>, T: Into>(cx: &mut C, x: T) -> &'a JsNumber { unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::primitive::number(&mut local, isolate.to_raw(), v); - Handle::new_internal(JsNumber(local)) + let h = cx.alloc_persistent(); + neon_runtime::primitive::init_number(h, cx.isolate().to_raw(), x.into()); + JsNumber::from_raw(h) } } - pub fn value(self) -> f64 { + pub fn value(&self) -> f64 { unsafe { neon_runtime::primitive::number_value(self.to_raw()) } } } -impl Value for JsNumber { } - -impl Managed for JsNumber { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsNumber(h) } -} +impl Managed for JsNumber { } impl ValueInternal for JsNumber { fn name() -> String { "number".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_number(other.to_raw()) } } } -/// A JavaScript object. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct JsObject(raw::Local); - -impl Value for JsObject { } - -impl Managed for JsObject { - fn to_raw(self) -> raw::Local { self.0 } +impl Value for JsNumber { } - fn from_raw(h: raw::Local) -> Self { JsObject(h) } -} +#[repr(C)] +pub struct JsObject(raw::Persistent); -unsafe impl This for JsObject { - fn as_this(h: raw::Local) -> Self { JsObject(h) } -} +impl Managed for JsObject { } impl ValueInternal for JsObject { fn name() -> String { "object".to_string() } - fn is_typeof(other: Other) -> bool { - unsafe { neon_runtime::tag::is_object(other.to_raw()) } + fn is_typeof(other: &Other) -> bool { + unsafe { neon_runtime::tag::is_object_thin(other.to_raw()) } } } +impl Value for JsObject { } + impl Object for JsObject { } -impl JsObject { - pub fn new<'a, C: Context<'a>>(_: &mut C) -> Handle<'a, JsObject> { - JsObject::new_internal() - } +unsafe impl This for JsObject { } - pub(crate) fn new_internal<'a>() -> Handle<'a, JsObject> { - JsObject::build(|out| { unsafe { neon_runtime::object::new(out) } }) +impl JsObject { + pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsObject { + unsafe { + let h = cx.alloc_persistent(); + neon_runtime::object::init(h, cx.isolate().to_raw()); + JsObject::from_raw(h) + } } - pub(crate) fn build<'a, F: FnOnce(&mut raw::Local)>(init: F) -> Handle<'a, JsObject> { + pub(crate) fn build<'a, C: Context<'a>, F: FnOnce(&mut raw::Local)>(cx: &mut C, init: F) -> &'a JsObject { unsafe { - let mut local: raw::Local = std::mem::zeroed(); - init(&mut local); - Handle::new_internal(JsObject(local)) + let local = cx.alloc(); + init(mem::transmute(local)); + mem::transmute(local) } } } @@ -402,23 +426,18 @@ impl JsObject { /// A JavaScript array object, i.e. a value for which `Array.isArray` /// would return `true`. #[repr(C)] -#[derive(Clone, Copy)] -pub struct JsArray(raw::Local); +pub struct JsArray(raw::Persistent); impl JsArray { - pub fn new<'a, C: Context<'a>>(cx: &mut C, len: u32) -> Handle<'a, JsArray> { - JsArray::new_internal(cx.isolate(), len) - } - pub(crate) fn new_internal<'a>(isolate: Isolate, len: u32) -> Handle<'a, JsArray> { - unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::array::new(&mut local, isolate.to_raw(), len); - Handle::new_internal(JsArray(local)) - } + pub fn new<'a, C: Context<'a>>(cx: &mut C, len: u32) -> &'a JsArray { + let isolate = { cx.isolate().to_raw() }; + build_infallible(cx, |out| unsafe { + neon_runtime::array::init(out, isolate, len) + }) } - pub fn to_vec<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult>> { + pub fn to_vec<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult> { let mut result = Vec::with_capacity(self.len() as usize); let mut i = 0; loop { @@ -432,25 +451,22 @@ impl JsArray { } } - pub fn len(self) -> u32 { + pub fn len(&self) -> u32 { unsafe { neon_runtime::array::len(self.to_raw()) } } + } impl Value for JsArray { } -impl Managed for JsArray { - fn to_raw(self) -> raw::Local { self.0 } - - fn from_raw(h: raw::Local) -> Self { JsArray(h) } -} +impl Managed for JsArray { } impl ValueInternal for JsArray { fn name() -> String { "Array".to_string() } - fn is_typeof(other: Other) -> bool { + fn is_typeof(other: &Other) -> bool { unsafe { neon_runtime::tag::is_array(other.to_raw()) } } } @@ -459,18 +475,30 @@ impl Object for JsArray { } /// A JavaScript function object. #[repr(C)] -#[derive(Clone, Copy)] pub struct JsFunction { - raw: raw::Local, - marker: PhantomData + raw: raw::Persistent, + marker: PhantomData, } impl Object for JsFunction { } -// Maximum number of function arguments in V8. -const V8_ARGC_LIMIT: usize = 65535; +impl JsFunction { + pub fn new<'a, C, U>(cx: &mut C, f: fn(FunctionContext) -> NeonResult<&U>) -> NeonResult<&'a JsFunction> + where C: Context<'a>, + U: Value + { + let isolate = cx.isolate().to_raw(); + build(cx, |out| { + unsafe { + let isolate: *mut c_void = std::mem::transmute(isolate); + let callback = FunctionCallback(f).into_c_callback(); + neon_runtime::fun::init(out, isolate, callback) + } + }) + } +} -unsafe fn prepare_call<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: &mut [Handle<'b, A>]) -> NeonResult<(*mut c_void, i32, *mut c_void)> +unsafe fn prepare_call<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: &mut [&'b A]) -> NeonResult<(*mut c_void, i32, *mut c_void)> where A: Value + 'b { let argv = args.as_mut_ptr(); @@ -482,67 +510,46 @@ unsafe fn prepare_call<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: &mut [Handle Ok((isolate, argc as i32, argv as *mut c_void)) } -impl JsFunction { - pub fn new<'a, C, U>(cx: &mut C, f: fn(FunctionContext) -> JsResult) -> JsResult<'a, JsFunction> - where C: Context<'a>, - U: Value - { - build(|out| { - unsafe { - let isolate: *mut c_void = std::mem::transmute(cx.isolate().to_raw()); - let callback = FunctionCallback(f).into_c_callback(); - neon_runtime::fun::new(out, isolate, callback) - } - }) - } -} - impl JsFunction { - pub fn call<'a, 'b, C: Context<'a>, T, A, AS>(self, cx: &mut C, this: Handle<'b, T>, args: AS) -> JsResult<'a, JsValue> + pub fn call<'a, 'b, C: Context<'a>, T, A, AS>(&self, cx: &mut C, this: &'b T, args: AS) -> NeonResult<&'a JsValue> where T: Value, A: Value + 'b, - AS: IntoIterator> + AS: IntoIterator { let mut args = args.into_iter().collect::>(); let (isolate, argc, argv) = unsafe { prepare_call(cx, &mut args) }?; - build(|out| { + build(cx, |out| { unsafe { - neon_runtime::fun::call(out, isolate, self.to_raw(), this.to_raw(), argc, argv) + neon_runtime::fun::call_thin(out, isolate, self.to_raw(), this.to_raw(), argc, argv) } }) } - pub fn construct<'a, 'b, C: Context<'a>, A, AS>(self, cx: &mut C, args: AS) -> JsResult<'a, CL> + pub fn construct<'a, 'b, C: Context<'a>, A, AS>(self, cx: &mut C, args: AS) -> NeonResult<&'a CL> where A: Value + 'b, - AS: IntoIterator> + AS: IntoIterator { let mut args = args.into_iter().collect::>(); let (isolate, argc, argv) = unsafe { prepare_call(cx, &mut args) }?; - build(|out| { + build(cx, |out| { unsafe { - neon_runtime::fun::construct(out, isolate, self.to_raw(), argc, argv) + neon_runtime::fun::construct_thin(out, isolate, self.to_raw(), argc, argv) } }) } } -impl Value for JsFunction { } - -impl Managed for JsFunction { - fn to_raw(self) -> raw::Local { self.raw } - - fn from_raw(h: raw::Local) -> Self { - JsFunction { - raw: h, - marker: PhantomData - } - } -} +impl Managed for JsFunction { } impl ValueInternal for JsFunction { fn name() -> String { "function".to_string() } - fn is_typeof(other: Other) -> bool { - unsafe { neon_runtime::tag::is_function(other.to_raw()) } + fn is_typeof(other: &Other) -> bool { + unsafe { neon_runtime::tag::is_function_thin(other.to_raw()) } } } + +impl Value for JsFunction { } + +// Maximum number of function arguments in V8. +const V8_ARGC_LIMIT: usize = 65535; From 977e7a1fde709082a061c8342ca1e2dc6c01703b Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 25 Jan 2019 10:25:55 -0800 Subject: [PATCH 03/11] Finish migrating the Task API. --- crates/neon-runtime/src/mem.rs | 4 ++++ crates/neon-runtime/src/neon.cc | 6 +++++- crates/neon-runtime/src/neon.h | 2 +- crates/neon-runtime/src/neon_task.h | 4 ++-- crates/neon-runtime/src/task.rs | 4 ++-- src/task/mod.rs | 11 ++--------- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/crates/neon-runtime/src/mem.rs b/crates/neon-runtime/src/mem.rs index f48f3c663..63597a876 100644 --- a/crates/neon-runtime/src/mem.rs +++ b/crates/neon-runtime/src/mem.rs @@ -19,4 +19,8 @@ extern "C" { #[link_name = "Neon_Mem_ResetPersistent"] pub fn reset_persistent(p: &Persistent, h: Local); + /// Initializes a local handle with the value of a persistent handle. + #[link_name = "Neon_Mem_ReadPersistent"] + pub fn read_persistent(out: &mut Local, p: &Persistent); + } diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index e4aa5a5ab..7df8fd770 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -771,12 +771,16 @@ extern "C" void Neon_Mem_DropPersistent(v8::Persistent *p) { p->Persistent::~Persistent(); } +extern "C" void Neon_Mem_ReadPersistent(v8::Local *out, v8::Persistent *p) { + *out = Nan::New(*p); +} + extern "C" void Neon_Mem_ResetPersistent(v8::Persistent *p, v8::Local h) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); p->Reset(isolate, h); } -extern "C" void Neon_Task_Schedule(void *task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, v8::Local callback) { +extern "C" void Neon_Task_Schedule(void *task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, v8::Persistent *callback) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); neon::Task *internal_task = new neon::Task(isolate, task, perform, complete, callback); neon::queue_task(internal_task); diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index b1fb00d75..ba1c0e0b8 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -157,7 +157,7 @@ extern "C" { typedef void* (*Neon_TaskPerformCallback)(void *); typedef void (*Neon_TaskCompleteCallback)(void *, void *, v8::Local *out); - void Neon_Task_Schedule(void *task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, v8::Local callback); + void Neon_Task_Schedule(void *task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, v8::Persistent *callback); } #endif diff --git a/crates/neon-runtime/src/neon_task.h b/crates/neon-runtime/src/neon_task.h index a0d9da12b..fc8e60839 100644 --- a/crates/neon-runtime/src/neon_task.h +++ b/crates/neon-runtime/src/neon_task.h @@ -13,7 +13,7 @@ class Task { void *rust_task, Neon_TaskPerformCallback perform, Neon_TaskCompleteCallback complete, - v8::Local callback) + v8::Persistent *callback) : isolate_(isolate), rust_task_(rust_task), perform_(perform), @@ -22,7 +22,7 @@ class Task { request_.data = this; result_ = nullptr; // Save the callback to be invoked when the task completes. - callback_.Reset(isolate, callback); + callback_.Reset(isolate, *callback); // Save the context (aka realm) to be used when invoking the callback. context_.Reset(isolate, isolate->GetCurrentContext()); } diff --git a/crates/neon-runtime/src/task.rs b/crates/neon-runtime/src/task.rs index a569bf61e..e0f4fceb1 100644 --- a/crates/neon-runtime/src/task.rs +++ b/crates/neon-runtime/src/task.rs @@ -1,6 +1,6 @@ //! Facilities for running background tasks in the libuv thread pool. -use raw::Local; +use raw::{Local, Persistent}; use std::os::raw::c_void; extern "C" { @@ -10,6 +10,6 @@ extern "C" { pub fn schedule(task: *mut c_void, perform: unsafe extern fn(*mut c_void) -> *mut c_void, complete: unsafe extern fn(*mut c_void, *mut c_void, &mut Local), - callback: Local); + callback: &Persistent); } diff --git a/src/task/mod.rs b/src/task/mod.rs index e32e2dfad..8c25d2ec8 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -4,7 +4,7 @@ use std::marker::{Send, Sized}; use std::mem; use std::os::raw::c_void; -use types::{Value, JsFunction}; +use types::{Value, Managed, JsFunction}; use result::NeonResult; use context::TaskContext; use neon_runtime; @@ -35,8 +35,6 @@ pub trait Task: Send + Sized + 'static { /// function callback(err, value) {} /// ``` fn schedule(self, callback: &JsFunction) { - // FIXME: implement -/* let boxed_self = Box::new(self); let self_raw = Box::into_raw(boxed_self); let callback_raw = callback.to_raw(); @@ -46,7 +44,6 @@ pub trait Task: Send + Sized + 'static { complete_task::, callback_raw); } -*/ } } @@ -57,16 +54,12 @@ unsafe extern "C" fn perform_task(task: *mut c_void) -> *mut c_void { mem::transmute(Box::into_raw(Box::new(result))) } -// FIXME: thinify this: - -/* unsafe extern "C" fn complete_task(task: *mut c_void, result: *mut c_void, out: &mut raw::Local) { let result: Result = *Box::from_raw(mem::transmute(result)); let task: Box = Box::from_raw(mem::transmute(task)); TaskContext::with(|cx| { if let Ok(result) = task.complete(cx, result) { - *out = result.to_raw(); + neon_runtime::mem::read_persistent(out, result.to_raw()); } }) } -*/ From ca754c314694c9ebf75b0deefb12257be44d81ee Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 15 Feb 2019 09:52:13 -0800 Subject: [PATCH 04/11] - Finish migrating class and object APIs - Move `build` and `build_infallible` into `cx.new()` and `cx.new_infallible()`, respectively --- crates/neon-runtime/src/call.rs | 2 +- crates/neon-runtime/src/class.rs | 8 ++-- crates/neon-runtime/src/fun.rs | 2 +- crates/neon-runtime/src/neon.cc | 64 ++++++++++++++++++++++--------- crates/neon-runtime/src/neon.h | 16 ++++---- crates/neon-runtime/src/object.rs | 4 +- src/context/internal.rs | 21 +++++++++- src/context/mod.rs | 24 +++++------- src/object/class/internal.rs | 28 ++++++-------- src/object/class/mod.rs | 30 +-------------- src/object/mod.rs | 14 +++---- src/types/binary.rs | 14 +++---- src/types/error.rs | 8 ++-- src/types/mod.rs | 45 +++++----------------- 14 files changed, 130 insertions(+), 150 deletions(-) diff --git a/crates/neon-runtime/src/call.rs b/crates/neon-runtime/src/call.rs index 3111fe2e1..56c7f0d3e 100644 --- a/crates/neon-runtime/src/call.rs +++ b/crates/neon-runtime/src/call.rs @@ -44,7 +44,7 @@ extern "C" { /// Mutates the `out` argument provided to refer to the `v8::Local` handle value of the object /// the function is bound to. #[link_name = "Neon_Call_This"] - pub fn this(info: &FunctionCallbackInfo, out: &mut Local); + pub fn this(info: &FunctionCallbackInfo, out: &Persistent, isolate: *mut Isolate); /// Mutates the `out` argument provided to refer to the `v8::Local` handle value of the /// `v8::FunctionCallbackInfo` `Data`. diff --git a/crates/neon-runtime/src/class.rs b/crates/neon-runtime/src/class.rs index c7747d479..8fad085f3 100644 --- a/crates/neon-runtime/src/class.rs +++ b/crates/neon-runtime/src/class.rs @@ -30,10 +30,10 @@ extern "C" { pub fn throw_this_error(isolate: *mut Isolate, metadata: *mut c_void); #[link_name = "Neon_Class_AddMethod"] - pub fn add_method(isolate: *mut Isolate, metadata: *mut c_void, name: *const u8, byte_length: u32, method: Local) -> bool; + pub fn add_method(isolate: *mut Isolate, metadata: *mut c_void, name: *const u8, byte_length: u32, method: &Persistent) -> bool; #[link_name = "Neon_Class_MetadataToConstructor"] - pub fn metadata_to_constructor(out: &mut Local, isolate: *mut Isolate, metadata: *mut c_void) -> bool; + pub fn metadata_to_constructor(out: &Persistent, isolate: *mut Isolate, metadata: *mut c_void) -> bool; // FIXME: get rid of all the "kernel" nomenclature @@ -50,9 +50,9 @@ extern "C" { pub fn constructor(out: &mut Local, ft: Local) -> bool; #[link_name = "Neon_Class_HasInstance"] - pub fn has_instance(metadata: *mut c_void, v: Local) -> bool; + pub fn has_instance(metadata: *mut c_void, v: &Persistent) -> bool; #[link_name = "Neon_Class_GetInstanceInternals"] - pub fn get_instance_internals(obj: Local) -> *mut c_void; + pub fn get_instance_internals(obj: &Persistent) -> *mut c_void; } diff --git a/crates/neon-runtime/src/fun.rs b/crates/neon-runtime/src/fun.rs index 3d66f1daf..f280d6df6 100644 --- a/crates/neon-runtime/src/fun.rs +++ b/crates/neon-runtime/src/fun.rs @@ -19,7 +19,7 @@ extern "C" { /// Mutates the `out` argument provided to refer to a newly created `v8::FunctionTemplate`. /// Returns `false` if the value couldn't be created. #[link_name = "Neon_Fun_Template_New"] - pub fn new_template(out: &mut Local, isolate: *mut c_void, callback: CCallback) -> bool; + pub fn new_template(out: &Persistent, isolate: *mut c_void, callback: CCallback) -> bool; /// Gets the reference to the `v8::Local` handle provided. #[link_name = "Neon_Fun_GetDynamicCallback"] diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index 7df8fd770..8436426a7 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -29,8 +29,9 @@ extern "C" bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info) return info->IsConstructCall(); } -extern "C" void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Local *out) { - *out = info->This(); +extern "C" void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate) { + Nan::HandleScope scope; + out->Reset(isolate, info->This()); } extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out) { @@ -134,13 +135,23 @@ extern "C" bool Neon_Primitive_IsInt32(v8::Local p) { return p->IsInt32(); } -extern "C" bool Neon_Object_Get_Index(v8::Local *out, v8::Local obj, uint32_t index) { - Nan::MaybeLocal maybe = Nan::Get(obj, index); - return maybe.ToLocal(out); +extern "C" bool Neon_Object_Get_Index(v8::Persistent *out, v8::Persistent *obj, uint32_t index) { + Nan::HandleScope scope; + v8::Local lobj = Nan::New(*obj); + Nan::MaybeLocal maybe = Nan::Get(lobj, index); + v8::Local local; + if (!maybe.ToLocal(&local)) { + return false; + } + out->Reset(v8::Isolate::GetCurrent(), local); + return true; } -extern "C" bool Neon_Object_Set_Index(bool *out, v8::Local object, uint32_t index, v8::Local val) { - Nan::Maybe maybe = Nan::Set(object, index, val); +extern "C" bool Neon_Object_Set_Index(bool *out, v8::Persistent *object, uint32_t index, v8::Persistent *val) { + Nan::HandleScope scope; + v8::Local lobject = Nan::New(*object); + v8::Local lval = Nan::New(*val); + Nan::Maybe maybe = Nan::Set(lobject, index, lval); return maybe.IsJust() && (*out = maybe.FromJust(), true); } @@ -502,9 +513,11 @@ extern "C" bool Neon_Class_Constructor(v8::Local *out, v8::Local v) { +extern "C" bool Neon_Class_HasInstance(void *metadata_pointer, v8::Persistent *v) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*v); neon::ClassMetadata *metadata = static_cast(metadata_pointer); - return metadata->GetTemplate(v8::Isolate::GetCurrent())->HasInstance(v); + return metadata->GetTemplate(v8::Isolate::GetCurrent())->HasInstance(local); } extern "C" bool Neon_Class_SetName(v8::Isolate *isolate, void *metadata_pointer, const char *name, uint32_t byte_length) { @@ -538,31 +551,41 @@ extern "C" void Neon_Class_ThrowThisError(v8::Isolate *isolate, void *metadata_p Nan::ThrowTypeError(metadata->GetThisError().ToJsString(isolate, "this is not an object of the expected type.")); } -extern "C" bool Neon_Class_AddMethod(v8::Isolate *isolate, void *metadata_pointer, const char *name, uint32_t byte_length, v8::Local method) { +extern "C" bool Neon_Class_AddMethod(v8::Isolate *isolate, void *metadata_pointer, const char *name, uint32_t byte_length, v8::Persistent *method) { + Nan::HandleScope scope; neon::ClassMetadata *metadata = static_cast(metadata_pointer); v8::Local ft = metadata->GetTemplate(isolate); v8::Local pt = ft->PrototypeTemplate(); - Nan::HandleScope scope; v8::MaybeLocal maybe_key = v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal, byte_length); v8::Local key; if (!maybe_key.ToLocal(&key)) { return false; } - pt->Set(key, method); + v8::Local lmethod = Nan::New(*method); + pt->Set(key, lmethod); return true; } -extern "C" bool Neon_Class_MetadataToConstructor(v8::Local *out, v8::Isolate *isolate, void *metadata) { +extern "C" bool Neon_Class_MetadataToConstructor(v8::Persistent *out, v8::Isolate *isolate, void *metadata) { + Nan::HandleScope scope; v8::Local ft = static_cast(metadata)->GetTemplate(isolate); v8::MaybeLocal maybe = ft->GetFunction(); - return maybe.ToLocal(out); + v8::Local local; + if (!maybe.ToLocal(&local)) { + return false; + } + out->Reset(isolate, local); + return true; } -extern "C" void *Neon_Class_GetInstanceInternals(v8::Local obj) { - return static_cast(obj->GetAlignedPointerFromInternalField(0))->GetInternals(); +extern "C" void *Neon_Class_GetInstanceInternals(v8::Persistent *obj) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*obj); + return static_cast(local->GetAlignedPointerFromInternalField(0))->GetInternals(); } -extern "C" bool Neon_Fun_Template_New(v8::Local *out, v8::Isolate *isolate, callback_t callback) { +extern "C" bool Neon_Fun_Template_New(v8::Persistent *out, v8::Isolate *isolate, callback_t callback) { + Nan::HandleScope scope; v8::Local wrapper = v8::External::New(isolate, callback.dynamic_callback); if (wrapper.IsEmpty()) { return false; @@ -570,7 +593,12 @@ extern "C" bool Neon_Fun_Template_New(v8::Local *out, v8:: v8::FunctionCallback static_callback = reinterpret_cast(callback.static_callback); v8::MaybeLocal maybe_result = v8::FunctionTemplate::New(isolate, static_callback, wrapper); - return maybe_result.ToLocal(out); + v8::Local local; + if (!maybe_result.ToLocal(&local)) { + return false; + } + out->Reset(isolate, local); + return true; } extern "C" bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback) { diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index ba1c0e0b8..c0106851a 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -18,7 +18,7 @@ extern "C" { void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo *info); void *Neon_Call_CurrentIsolate(); bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info); - void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Local *out); + void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolae); void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out); void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, v8::Persistent *out); int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info); @@ -37,8 +37,8 @@ extern "C" { void Neon_Object_Init(v8::Persistent *out, v8::Isolate *isolate); bool Neon_Object_GetOwnPropertyNames(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *obj); void *Neon_Object_GetIsolate(v8::Local obj); - bool Neon_Object_Get_Index(v8::Local *out, v8::Local object, uint32_t index); - bool Neon_Object_Set_Index(bool *out, v8::Local object, uint32_t index, v8::Local val); + bool Neon_Object_Get_Index(v8::Persistent *out, v8::Persistent *object, uint32_t index); + bool Neon_Object_Set_Index(bool *out, v8::Persistent *object, uint32_t index, v8::Persistent *val); bool Neon_Object_Get_String(v8::Local *out, v8::Local object, const uint8_t *key, int32_t len); bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Persistent *object, const uint8_t *key, int32_t len); bool Neon_Object_Set_String(bool *out, v8::Local object, const uint8_t *key, int32_t len, v8::Local val); @@ -88,7 +88,7 @@ extern "C" { bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); bool Neon_Fun_Init(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); - bool Neon_Fun_Template_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); + bool Neon_Fun_Template_New(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); void *Neon_Fun_GetDynamicCallback(v8::Persistent *obj); bool Neon_Fun_Call(v8::Local *out, v8::Isolate *isolate, v8::Local fun, v8::Local self, int32_t argc, v8::Local argv[]); bool Neon_Fun_CallThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]); @@ -115,13 +115,13 @@ extern "C" { void *Neon_Class_GetConstructKernel(v8::Persistent *wrapper); void *Neon_Class_GetAllocateKernel(v8::Persistent *wrapper); bool Neon_Class_Constructor(v8::Local *out, v8::Local ft); - bool Neon_Class_HasInstance(void *metadata, v8::Local v); + bool Neon_Class_HasInstance(void *metadata, v8::Persistent *v); bool Neon_Class_SetName(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length); void Neon_Class_GetName(const char **chars_out, size_t *len_out, v8::Isolate *isolate, void *metadata); void Neon_Class_ThrowThisError(v8::Isolate *isolate, void *metadata_pointer); - bool Neon_Class_AddMethod(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length, v8::Local method); - bool Neon_Class_MetadataToConstructor(v8::Local *out, v8::Isolate *isolate, void *metadata); - void *Neon_Class_GetInstanceInternals(v8::Local obj); + bool Neon_Class_AddMethod(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length, v8::Persistent *method); + bool Neon_Class_MetadataToConstructor(v8::Persistent *out, v8::Isolate *isolate, void *metadata); + void *Neon_Class_GetInstanceInternals(v8::Persistent *obj); uint32_t Neon_Module_GetVersion(); diff --git a/crates/neon-runtime/src/object.rs b/crates/neon-runtime/src/object.rs index 9b9dc3bcf..e55ceec83 100644 --- a/crates/neon-runtime/src/object.rs +++ b/crates/neon-runtime/src/object.rs @@ -24,13 +24,13 @@ extern "C" { /// Mutates the `out` argument provided to refer to the `v8::Local` value at the `index` /// provided of the `v8::Object`. Returns `false` if the result couldn't be retrieved. #[link_name = "Neon_Object_Get_Index"] - pub fn get_index(out: &mut Local, object: Local, index: u32) -> bool; + pub fn get_index(out: &Persistent, object: &Persistent, index: u32) -> bool; /// Sets the key value of a `v8::Object` at the `index` provided. Also mutates the `out` /// argument provided to refer to a `v8::Local` boolean value, `true` if the set was /// successful. #[link_name = "Neon_Object_Set_Index"] - pub fn set_index(out: &mut bool, object: Local, index: u32, val: Local) -> bool; + pub fn set_index(out: &mut bool, object: &Persistent, index: u32, val: &Persistent) -> bool; /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `v8::String`'s /// underlying content. Returns `false` if the value couldn't be retrieved. diff --git a/src/context/internal.rs b/src/context/internal.rs index 2f4eee311..ae1da9fba 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -10,7 +10,7 @@ use neon_runtime::scope::Root; use typed_arena::Arena; use types::{JsObject, Managed}; use object::class::ClassMap; -use result::NeonResult; +use result::{NeonResult, Throw}; use super::ModuleContext; #[repr(C)] @@ -198,6 +198,25 @@ pub trait ContextInternal<'a>: Sized { unsafe fn alloc_persistent(&mut self) -> &'a raw::Persistent { self.persistent_arena().alloc() } + + fn new bool>(&mut self, init: F) -> NeonResult<&'a T> { + unsafe { + let h = self.alloc_persistent(); + if init(h) { + Ok(T::from_raw(h)) + } else { + Err(Throw) + } + } + } + + fn new_infallible(&mut self, init: F) -> &'a T { + unsafe { + let h = self.alloc_persistent(); + init(h); + T::from_raw(h) + } + } } pub fn initialize_module(exports: raw::Local, init: fn(ModuleContext) -> NeonResult<()>) { diff --git a/src/context/mod.rs b/src/context/mod.rs index 99caac813..82b2616db 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -12,7 +12,7 @@ use neon_runtime; use neon_runtime::raw; use borrow::{Ref, RefMut, Borrow, BorrowMut}; use borrow::internal::Ledger; -use types::{Value, JsValue, JsObject, /*JsArray,*/ JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined, build_infallible}; +use types::{Value, JsValue, JsObject, /*JsArray,*/ JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; use types::binary::{JsArrayBuffer, JsBuffer}; use types::error::JsError; use object::{Object, This}; @@ -29,7 +29,7 @@ impl CallbackInfo { pub fn data<'a, C: Context<'a>>(&self, cx: &mut C) -> &'a JsValue { let isolate = { cx.isolate().to_raw() }; - build_infallible(cx, |out| unsafe { + cx.new_infallible(|out| unsafe { neon_runtime::call::init_data(&self.info, isolate, out) }) } @@ -40,7 +40,6 @@ impl CallbackInfo { pub fn set_return<'a, 'b, T: Value>(&'a self, value: &'b T) { unsafe { - // FIXME: Value should have a conversion function like to_raw() neon_runtime::call::set_return_thin(&self.info, value.to_raw()); } } @@ -65,7 +64,7 @@ impl CallbackInfo { } let isolate = { cx.isolate().to_raw() }; unsafe { - Some(build_infallible(cx, |out| { + Some(cx.new_infallible(|out| { neon_runtime::call::init_get(&self.info, isolate, i, out) })) } @@ -77,18 +76,17 @@ impl CallbackInfo { } let isolate = { cx.isolate().to_raw() }; unsafe { - Ok(build_infallible(cx, |out| { + Ok(cx.new_infallible(|out| { neon_runtime::call::init_get(&self.info, isolate, i, out) })) } } - pub fn this<'b, V: Context<'b>>(&self, _: &mut V) -> raw::Local { - unsafe { - let mut local: raw::Local = std::mem::zeroed(); - neon_runtime::call::this(std::mem::transmute(&self.info), &mut local); - local - } + pub fn this<'b, C: Context<'b>>(&self, cx: &mut C) -> &'b JsValue { + let isolate = { cx.isolate().to_raw() }; + cx.new_infallible(|out| unsafe { + neon_runtime::call::this(&self.info, out, isolate) + }) } } @@ -355,13 +353,9 @@ impl<'a> ModuleContext<'a> { /// Convenience method for exporting a Neon class constructor from a module. pub fn export_class(&mut self, key: &str) -> NeonResult<()> { - // FIXME: implement this - /* let constructor = T::constructor(self)?; self.exports.set(self, key, constructor)?; Ok(()) - */ - unimplemented!() } /// Exports a JavaScript value from a Neon module. diff --git a/src/object/class/internal.rs b/src/object/class/internal.rs index b0da2de9d..60fbefae7 100644 --- a/src/object/class/internal.rs +++ b/src/object/class/internal.rs @@ -7,7 +7,7 @@ use super::{Class, ClassInternal, Callback}; use context::{CallbackInfo, CallContext, Context}; use context::internal::ContextInternal; use result::{NeonResult, Throw}; -use types::{JsFunction, JsValue, JsObject, JsUndefined, Managed}; +use types::{JsFunction, JsValue, JsObject, JsUndefined, Managed, Value}; use types::error::convert_panics; #[repr(C)] @@ -15,27 +15,24 @@ pub struct MethodCallback(pub fn(CallContext) -> NeonResult<&JsValu impl Callback<()> for MethodCallback { extern "C" fn invoke(info: &CallbackInfo) { - // FIXME: implement this - /* unsafe { info.with_cx::(|mut cx| { - let data = info.data(); - let this: Handle = Handle::new_internal(JsValue::from_raw(info.this(&mut cx))); + let data = info.data(&mut cx); + let this = info.this(&mut cx); if !this.is_a::() { + let isolate = { cx.isolate().to_raw() }; if let Ok(metadata) = T::metadata(&mut cx) { - neon_runtime::class::throw_this_error(mem::transmute(cx.isolate()), metadata.pointer); + neon_runtime::class::throw_this_error(isolate, metadata.pointer); } return; - }; - let dynamic_callback: fn(CallContext) -> JsResult = + } + let dynamic_callback: fn(CallContext) -> NeonResult<&JsValue> = mem::transmute(neon_runtime::fun::get_dynamic_callback(data.to_raw())); if let Ok(value) = convert_panics(|| { dynamic_callback(cx) }) { info.set_return(value); } }) } - */ - unimplemented!() } fn as_ptr(self) -> *mut c_void { @@ -140,16 +137,13 @@ pub struct ClassMetadata { impl ClassMetadata { pub unsafe fn constructor<'a, T: Class, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsFunction> { - // FIXME: implement this - unimplemented!() - /* - build(|out| { - neon_runtime::class::metadata_to_constructor(out, mem::transmute(cx.isolate()), self.pointer) + let isolate = { cx.isolate().to_raw() }; + cx.new(|out| { + neon_runtime::class::metadata_to_constructor(out, isolate, self.pointer) }) - */ } - pub unsafe fn has_instance(&self, value: raw::Local) -> bool { + pub unsafe fn has_instance(&self, value: &raw::Persistent) -> bool { neon_runtime::class::has_instance(self.pointer, value) } } diff --git a/src/object/class/mod.rs b/src/object/class/mod.rs index 48aa984e9..ba1aba209 100644 --- a/src/object/class/mod.rs +++ b/src/object/class/mod.rs @@ -98,12 +98,8 @@ pub trait Class: Managed + Any { /// Produces a handle to the constructor function for this class. fn constructor<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'a JsFunction> { - // FIXME: implement this -/* let metadata = Self::metadata(cx)?; unsafe { metadata.constructor(cx) } -*/ - unimplemented!() } /// Convenience method for constructing new instances of this class without having to extract the constructor function. @@ -111,12 +107,8 @@ pub trait Class: Managed + Any { where A: Value + 'b, AS: IntoIterator { - // FIXME: implement this -/* let constructor = Self::constructor(cx)?; constructor.construct(cx, args) -*/ - unimplemented!() } #[doc(hidden)] @@ -172,16 +164,14 @@ pub(crate) trait ClassInternal: Class { } for (name, method) in descriptor.methods { - // FIXME: implement this with JsValue - /* - let method: Handle = build(|out| { + let method: &JsValue = cx.new(|out| { let callback = method.into_c_callback(); neon_runtime::fun::new_template(out, isolate, callback) })?; + if !neon_runtime::class::add_method(isolate, metadata_pointer, name.as_ptr(), name.len() as u32, method.to_raw()) { return Err(Throw); } - */ } let metadata = ClassMetadata { @@ -199,8 +189,6 @@ impl ClassInternal for T { } impl ValueInternal for T { fn name() -> String { - // FIXME: implement this - /* let mut isolate: Isolate = unsafe { mem::transmute(neon_runtime::call::current_isolate()) }; @@ -215,13 +203,9 @@ impl ValueInternal for T { String::from_utf8_lossy(slice::from_raw_parts_mut(chars, len)).to_string() } } - */ - unimplemented!() } fn is_typeof(value: &Other) -> bool { - // FIXME: implement this - /* let mut isolate: Isolate = unsafe { mem::transmute(neon_runtime::call::current_isolate()) }; @@ -232,8 +216,6 @@ impl ValueInternal for T { metadata.has_instance(value.to_raw()) } } - */ - unimplemented!() } } @@ -243,14 +225,10 @@ impl<'a, T: Class> Borrow for &'a T { type Target = &'a mut T::Internals; fn try_borrow<'b>(self, lock: &'b Lock<'b>) -> Result, LoanError> { - // FIXME: implement this - /* unsafe { let ptr: *mut c_void = neon_runtime::class::get_instance_internals(self.to_raw()); Ref::new(lock, mem::transmute(ptr)) } - */ - unimplemented!() } } @@ -264,14 +242,10 @@ impl<'a, T: Class> Borrow for &'a mut T { impl<'a, T: Class> BorrowMut for &'a mut T { fn try_borrow_mut<'b>(self, lock: &'b Lock<'b>) -> Result, LoanError> { - // FIXME: implement this - /* unsafe { let ptr: *mut c_void = neon_runtime::class::get_instance_internals(self.to_raw()); RefMut::new(lock, mem::transmute(ptr)) } - */ - unimplemented!() } } diff --git a/src/object/mod.rs b/src/object/mod.rs index 9d879fb99..fbea165a7 100644 --- a/src/object/mod.rs +++ b/src/object/mod.rs @@ -4,7 +4,7 @@ pub(crate) mod class; use neon_runtime; use neon_runtime::raw; -use types::{JsValue, JsArray, Managed, Value, build}; +use types::{JsValue, JsArray, Managed, Value}; use types::utf8::Utf8; use context::Context; use result::{NeonResult, Throw}; @@ -19,15 +19,11 @@ pub trait PropertyKey { impl PropertyKey for u32 { unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { - // FIXME: implement this - // was: neon_runtime::object::get_index(out, obj, self) - unimplemented!() + neon_runtime::object::get_index(out, obj, self) } unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { - // FIXME: implement this - // was: neon_runtime::object::set_index(out, obj, self, val) - unimplemented!() + neon_runtime::object::set_index(out, obj, self, val) } } @@ -55,12 +51,12 @@ impl<'a, T: Value> PropertyKey for &'a T { pub trait Object: Value { fn get<'a, C: Context<'a>, K: PropertyKey>(&self, cx: &mut C, key: K) -> NeonResult<&'a JsValue> { - build(cx, |out| { unsafe { key.get_from(out, self.to_raw()) } }) + cx.new(|out| { unsafe { key.get_from(out, self.to_raw()) } }) } fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsArray> { let isolate = { cx.isolate().to_raw() }; - build(cx, |out| unsafe { + cx.new(|out| unsafe { neon_runtime::object::get_own_property_names(out, isolate, self.to_raw()) }) } diff --git a/src/types/binary.rs b/src/types/binary.rs index 06d7e8157..48feb0dea 100644 --- a/src/types/binary.rs +++ b/src/types/binary.rs @@ -7,7 +7,7 @@ use std::slice; use context::{Context, Lock}; use borrow::{Borrow, BorrowMut, Ref, RefMut, LoanError}; use borrow::internal::Pointer; -use types::{Object, Managed, Value, build}; +use types::{Object, Managed, Value}; use types::internal::ValueInternal; use result::NeonResult; use neon_runtime; @@ -22,16 +22,16 @@ impl JsBuffer { /// Constructs a new `Buffer` object, safely zero-filled. pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { let isolate = cx.isolate().to_raw(); - build(cx, |out| { - unsafe { neon_runtime::buffer::init_safe(out, isolate, size) } + cx.new(|out| unsafe { + neon_runtime::buffer::init_safe(out, isolate, size) }) } /// Constructs a new `Buffer` object, unsafely filled with uninitialized data. pub unsafe fn uninitialized<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { let isolate = cx.isolate().to_raw(); - build(cx, |out| { - unsafe { neon_runtime::buffer::init_unsafe(out, isolate, size) } + cx.new(|out| unsafe { + neon_runtime::buffer::init_unsafe(out, isolate, size) }) } @@ -60,8 +60,8 @@ impl JsArrayBuffer { /// Constructs a new `ArrayBuffer` object with the given size, in bytes. pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsArrayBuffer> { let isolate = { cx.isolate().to_raw() }; - build(cx, |out| { - unsafe { neon_runtime::arraybuffer::init(out, isolate, size) } + cx.new(|out| unsafe { + neon_runtime::arraybuffer::init(out, isolate, size) }) } diff --git a/src/types/error.rs b/src/types/error.rs index 2de273d70..1c56f1540 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -7,7 +7,7 @@ use neon_runtime::raw; use context::Context; use result::{NeonResult, Throw}; -use types::{Object, Value, ValueInternal, Managed, build}; +use types::{Object, Value, ValueInternal, Managed}; use types::utf8::Utf8; /// A JS `Error` object. @@ -34,7 +34,7 @@ impl JsError { pub fn error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; let isolate = { cx.isolate().to_raw() }; - build(cx, |out| unsafe { + cx.new(|out| unsafe { neon_runtime::error::init_error(out, isolate, msg); true }) @@ -44,7 +44,7 @@ impl JsError { pub fn type_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; let isolate = { cx.isolate().to_raw() }; - build(cx, |out| unsafe { + cx.new(|out| unsafe { neon_runtime::error::init_type_error(out, isolate, msg); true }) @@ -54,7 +54,7 @@ impl JsError { pub fn range_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; let isolate = { cx.isolate().to_raw() }; - build(cx, |out| unsafe { + cx.new(|out| unsafe { neon_runtime::error::init_range_error(out, isolate, msg); true }) diff --git a/src/types/mod.rs b/src/types/mod.rs index e954900f5..587644bea 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -25,25 +25,6 @@ use self::utf8::Utf8; pub use self::binary::{JsBuffer, JsArrayBuffer, BinaryData, BinaryViewType}; pub use self::error::JsError; -pub(crate) fn build<'a, C: Context<'a>, T: Managed, F: FnOnce(&raw::Persistent) -> bool>(cx: &mut C, init: F) -> NeonResult<&'a T> { - unsafe { - let h = cx.alloc_persistent(); - if init(h) { - Ok(T::from_raw(h)) - } else { - Err(Throw) - } - } -} - -pub(crate) fn build_infallible<'a, C: Context<'a>, T: Managed, F: FnOnce(&raw::Persistent)>(cx: &mut C, init: F) -> &'a T { - unsafe { - let h = cx.alloc_persistent(); - init(h); - T::from_raw(h) - } -} - pub unsafe trait SuperType { } unsafe impl SuperType for JsValue { } @@ -432,7 +413,7 @@ impl JsArray { pub fn new<'a, C: Context<'a>>(cx: &mut C, len: u32) -> &'a JsArray { let isolate = { cx.isolate().to_raw() }; - build_infallible(cx, |out| unsafe { + cx.new_infallible(|out| unsafe { neon_runtime::array::init(out, isolate, len) }) } @@ -488,12 +469,10 @@ impl JsFunction { U: Value { let isolate = cx.isolate().to_raw(); - build(cx, |out| { - unsafe { - let isolate: *mut c_void = std::mem::transmute(isolate); - let callback = FunctionCallback(f).into_c_callback(); - neon_runtime::fun::init(out, isolate, callback) - } + cx.new(|out| unsafe { + let isolate: *mut c_void = std::mem::transmute(isolate); + let callback = FunctionCallback(f).into_c_callback(); + neon_runtime::fun::init(out, isolate, callback) }) } } @@ -518,23 +497,19 @@ impl JsFunction { { let mut args = args.into_iter().collect::>(); let (isolate, argc, argv) = unsafe { prepare_call(cx, &mut args) }?; - build(cx, |out| { - unsafe { - neon_runtime::fun::call_thin(out, isolate, self.to_raw(), this.to_raw(), argc, argv) - } + cx.new(|out| unsafe { + neon_runtime::fun::call_thin(out, isolate, self.to_raw(), this.to_raw(), argc, argv) }) } - pub fn construct<'a, 'b, C: Context<'a>, A, AS>(self, cx: &mut C, args: AS) -> NeonResult<&'a CL> + pub fn construct<'a, 'b, C: Context<'a>, A, AS>(&self, cx: &mut C, args: AS) -> NeonResult<&'a CL> where A: Value + 'b, AS: IntoIterator { let mut args = args.into_iter().collect::>(); let (isolate, argc, argv) = unsafe { prepare_call(cx, &mut args) }?; - build(cx, |out| { - unsafe { - neon_runtime::fun::construct_thin(out, isolate, self.to_raw(), argc, argv) - } + cx.new(|out| unsafe { + neon_runtime::fun::construct_thin(out, isolate, self.to_raw(), argc, argv) }) } } From f7c63adc483c4e4840f935c9c2c78ba7b7cf4df4 Mon Sep 17 00:00:00 2001 From: David Herman Date: Sat, 16 Feb 2019 16:22:39 -1000 Subject: [PATCH 05/11] Lots of cleanup and refactoring: - runtime API consistency improvements - eliminate HandleArena - build/build_infallible -> ContextInternal::new/new_infallible, and they abstract the extraction of the raw Isolate - abstract away ContextInternal::alloc_persistent into the internals of new/new_infallible - add ContextInternal::new_opt for string construction that can fail without throwing a JS exception - execute_scoped - uncomment cx.empty_array - rename persistent_arena to handles --- crates/neon-runtime/src/call.rs | 2 +- crates/neon-runtime/src/neon.cc | 25 ++++--- crates/neon-runtime/src/neon.h | 16 ++--- crates/neon-runtime/src/object.rs | 12 ++-- crates/neon-runtime/src/scope.rs | 4 +- src/context/internal.rs | 111 ++++++------------------------ src/context/mod.rs | 82 +++++++--------------- src/object/class/internal.rs | 3 +- src/object/class/mod.rs | 5 +- src/object/mod.rs | 42 ++++++----- src/types/binary.rs | 9 +-- src/types/error.rs | 9 +-- src/types/internal.rs | 1 - src/types/mod.rs | 92 +++++++++---------------- 14 files changed, 139 insertions(+), 274 deletions(-) diff --git a/crates/neon-runtime/src/call.rs b/crates/neon-runtime/src/call.rs index 56c7f0d3e..f7d9c884d 100644 --- a/crates/neon-runtime/src/call.rs +++ b/crates/neon-runtime/src/call.rs @@ -54,7 +54,7 @@ extern "C" { /// Initializes the `out` argument provided to refer to the value of the /// `v8::FunctionCallbackInfo` `Data`. #[link_name = "Neon_Call_InitData"] - pub fn init_data(info: &FunctionCallbackInfo, isolate: *mut Isolate, out: &Persistent); + pub fn init_data(info: &FunctionCallbackInfo, out: &Persistent, isolate: *mut Isolate); /// Gets the number of arguments passed to the function. #[link_name = "Neon_Call_Length"] diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index 8436426a7..104167662 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -44,7 +44,7 @@ extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Lo *out = info->Data(); } -extern "C" void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, v8::Persistent *out) { +extern "C" void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate) { Nan::HandleScope scope; v8::Local data = info->Data(); out->Reset(isolate, data); @@ -135,7 +135,7 @@ extern "C" bool Neon_Primitive_IsInt32(v8::Local p) { return p->IsInt32(); } -extern "C" bool Neon_Object_Get_Index(v8::Persistent *out, v8::Persistent *obj, uint32_t index) { +extern "C" bool Neon_Object_Get_Index(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *obj, uint32_t index) { Nan::HandleScope scope; v8::Local lobj = Nan::New(*obj); Nan::MaybeLocal maybe = Nan::Get(lobj, index); @@ -143,11 +143,11 @@ extern "C" bool Neon_Object_Get_Index(v8::Persistent *out, v8::Persis if (!maybe.ToLocal(&local)) { return false; } - out->Reset(v8::Isolate::GetCurrent(), local); + out->Reset(isolate, local); return true; } -extern "C" bool Neon_Object_Set_Index(bool *out, v8::Persistent *object, uint32_t index, v8::Persistent *val) { +extern "C" bool Neon_Object_Set_Index(bool *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index, v8::Persistent *val) { Nan::HandleScope scope; v8::Local lobject = Nan::New(*object); v8::Local lval = Nan::New(*val); @@ -175,7 +175,7 @@ extern "C" bool Neon_Object_Get_String(v8::Local *out, v8::Local *p_out, v8::Persistent *p_obj, const uint8_t *data, int32_t len) { +extern "C" bool Neon_Object_Get_StringThin(v8::Persistent *p_out, v8::Isolate *isolate, v8::Persistent *p_obj, const uint8_t *data, int32_t len) { Nan::HandleScope scope; v8::Local key; if (!Neon_ASCII_Key(&key, data, len)) { @@ -187,7 +187,7 @@ extern "C" bool Neon_Object_Get_StringThin(v8::Persistent *p_out, v8: if (!maybe.ToLocal(&result)) { return false; } - p_out->Reset(v8::Isolate::GetCurrent(), result); + p_out->Reset(isolate, result); return true; } @@ -201,7 +201,7 @@ extern "C" bool Neon_Object_Set_String(bool *out, v8::Local obj, con return maybe.IsJust() && (*out = maybe.FromJust(), true); } -extern "C" bool Neon_Object_Set_StringThin(bool *out, v8::Persistent *p_obj, const uint8_t *data, int32_t len, v8::Persistent *p_val) { +extern "C" bool Neon_Object_Set_StringThin(bool *out, v8::Isolate *isolate, v8::Persistent *p_obj, const uint8_t *data, int32_t len, v8::Persistent *p_val) { Nan::HandleScope scope; v8::Local key; if (!Neon_ASCII_Key(&key, data, len)) { @@ -218,10 +218,8 @@ extern "C" bool Neon_Object_Get(v8::Local *out, v8::Local return maybe.ToLocal(out); } -extern "C" bool Neon_Object_GetThin(v8::Persistent *p_out, v8::Persistent *p_obj, v8::Persistent *p_key) { +extern "C" bool Neon_Object_GetThin(v8::Persistent *p_out, v8::Isolate *isolate, v8::Persistent *p_obj, v8::Persistent *p_key) { Nan::HandleScope scope; - // FIXME: pass in the isolate - v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::Local object = Nan::New(*p_obj); v8::Local key = Nan::New(*p_key); Nan::MaybeLocal maybe = Nan::Get(object, key); @@ -242,7 +240,7 @@ extern "C" bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local< return false; } -extern "C" bool Neon_Object_SetThin(bool *out, v8::Persistent *p_obj, v8::Persistent *p_key, v8::Persistent *p_val) { +extern "C" bool Neon_Object_SetThin(bool *out, v8::Isolate *isolate, v8::Persistent *p_obj, v8::Persistent *p_key, v8::Persistent *p_val) { Nan::HandleScope scope; v8::Local object = Nan::New(*p_obj); v8::Local key = Nan::New(*p_key); @@ -430,9 +428,10 @@ extern "C" size_t Neon_Scope_AlignofEscapable() { return alignof(v8::EscapableHandleScope); } -extern "C" void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Local *out) { +extern "C" void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Persistent *out) { + Nan::HandleScope scope; auto ctx = isolate->GetCurrentContext(); - *out = ctx->Global(); + out->Reset(isolate, ctx->Global()); } extern "C" uint32_t Neon_Module_GetVersion() { diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index c0106851a..35703e807 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -20,7 +20,7 @@ extern "C" { bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info); void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolae); void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out); - void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, v8::Persistent *out); + void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate); int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info); void Neon_Call_Get(v8::FunctionCallbackInfo *info, int32_t i, v8::Local *out); void Neon_Call_InitGet(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out); @@ -37,16 +37,16 @@ extern "C" { void Neon_Object_Init(v8::Persistent *out, v8::Isolate *isolate); bool Neon_Object_GetOwnPropertyNames(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *obj); void *Neon_Object_GetIsolate(v8::Local obj); - bool Neon_Object_Get_Index(v8::Persistent *out, v8::Persistent *object, uint32_t index); - bool Neon_Object_Set_Index(bool *out, v8::Persistent *object, uint32_t index, v8::Persistent *val); + bool Neon_Object_Get_Index(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index); + bool Neon_Object_Set_Index(bool *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index, v8::Persistent *val); bool Neon_Object_Get_String(v8::Local *out, v8::Local object, const uint8_t *key, int32_t len); - bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Persistent *object, const uint8_t *key, int32_t len); + bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Isolate isolate, v8::Persistent *object, const uint8_t *key, int32_t len); bool Neon_Object_Set_String(bool *out, v8::Local object, const uint8_t *key, int32_t len, v8::Local val); - bool Neon_Object_Set_StringThin(bool *out, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); + bool Neon_Object_Set_StringThin(bool *out, v8::Isolate isolate, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); bool Neon_Object_Get(v8::Local *out, v8::Local object, v8::Local key); - bool Neon_Object_GetThin(v8::Persistent *out, v8::Persistent *object, v8::Persistent *key); + bool Neon_Object_GetThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, v8::Persistent *key); bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local key, v8::Local val); - bool Neon_Object_SetThin(bool *out, v8::Persistent *obj, v8::Persistent *key, v8::Persistent *val); + bool Neon_Object_SetThin(bool *out, v8::Isolate *isolate, v8::Persistent *obj, v8::Persistent *key, v8::Persistent *val); void Neon_Array_New(v8::Local *out, v8::Isolate *isolate, uint32_t length); void Neon_Array_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t length); @@ -84,7 +84,7 @@ extern "C" { size_t Neon_Scope_Alignof(); size_t Neon_Scope_SizeofEscapable(); size_t Neon_Scope_AlignofEscapable(); - void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Local *out); + void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Persistent *out); bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); bool Neon_Fun_Init(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); diff --git a/crates/neon-runtime/src/object.rs b/crates/neon-runtime/src/object.rs index e55ceec83..58dd5760c 100644 --- a/crates/neon-runtime/src/object.rs +++ b/crates/neon-runtime/src/object.rs @@ -24,13 +24,13 @@ extern "C" { /// Mutates the `out` argument provided to refer to the `v8::Local` value at the `index` /// provided of the `v8::Object`. Returns `false` if the result couldn't be retrieved. #[link_name = "Neon_Object_Get_Index"] - pub fn get_index(out: &Persistent, object: &Persistent, index: u32) -> bool; + pub fn get_index(out: &Persistent, isolate: *mut Isolate, object: &Persistent, index: u32) -> bool; /// Sets the key value of a `v8::Object` at the `index` provided. Also mutates the `out` /// argument provided to refer to a `v8::Local` boolean value, `true` if the set was /// successful. #[link_name = "Neon_Object_Set_Index"] - pub fn set_index(out: &mut bool, object: &Persistent, index: u32, val: &Persistent) -> bool; + pub fn set_index(out: &mut bool, isolate: *mut Isolate, object: &Persistent, index: u32, val: &Persistent) -> bool; /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `v8::String`'s /// underlying content. Returns `false` if the value couldn't be retrieved. @@ -40,7 +40,7 @@ extern "C" { /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `v8::String`'s /// underlying content. Returns `false` if the value couldn't be retrieved. #[link_name = "Neon_Object_Get_StringThin"] - pub fn get_string_thin(out: &Persistent, object: &Persistent, key: *const u8, len: i32) -> bool; + pub fn get_string_thin(out: &Persistent, isolate: *mut Isolate, object: &Persistent, key: *const u8, len: i32) -> bool; /// Sets the underlying content of a `v8::String` object. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. @@ -50,7 +50,7 @@ extern "C" { /// Sets the underlying content of a `v8::String` object. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. #[link_name = "Neon_Object_Set_StringThin"] - pub fn set_string_thin(out: &mut bool, object: &Persistent, key: *const u8, len: i32, val: &Persistent) -> bool; + pub fn set_string_thin(out: &mut bool, isolate: *mut Isolate, object: &Persistent, key: *const u8, len: i32, val: &Persistent) -> bool; /// Mutates the `out` argument provided to refer to the `v8::Local` value at the `key` /// provided. Returns `false` if the result couldn't be retrieved. @@ -60,7 +60,7 @@ extern "C" { /// Mutates the `out` argument provided to refer to the property value at the `key` /// provided. Returns `false` if the result couldn't be retrieved. #[link_name = "Neon_Object_GetThin"] - pub fn get_thin(out: &Persistent, object: &Persistent, key: &Persistent) -> bool; + pub fn get_thin(out: &Persistent, isolate: *mut Isolate, object: &Persistent, key: &Persistent) -> bool; /// Sets the key value of a `v8::Object` at the `key` provided. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. @@ -70,6 +70,6 @@ extern "C" { /// Sets the key value of a `v8::Object` at the `key` provided. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. #[link_name = "Neon_Object_SetThin"] - pub fn set_thin(out: &mut bool, object: &Persistent, key: &Persistent, val: &Persistent) -> bool; + pub fn set_thin(out: &mut bool, isolate: *mut Isolate, object: &Persistent, key: &Persistent, val: &Persistent) -> bool; } diff --git a/crates/neon-runtime/src/scope.rs b/crates/neon-runtime/src/scope.rs index a0a9f80dd..f7eef90b0 100644 --- a/crates/neon-runtime/src/scope.rs +++ b/crates/neon-runtime/src/scope.rs @@ -1,7 +1,7 @@ //! Facilities for working with `v8::HandleScope`s and `v8::EscapableHandleScope`s. use std::os::raw::c_void; -use raw::{HandleScope, EscapableHandleScope, InheritedHandleScope, Local, Isolate}; +use raw::{HandleScope, EscapableHandleScope, InheritedHandleScope, Local, Isolate, Persistent}; pub trait Root { unsafe fn allocate() -> Self; @@ -86,6 +86,6 @@ extern "C" { /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `global` /// object #[link_name = "Neon_Scope_GetGlobal"] - pub fn get_global(isolate: *mut c_void, out: &mut Local); + pub fn get_global(isolate: *mut c_void, out: &Persistent); } diff --git a/src/context/internal.rs b/src/context/internal.rs index ae1da9fba..abb3b6b87 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -1,7 +1,5 @@ use std; -use std::cell::{Cell, RefCell}; -use std::collections::LinkedList; -use std::marker::PhantomData; +use std::cell::Cell; use std::mem; use std::os::raw::c_void; use neon_runtime; @@ -55,9 +53,9 @@ pub struct ScopeMetadata { pub struct Scope<'a, R: Root + 'static> { pub metadata: ScopeMetadata, + // FIXME: can we ultimately get rid of this? pub handle_scope: &'a mut R, - pub handle_arena: HandleArena<'a>, - pub persistent_arena: &'a PersistentArena, + pub handles: &'a PersistentArena, } pub struct PersistentArena { @@ -82,70 +80,11 @@ impl PersistentArena { } } -const CHUNK_SIZE: usize = 16; - -type Chunk = [raw::Local; CHUNK_SIZE]; - -pub struct HandleArena<'a> { - chunks: Vec>, - pub(crate) chunk_allocated: usize, - phantom: PhantomData<&'a ()> -} - -impl<'a> HandleArena<'a> { - fn new() -> Self { - let mut chunks = Vec::with_capacity(16); - - chunks.push(Box::new(unsafe { mem::uninitialized() })); - - HandleArena { - chunks, - chunk_allocated: 0, - phantom: PhantomData - } - } - - pub unsafe fn alloc(&mut self) -> *mut raw::Local { - if self.chunk_allocated >= CHUNK_SIZE { - let mut chunk: Box = Box::new(mem::uninitialized()); - let p: *mut raw::Local = &mut chunk[0]; - self.chunks.push(chunk); - self.chunk_allocated = 1; - p - } else { - let chunk: &mut Box = self.chunks.last_mut().unwrap(); - let p: *mut raw::Local = &mut chunk[self.chunk_allocated]; - self.chunk_allocated += 1; - p - } - } -/* - fn alloc(&mut self, init: raw::Local) -> &'a raw::Local { - let p = if self.chunk_allocated >= CHUNK_SIZE { - let mut chunk: Box = Box::new(unsafe { mem::uninitialized() }); - chunk[0] = init; - let p: *const raw::Local = &chunk[0]; - self.chunks.push_back(chunk); - self.chunk_allocated = 1; - p - } else { - let chunk: &mut Box = self.chunks.back_mut().unwrap(); - chunk[self.chunk_allocated] = init; - let p: *const raw::Local = &chunk[self.chunk_allocated]; - self.chunk_allocated += 1; - p - }; - - unsafe { mem::transmute(p) } - } -*/ - -} - impl<'a, R: Root + 'static> Scope<'a, R> { + // FIXME: do we no longer need to ensure there's a HandleScope? pub fn with FnOnce(Scope<'b, R>) -> T>(f: F) -> T { let mut handle_scope: R = unsafe { R::allocate() }; - let persistent_arena = PersistentArena::new(); + let handles = PersistentArena::new(); let isolate = Isolate::current(); unsafe { handle_scope.enter(isolate.to_raw()); @@ -157,8 +96,7 @@ impl<'a, R: Root + 'static> Scope<'a, R> { active: Cell::new(true) }, handle_scope: &mut handle_scope, - handle_arena: HandleArena::new(), - persistent_arena: &persistent_arena, + handles: &handles, }; f(scope) }; @@ -171,8 +109,7 @@ impl<'a, R: Root + 'static> Scope<'a, R> { pub trait ContextInternal<'a>: Sized { fn scope_metadata(&self) -> &ScopeMetadata; - fn handle_arena(&mut self) -> &mut HandleArena<'a>; - fn persistent_arena(&self) -> &'a PersistentArena; + fn handles(&self) -> &'a PersistentArena; fn isolate(&self) -> Isolate { self.scope_metadata().isolate @@ -191,30 +128,24 @@ pub trait ContextInternal<'a>: Sized { fn activate(&self) { self.scope_metadata().active.set(true); } fn deactivate(&self) { self.scope_metadata().active.set(false); } - unsafe fn alloc(&mut self) -> *mut raw::Local { - self.handle_arena().alloc() + fn new bool>(&mut self, init: F) -> NeonResult<&'a T> { + self.new_opt(init).ok_or(Throw) } - unsafe fn alloc_persistent(&mut self) -> &'a raw::Persistent { - self.persistent_arena().alloc() + fn new_infallible(&mut self, init: F) -> &'a T { + let isolate = { self.isolate().to_raw() }; + let h = self.handles().alloc(); + init(h, isolate); + T::from_raw(h) } - fn new bool>(&mut self, init: F) -> NeonResult<&'a T> { - unsafe { - let h = self.alloc_persistent(); - if init(h) { - Ok(T::from_raw(h)) - } else { - Err(Throw) - } - } - } - - fn new_infallible(&mut self, init: F) -> &'a T { - unsafe { - let h = self.alloc_persistent(); - init(h); - T::from_raw(h) + fn new_opt bool>(&mut self, init: F) -> Option<&'a T> { + let isolate = { self.isolate().to_raw() }; + let h = self.handles().alloc(); + if init(h, isolate) { + Some(T::from_raw(h)) + } else { + None } } } diff --git a/src/context/mod.rs b/src/context/mod.rs index 82b2616db..568fd32fc 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -2,7 +2,6 @@ pub(crate) mod internal; -use std::ffi::c_void; use std; use std::cell::RefCell; use std::convert::Into; @@ -12,13 +11,13 @@ use neon_runtime; use neon_runtime::raw; use borrow::{Ref, RefMut, Borrow, BorrowMut}; use borrow::internal::Ledger; -use types::{Value, JsValue, JsObject, /*JsArray,*/ JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; +use types::{Value, JsValue, 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}; -use self::internal::{ContextInternal, Scope, ScopeMetadata, HandleArena, PersistentArena}; +use self::internal::{ContextInternal, Scope, ScopeMetadata, PersistentArena}; #[repr(C)] pub(crate) struct CallbackInfo { @@ -28,9 +27,8 @@ pub(crate) struct CallbackInfo { impl CallbackInfo { pub fn data<'a, C: Context<'a>>(&self, cx: &mut C) -> &'a JsValue { - let isolate = { cx.isolate().to_raw() }; - cx.new_infallible(|out| unsafe { - neon_runtime::call::init_data(&self.info, isolate, out) + cx.new_infallible(|out, isolate| unsafe { + neon_runtime::call::init_data(&self.info, out, isolate) }) } @@ -62,9 +60,8 @@ impl CallbackInfo { if i < 0 || i >= self.len() { return None; } - let isolate = { cx.isolate().to_raw() }; unsafe { - Some(cx.new_infallible(|out| { + Some(cx.new_infallible(|out, isolate| { neon_runtime::call::init_get(&self.info, isolate, i, out) })) } @@ -74,17 +71,13 @@ impl CallbackInfo { if i < 0 || i >= self.len() { return cx.throw_type_error("not enough arguments"); } - let isolate = { cx.isolate().to_raw() }; - unsafe { - Ok(cx.new_infallible(|out| { - neon_runtime::call::init_get(&self.info, isolate, i, out) - })) - } + Ok(cx.new_infallible(|out, isolate| unsafe { + neon_runtime::call::init_get(&self.info, isolate, i, out) + })) } pub fn this<'b, C: Context<'b>>(&self, cx: &mut C) -> &'b JsValue { - let isolate = { cx.isolate().to_raw() }; - cx.new_infallible(|out| unsafe { + cx.new_infallible(|out, isolate| unsafe { neon_runtime::call::this(&self.info, out, isolate) }) } @@ -175,7 +168,6 @@ pub trait Context<'a>: ContextInternal<'a> { f(contents) } -/* /// Executes a computation in a new memory management scope. /// /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape. @@ -191,14 +183,15 @@ pub trait Context<'a>: ContextInternal<'a> { result } +/* /// Executes a computation in a new memory management scope and computes a single result value that outlives the computation. /// /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape, with the exception of the result value, which is rooted in the outer context. /// /// This method can be useful for limiting the life of temporary values created during long-running computations, to prevent leaks. - fn compute_scoped(&self, f: F) -> JsResult<'a, V> + fn compute_scoped(&self, f: F) -> NeonResult<&'a V> where V: Value, - F: for<'b, 'c> FnOnce(ComputeContext<'b, 'c>) -> JsResult<'b, V> + F: for<'b, 'c> FnOnce(ComputeContext<'b, 'c>) -> NeonResult<&'b V> { self.check_active(); self.deactivate(); @@ -255,12 +248,10 @@ pub trait Context<'a>: ContextInternal<'a> { JsObject::new(self) } -/* /// Convenience method for creating an empty `JsArray` value. fn empty_array(&mut self) -> &'a JsArray { JsArray::new(self, 0) } -*/ /// Convenience method for creating an empty `JsArrayBuffer` value. fn array_buffer(&mut self, size: u32) -> NeonResult<&'a JsArrayBuffer> { @@ -274,11 +265,8 @@ pub trait Context<'a>: ContextInternal<'a> { /// Produces a handle to the JavaScript global object. fn global(&mut self) -> &'a JsObject { - let isolate = self.isolate().to_raw(); - JsObject::build(self, |out| { - unsafe { - neon_runtime::scope::get_global(isolate, out); - } + self.new_infallible(|out, isolate| unsafe { + neon_runtime::scope::get_global(isolate, out) }) } @@ -375,18 +363,13 @@ impl<'a> ContextInternal<'a> for ModuleContext<'a> { &self.scope.metadata } - fn handle_arena(&mut self) -> &mut HandleArena<'a> { - &mut self.scope.handle_arena - } - - fn persistent_arena(&self) -> &'a PersistentArena { - self.scope.persistent_arena + fn handles(&self) -> &'a PersistentArena { + self.scope.handles } } impl<'a> Context<'a> for ModuleContext<'a> { } -/* /// A view of the JS engine in the context of a scoped computation started by `Context::execute_scoped()`. pub struct ExecuteContext<'a> { scope: Scope<'a, raw::HandleScope> @@ -405,17 +388,14 @@ impl<'a> ContextInternal<'a> for ExecuteContext<'a> { &self.scope.metadata } - fn handle_arena(&mut self) -> &mut HandleArena<'a> { - &mut self.scope.handle_arena - } - - fn persistent_arena(&self) -> &'a PersistentArena { - self.scope.persistent_arena + fn handles(&self) -> &'a PersistentArena { + self.scope.handles } } impl<'a> Context<'a> for ExecuteContext<'a> { } +/* /// A view of the JS engine in the context of a scoped computation started by `Context::compute_scoped()`. pub struct ComputeContext<'a, 'outer> { scope: Scope<'a, raw::EscapableHandleScope>, @@ -440,12 +420,8 @@ impl<'a, 'b> ContextInternal<'a> for ComputeContext<'a, 'b> { &self.scope.metadata } - fn handle_arena(&mut self) -> &mut HandleArena<'a> { - &mut self.scope.handle_arena - } - - fn persistent_arena(&self) -> &'a PersistentArena { - self.scope.persistent_arena + fn handles(&self) -> &'a PersistentArena { + self.scope.handles } } @@ -504,12 +480,8 @@ impl<'a, T: This> ContextInternal<'a> for CallContext<'a, T> { &self.scope.metadata } - fn handle_arena(&mut self) -> &mut HandleArena<'a> { - &mut self.scope.handle_arena - } - - fn persistent_arena(&self) -> &'a PersistentArena { - self.scope.persistent_arena + fn handles(&self) -> &'a PersistentArena { + self.scope.handles } } @@ -541,12 +513,8 @@ impl<'a> ContextInternal<'a> for TaskContext<'a> { &self.scope.metadata } - fn handle_arena(&mut self) -> &mut HandleArena<'a> { - &mut self.scope.handle_arena - } - - fn persistent_arena(&self) -> &'a PersistentArena { - self.scope.persistent_arena + fn handles(&self) -> &'a PersistentArena { + self.scope.handles } } diff --git a/src/object/class/internal.rs b/src/object/class/internal.rs index 60fbefae7..557536c4f 100644 --- a/src/object/class/internal.rs +++ b/src/object/class/internal.rs @@ -137,8 +137,7 @@ pub struct ClassMetadata { impl ClassMetadata { pub unsafe fn constructor<'a, T: Class, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsFunction> { - let isolate = { cx.isolate().to_raw() }; - cx.new(|out| { + cx.new(|out, isolate| { neon_runtime::class::metadata_to_constructor(out, isolate, self.pointer) }) } diff --git a/src/object/class/mod.rs b/src/object/class/mod.rs index ba1aba209..8d6026ac0 100644 --- a/src/object/class/mod.rs +++ b/src/object/class/mod.rs @@ -8,7 +8,6 @@ use std::os::raw::c_void; use std::slice; use std::collections::HashMap; use neon_runtime; -use neon_runtime::raw; use neon_runtime::call::CCallback; use context::{Context, Lock, CallbackInfo}; use context::internal::Isolate; @@ -139,7 +138,7 @@ pub(crate) trait ClassInternal: Class { fn create<'a, C: Context<'a>>(cx: &mut C) -> NeonResult { let descriptor = Self::setup(cx)?; unsafe { - let isolate: *mut c_void = mem::transmute(cx.isolate()); + let isolate: *mut c_void = { cx.isolate().to_raw() }; let allocate = descriptor.allocate.into_c_callback(); let construct = descriptor.construct.map(|callback| callback.into_c_callback()).unwrap_or_default(); @@ -164,7 +163,7 @@ pub(crate) trait ClassInternal: Class { } for (name, method) in descriptor.methods { - let method: &JsValue = cx.new(|out| { + let method: &JsValue = cx.new(|out, isolate| { let callback = method.into_c_callback(); neon_runtime::fun::new_template(out, isolate, callback) })?; diff --git a/src/object/mod.rs b/src/object/mod.rs index fbea165a7..88c91feef 100644 --- a/src/object/mod.rs +++ b/src/object/mod.rs @@ -13,57 +13,61 @@ pub use self::class::{Class, ClassDescriptor}; /// A property key in a JavaScript object. pub trait PropertyKey { - unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool; - unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool; + unsafe fn get_from(self, out: &raw::Persistent, isolate: *mut raw::Isolate, obj: &raw::Persistent) -> bool; + unsafe fn set_from(self, out: &mut bool, isolate: *mut raw::Isolate, obj: &raw::Persistent, val: &raw::Persistent) -> bool; } impl PropertyKey for u32 { - unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { - neon_runtime::object::get_index(out, obj, self) + unsafe fn get_from(self, out: &raw::Persistent, isolate: *mut raw::Isolate, obj: &raw::Persistent) -> bool { + neon_runtime::object::get_index(out, isolate, obj, self) } - unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { - neon_runtime::object::set_index(out, obj, self, val) + unsafe fn set_from(self, out: &mut bool, isolate: *mut raw::Isolate, obj: &raw::Persistent, val: &raw::Persistent) -> bool { + neon_runtime::object::set_index(out, isolate, obj, self, val) } } impl<'a> PropertyKey for &'a str { - unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { + unsafe fn get_from(self, out: &raw::Persistent, isolate: *mut raw::Isolate, obj: &raw::Persistent) -> bool { let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); - neon_runtime::object::get_string_thin(out, obj, ptr, len) + // FIXME: rename the `_thin` back to normal + neon_runtime::object::get_string_thin(out, isolate, obj, ptr, len) } - unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { + unsafe fn set_from(self, out: &mut bool, isolate: *mut raw::Isolate, obj: &raw::Persistent, val: &raw::Persistent) -> bool { let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); - neon_runtime::object::set_string_thin(out, obj, ptr, len, val) + // FIXME: rename the `_thin` back to normal + neon_runtime::object::set_string_thin(out, isolate, obj, ptr, len, val) } } impl<'a, T: Value> PropertyKey for &'a T { - unsafe fn get_from(self, out: &raw::Persistent, obj: &raw::Persistent) -> bool { - neon_runtime::object::get_thin(out, obj, self.to_raw()) + unsafe fn get_from(self, out: &raw::Persistent, isolate: *mut raw::Isolate, obj: &raw::Persistent) -> bool { + // FIXME: rename the `_thin` back to normal + neon_runtime::object::get_thin(out, isolate, obj, self.to_raw()) } - unsafe fn set_from(self, out: &mut bool, obj: &raw::Persistent, val: &raw::Persistent) -> bool { - neon_runtime::object::set_thin(out, obj, self.to_raw(), val) + unsafe fn set_from(self, out: &mut bool, isolate: *mut raw::Isolate, obj: &raw::Persistent, val: &raw::Persistent) -> bool { + // FIXME: rename the `_thin` back to normal + neon_runtime::object::set_thin(out, isolate, obj, self.to_raw(), val) } } pub trait Object: Value { fn get<'a, C: Context<'a>, K: PropertyKey>(&self, cx: &mut C, key: K) -> NeonResult<&'a JsValue> { - cx.new(|out| { unsafe { key.get_from(out, self.to_raw()) } }) + cx.new(|out, isolate| { unsafe { key.get_from(out, isolate, self.to_raw()) } }) } fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsArray> { - let isolate = { cx.isolate().to_raw() }; - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { neon_runtime::object::get_own_property_names(out, isolate, self.to_raw()) }) } - fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(&self, _: &mut C, key: K, val: &W) -> NeonResult { + fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(&self, cx: &mut C, key: K, val: &W) -> NeonResult { let mut result = false; - if unsafe { key.set_from(&mut result, self.to_raw(), val.to_raw()) } { + let isolate = { cx.isolate().to_raw() }; + if unsafe { key.set_from(&mut result, isolate, self.to_raw(), val.to_raw()) } { Ok(result) } else { Err(Throw) diff --git a/src/types/binary.rs b/src/types/binary.rs index 48feb0dea..5a2d60b43 100644 --- a/src/types/binary.rs +++ b/src/types/binary.rs @@ -21,16 +21,14 @@ impl JsBuffer { /// Constructs a new `Buffer` object, safely zero-filled. pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { - let isolate = cx.isolate().to_raw(); - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { neon_runtime::buffer::init_safe(out, isolate, size) }) } /// Constructs a new `Buffer` object, unsafely filled with uninitialized data. pub unsafe fn uninitialized<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { - let isolate = cx.isolate().to_raw(); - cx.new(|out| unsafe { + cx.new(|out, isolate| { neon_runtime::buffer::init_unsafe(out, isolate, size) }) } @@ -59,8 +57,7 @@ impl JsArrayBuffer { /// Constructs a new `ArrayBuffer` object with the given size, in bytes. pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsArrayBuffer> { - let isolate = { cx.isolate().to_raw() }; - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { neon_runtime::arraybuffer::init(out, isolate, size) }) } diff --git a/src/types/error.rs b/src/types/error.rs index 1c56f1540..fd1828258 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -33,8 +33,7 @@ impl JsError { /// Creates a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class. pub fn error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; - let isolate = { cx.isolate().to_raw() }; - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { neon_runtime::error::init_error(out, isolate, msg); true }) @@ -43,8 +42,7 @@ impl JsError { /// Creates an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class. pub fn type_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; - let isolate = { cx.isolate().to_raw() }; - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { neon_runtime::error::init_type_error(out, isolate, msg); true }) @@ -53,8 +51,7 @@ impl JsError { /// Creates an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class. pub fn range_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; - let isolate = { cx.isolate().to_raw() }; - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { neon_runtime::error::init_range_error(out, isolate, msg); true }) diff --git a/src/types/internal.rs b/src/types/internal.rs index d642d70fc..84fc68436 100644 --- a/src/types/internal.rs +++ b/src/types/internal.rs @@ -1,7 +1,6 @@ use std::mem; use std::os::raw::c_void; use neon_runtime; -use neon_runtime::raw; use context::{CallbackInfo, FunctionContext}; use types::error::convert_panics; use types::{JsObject, Managed}; diff --git a/src/types/mod.rs b/src/types/mod.rs index 587644bea..15b673f38 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -15,8 +15,7 @@ use std::marker::PhantomData; use neon_runtime; use neon_runtime::raw; use context::{Context, FunctionContext}; -use context::internal::Isolate; -use result::{NeonResult, Throw, NeonResultExt}; +use result::{NeonResult, NeonResultExt}; use object::{Object, This}; use object::class::Callback; use self::internal::{ValueInternal, FunctionCallback}; @@ -169,11 +168,9 @@ pub struct JsUndefined(raw::Persistent); impl JsUndefined { pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsUndefined { - unsafe { - let h = cx.alloc_persistent(); - neon_runtime::primitive::init_undefined(h, cx.isolate().to_raw()); - JsUndefined::from_raw(h) - } + cx.new_infallible(|out, isolate| unsafe { + neon_runtime::primitive::init_undefined(out, isolate) + }) } } @@ -197,11 +194,9 @@ pub struct JsNull(raw::Persistent); impl JsNull { pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsNull { - unsafe { - let h = cx.alloc_persistent(); - neon_runtime::primitive::init_null(h, cx.isolate().to_raw()); - JsNull::from_raw(h) - } + cx.new_infallible(|out, isolate| unsafe { + neon_runtime::primitive::init_null(out, isolate) + }) } } @@ -223,11 +218,9 @@ pub struct JsBoolean(raw::Persistent); impl JsBoolean { pub fn new<'a, C: Context<'a>>(cx: &mut C, b: bool) -> &'a JsBoolean { - unsafe { - let h = cx.alloc_persistent(); - neon_runtime::primitive::init_boolean(h, cx.isolate().to_raw(), b); - JsBoolean::from_raw(h) - } + cx.new_infallible(|out, isolate| unsafe { + neon_runtime::primitive::init_boolean(out, isolate, b) + }) } pub fn value(&self) -> bool { @@ -318,20 +311,14 @@ impl JsString { } fn new_internal<'a, C: Context<'a>>(cx: &mut C, val: &str) -> Option<&'a JsString> { - let (ptr, len) = if let Some(small) = Utf8::from(val).into_small() { - small.lower() - } else { - return None; - }; - - unsafe { - let h = cx.alloc_persistent(); - if neon_runtime::string::new(h, cx.isolate().to_raw(), ptr, len) { - Some(JsString::from_raw(h)) - } else { - None - } - } + Utf8::from(val) + .into_small() + .and_then(|small| { + let (ptr, len) = small.lower(); + cx.new_opt(|out, isolate| unsafe { + neon_runtime::string::new(out, isolate, ptr, len) + }) + }) } } @@ -341,11 +328,9 @@ pub struct JsNumber(raw::Persistent); impl JsNumber { pub fn new<'a, C: Context<'a>, T: Into>(cx: &mut C, x: T) -> &'a JsNumber { - unsafe { - let h = cx.alloc_persistent(); - neon_runtime::primitive::init_number(h, cx.isolate().to_raw(), x.into()); - JsNumber::from_raw(h) - } + cx.new_infallible(|out, isolate| unsafe { + neon_runtime::primitive::init_number(out, isolate, x.into()) + }) } pub fn value(&self) -> f64 { @@ -388,19 +373,9 @@ unsafe impl This for JsObject { } impl JsObject { pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsObject { - unsafe { - let h = cx.alloc_persistent(); - neon_runtime::object::init(h, cx.isolate().to_raw()); - JsObject::from_raw(h) - } - } - - pub(crate) fn build<'a, C: Context<'a>, F: FnOnce(&mut raw::Local)>(cx: &mut C, init: F) -> &'a JsObject { - unsafe { - let local = cx.alloc(); - init(mem::transmute(local)); - mem::transmute(local) - } + cx.new_infallible(|out, isolate| unsafe { + neon_runtime::object::init(out, isolate) + }) } } @@ -412,8 +387,7 @@ pub struct JsArray(raw::Persistent); impl JsArray { pub fn new<'a, C: Context<'a>>(cx: &mut C, len: u32) -> &'a JsArray { - let isolate = { cx.isolate().to_raw() }; - cx.new_infallible(|out| unsafe { + cx.new_infallible(|out, isolate| unsafe { neon_runtime::array::init(out, isolate, len) }) } @@ -468,8 +442,7 @@ impl JsFunction { where C: Context<'a>, U: Value { - let isolate = cx.isolate().to_raw(); - cx.new(|out| unsafe { + cx.new(|out, isolate| unsafe { let isolate: *mut c_void = std::mem::transmute(isolate); let callback = FunctionCallback(f).into_c_callback(); neon_runtime::fun::init(out, isolate, callback) @@ -477,7 +450,7 @@ impl JsFunction { } } -unsafe fn prepare_call<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: &mut [&'b A]) -> NeonResult<(*mut c_void, i32, *mut c_void)> +unsafe fn prepare_args<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: &mut [&'b A]) -> NeonResult<(i32, *mut c_void)> where A: Value + 'b { let argv = args.as_mut_ptr(); @@ -485,8 +458,7 @@ unsafe fn prepare_call<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: &mut [&'b A] if argc > V8_ARGC_LIMIT { return cx.throw_range_error("too many arguments"); } - let isolate: *mut c_void = std::mem::transmute(cx.isolate().to_raw()); - Ok((isolate, argc as i32, argv as *mut c_void)) + Ok((argc as i32, argv as *mut c_void)) } impl JsFunction { @@ -496,8 +468,8 @@ impl JsFunction { AS: IntoIterator { let mut args = args.into_iter().collect::>(); - let (isolate, argc, argv) = unsafe { prepare_call(cx, &mut args) }?; - cx.new(|out| unsafe { + let (argc, argv) = unsafe { prepare_args(cx, &mut args) }?; + cx.new(|out, isolate| unsafe { neon_runtime::fun::call_thin(out, isolate, self.to_raw(), this.to_raw(), argc, argv) }) } @@ -507,8 +479,8 @@ impl JsFunction { AS: IntoIterator { let mut args = args.into_iter().collect::>(); - let (isolate, argc, argv) = unsafe { prepare_call(cx, &mut args) }?; - cx.new(|out| unsafe { + let (argc, argv) = unsafe { prepare_args(cx, &mut args) }?; + cx.new(|out, isolate| unsafe { neon_runtime::fun::construct_thin(out, isolate, self.to_raw(), argc, argv) }) } From d8d5f0b9d2fb0257e01fa6618f712b368d985457 Mon Sep 17 00:00:00 2001 From: David Herman Date: Wed, 20 Feb 2019 22:24:54 -1000 Subject: [PATCH 06/11] - implemented compute_scoped - eliminated all HandleScopes - changed classes to use Persistents --- crates/neon-runtime/src/neon.cc | 46 ++---------------- crates/neon-runtime/src/neon.h | 17 ++----- crates/neon-runtime/src/raw.rs | 39 --------------- crates/neon-runtime/src/scope.rs | 81 +++----------------------------- src/context/internal.rs | 45 ++++++++---------- src/context/mod.rs | 25 +++------- src/lib.rs | 5 +- 7 files changed, 44 insertions(+), 214 deletions(-) diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index 104167662..abc2b1bf1 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -29,7 +29,7 @@ extern "C" bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info) return info->IsConstructCall(); } -extern "C" void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate) { +extern "C" void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate) { Nan::HandleScope scope; out->Reset(isolate, info->This()); } @@ -381,13 +381,10 @@ extern "C" bool Neon_Tag_IsArrayBuffer(v8::Persistent *val) { return local->IsArrayBuffer(); } -extern "C" void Neon_Scope_Escape(v8::Local *out, Nan::EscapableHandleScope *scope, v8::Local value) { - *out = scope->Escape(value); -} - -extern "C" void Neon_Scope_Chained(void *out, void *closure, Neon_ChainedScopeCallback callback, void *parent_scope) { - Nan::EscapableHandleScope v8_scope; - callback(out, parent_scope, &v8_scope, closure); +extern "C" void Neon_Scope_ClonePersistent(v8::Isolate *isolate, v8::Persistent *to, v8::Persistent *from) { + Nan::HandleScope scope; + v8::Local local = Nan::New(*from); + to->Reset(isolate, local); } extern "C" void Neon_Scope_Nested(void *out, void *closure, Neon_NestedScopeCallback callback, void *realm) { @@ -395,39 +392,6 @@ extern "C" void Neon_Scope_Nested(void *out, void *closure, Neon_NestedScopeCall callback(out, realm, closure); } -extern "C" void Neon_Scope_Enter(v8::HandleScope *scope, v8::Isolate *isolate) { - void *p = scope; - ::new (p) v8::HandleScope(isolate); -} - -extern "C" void Neon_Scope_Exit(v8::HandleScope *scope) { - scope->HandleScope::~HandleScope(); -} -extern "C" void Neon_Scope_Enter_Escapable(v8::EscapableHandleScope *scope, v8::Isolate *isolate) { - void *p = scope; - ::new (p) v8::EscapableHandleScope(isolate); -} - -extern "C" void Neon_Scope_Exit_Escapable(v8::EscapableHandleScope *scope) { - scope->EscapableHandleScope::~EscapableHandleScope(); -} - -extern "C" size_t Neon_Scope_Sizeof() { - return sizeof(v8::HandleScope); -} - -extern "C" size_t Neon_Scope_Alignof() { - return alignof(v8::HandleScope); -} - -extern "C" size_t Neon_Scope_SizeofEscapable() { - return sizeof(v8::EscapableHandleScope); -} - -extern "C" size_t Neon_Scope_AlignofEscapable() { - return alignof(v8::EscapableHandleScope); -} - extern "C" void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Persistent *out) { Nan::HandleScope scope; auto ctx = isolate->GetCurrentContext(); diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index 35703e807..bbc68e545 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -18,7 +18,7 @@ extern "C" { void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo *info); void *Neon_Call_CurrentIsolate(); bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info); - void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolae); + void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate); void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out); void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate); int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info); @@ -40,9 +40,9 @@ extern "C" { bool Neon_Object_Get_Index(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index); bool Neon_Object_Set_Index(bool *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index, v8::Persistent *val); bool Neon_Object_Get_String(v8::Local *out, v8::Local object, const uint8_t *key, int32_t len); - bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Isolate isolate, v8::Persistent *object, const uint8_t *key, int32_t len); + bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, const uint8_t *key, int32_t len); bool Neon_Object_Set_String(bool *out, v8::Local object, const uint8_t *key, int32_t len, v8::Local val); - bool Neon_Object_Set_StringThin(bool *out, v8::Isolate isolate, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); + bool Neon_Object_Set_StringThin(bool *out, v8::Isolate *isolate, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); bool Neon_Object_Get(v8::Local *out, v8::Local object, v8::Local key); bool Neon_Object_GetThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, v8::Persistent *key); bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local key, v8::Local val); @@ -73,17 +73,8 @@ extern "C" { typedef void(*Neon_NestedScopeCallback)(void *, void *, void *); typedef void(*Neon_RootScopeCallback)(void *, void *, void *); - void Neon_Scope_Escape(v8::Local *out, Nan::EscapableHandleScope *scope, v8::Local value); + void Neon_Scope_ClonePersistent(v8::Isolate *isolate, v8::Persistent *to, v8::Persistent *from); void Neon_Scope_Nested(void *out, void *closure, Neon_NestedScopeCallback callback, void *realm); - void Neon_Scope_Chained(void *out, void *closure, Neon_ChainedScopeCallback callback, void *parent_scope); - void Neon_Scope_Enter(v8::HandleScope *scope, v8::Isolate *isolate); - void Neon_Scope_Exit(v8::HandleScope *scope); - void Neon_Scope_Enter_Escapable(v8::EscapableHandleScope *scope, v8::Isolate *isolate); - void Neon_Scope_Exit_Escapable(v8::EscapableHandleScope *scope); - size_t Neon_Scope_Sizeof(); - size_t Neon_Scope_Alignof(); - size_t Neon_Scope_SizeofEscapable(); - size_t Neon_Scope_AlignofEscapable(); void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Persistent *out); bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); diff --git a/crates/neon-runtime/src/raw.rs b/crates/neon-runtime/src/raw.rs index f015523ee..e68d05f73 100644 --- a/crates/neon-runtime/src/raw.rs +++ b/crates/neon-runtime/src/raw.rs @@ -68,42 +68,3 @@ pub type FunctionCallbackInfo = c_void; /// Represents an instance of the V8 runtime. pub type Isolate = c_void; - -const HANDLE_SCOPE_SIZE: usize = 24; - -/// A V8 `HandleScope`. -/// -/// A `HandleScope` contains `Local` handles. `HandleScope`s are used by V8 to help the garbage -/// collector do its bookkeeping. Once a new `HandleScope` is created all subsequently created -/// `Local` handles will be contained in it. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct HandleScope { - pub align_to_pointer: [*mut c_void; 0], - pub fields: [u8; HANDLE_SCOPE_SIZE] -} - -impl HandleScope { - pub fn new() -> HandleScope { unsafe { mem::zeroed() } } -} - -const ESCAPABLE_HANDLE_SCOPE_SIZE: usize = 32; - -/// A V8 `EscapableHandleScope`. -/// -/// A `EscapableHandleScope` is like `HandleScope` but also allows us to push `Local` handles out -/// to the previous `HandleScope`, permitting the `Local` value to remain rooted longer than the -/// `EscapableHandleScope` where it was intially rooted. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct EscapableHandleScope { - pub align_to_pointer: [*mut c_void; 0], - pub fields: [u8; ESCAPABLE_HANDLE_SCOPE_SIZE] -} - -impl EscapableHandleScope { - pub fn new() -> EscapableHandleScope { unsafe { mem::zeroed() } } -} - -#[derive(Clone, Copy)] -pub struct InheritedHandleScope; diff --git a/crates/neon-runtime/src/scope.rs b/crates/neon-runtime/src/scope.rs index f7eef90b0..9c6c16b86 100644 --- a/crates/neon-runtime/src/scope.rs +++ b/crates/neon-runtime/src/scope.rs @@ -1,91 +1,22 @@ -//! Facilities for working with `v8::HandleScope`s and `v8::EscapableHandleScope`s. +//! Facilities for working with `v8::HandleScope`s. use std::os::raw::c_void; -use raw::{HandleScope, EscapableHandleScope, InheritedHandleScope, Local, Isolate, Persistent}; - -pub trait Root { - unsafe fn allocate() -> Self; - unsafe fn enter(&mut self, *mut Isolate); - unsafe fn exit(&mut self); -} - -impl Root for HandleScope { - unsafe fn allocate() -> Self { HandleScope::new() } - unsafe fn enter(&mut self, isolate: *mut Isolate) { - enter(self, isolate) - } - unsafe fn exit(&mut self) { - exit(self) - } -} - -impl Root for EscapableHandleScope { - unsafe fn allocate() -> Self { EscapableHandleScope::new() } - unsafe fn enter(&mut self, isolate: *mut Isolate) { - enter_escapable(self, isolate) - } - unsafe fn exit(&mut self) { - exit_escapable(self) - } -} - -impl Root for InheritedHandleScope { - unsafe fn allocate() -> Self { InheritedHandleScope } - unsafe fn enter(&mut self, _: *mut Isolate) { } - unsafe fn exit(&mut self) { } -} +use raw::{Isolate, Persistent}; extern "C" { - /// Mutates the `out` argument provided to refer to the newly escaped `v8::Local` value. - #[link_name = "Neon_Scope_Escape"] - pub fn escape(out: &mut Local, scope: *mut EscapableHandleScope, value: Local); - - /// Creates a `v8::EscapableHandleScope` and calls the `callback` provided with the argument - /// signature `(out, parent_scope, &v8_scope, closure)`. - #[link_name = "Neon_Scope_Chained"] - pub fn chained(out: *mut c_void, closure: *mut c_void, callback: extern fn(&mut c_void, *mut c_void, *mut c_void, *mut c_void), parent_scope: *mut c_void); + /// Clones one persistent handle into another. + #[link_name = "Neon_Scope_ClonePersistent"] + pub fn clone_persistent(isolate: *mut Isolate, to: &Persistent, from: &Persistent); /// Creates a `v8::HandleScope` and calls the `callback` provided with the argument signature /// `(out, realm, closure)`. #[link_name = "Neon_Scope_Nested"] pub fn nested(out: *mut c_void, closure: *mut c_void, callback: extern fn(&mut c_void, *mut c_void, *mut c_void), realm: *mut c_void); - /// Instantiates a new `v8::HandleScope`. - #[link_name = "Neon_Scope_Enter"] - pub fn enter(scope: &mut HandleScope, isolate: *mut c_void); - - /// Destructs a `v8::HandleScope`. - #[link_name = "Neon_Scope_Exit"] - pub fn exit(scope: &mut HandleScope); - - /// Instantiates a new `v8::HandleScope`. - #[link_name = "Neon_Scope_Enter_Escapable"] - pub fn enter_escapable(scope: &mut EscapableHandleScope, isolate: *mut c_void); - - /// Destructs a `v8::HandleScope`. - #[link_name = "Neon_Scope_Exit_Escapable"] - pub fn exit_escapable(scope: &mut EscapableHandleScope); - - /// Gets the size of a `v8::HandleScope`. - #[link_name = "Neon_Scope_Sizeof"] - pub fn size() -> usize; - - /// Gets the alignment requirement of a `v8::HandleScope`. - #[link_name = "Neon_Scope_Alignof"] - pub fn alignment() -> usize; - - /// Gets the size of a `v8::EscapableHandleScope`. - #[link_name = "Neon_Scope_SizeofEscapable"] - pub fn escapable_size() -> usize; - - /// Gets the alignment requirement of a `v8::EscapableHandleScope`. - #[link_name = "Neon_Scope_AlignofEscapable"] - pub fn escapable_alignment() -> usize; - /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `global` /// object #[link_name = "Neon_Scope_GetGlobal"] - pub fn get_global(isolate: *mut c_void, out: &Persistent); + pub fn get_global(isolate: *mut Isolate, out: &Persistent); } diff --git a/src/context/internal.rs b/src/context/internal.rs index abb3b6b87..27c4e8bc4 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -4,7 +4,6 @@ use std::mem; use std::os::raw::c_void; use neon_runtime; use neon_runtime::raw; -use neon_runtime::scope::Root; use typed_arena::Arena; use types::{JsObject, Managed}; use object::class::ClassMap; @@ -51,13 +50,12 @@ pub struct ScopeMetadata { active: Cell } -pub struct Scope<'a, R: Root + 'static> { +pub struct Scope<'a> { pub metadata: ScopeMetadata, - // FIXME: can we ultimately get rid of this? - pub handle_scope: &'a mut R, pub handles: &'a PersistentArena, } +// FIXME: rename to HandleArena pub struct PersistentArena { handles: Arena, } @@ -78,32 +76,28 @@ impl PersistentArena { mem::transmute(ptr) } } + + pub(crate) fn clone<'a, 'b>(&'a self, isolate: *mut raw::Isolate, handle: &'b raw::Persistent) -> &'a raw::Persistent { + let new_ptr = self.alloc(); + unsafe { + neon_runtime::scope::clone_persistent(isolate, new_ptr, handle); + } + new_ptr + } } -impl<'a, R: Root + 'static> Scope<'a, R> { - // FIXME: do we no longer need to ensure there's a HandleScope? - pub fn with FnOnce(Scope<'b, R>) -> T>(f: F) -> T { - let mut handle_scope: R = unsafe { R::allocate() }; +impl<'a> Scope<'a> { + pub fn with FnOnce(Scope<'b>) -> T>(f: F) -> T { let handles = PersistentArena::new(); let isolate = Isolate::current(); - unsafe { - handle_scope.enter(isolate.to_raw()); - } - let result = { - let scope = Scope { - metadata: ScopeMetadata { - isolate, - active: Cell::new(true) - }, - handle_scope: &mut handle_scope, - handles: &handles, - }; - f(scope) + let scope = Scope { + metadata: ScopeMetadata { + isolate, + active: Cell::new(true) + }, + handles: &handles, }; - unsafe { - handle_scope.exit(); - } - result + f(scope) } } @@ -151,6 +145,7 @@ pub trait ContextInternal<'a>: Sized { } pub fn initialize_module(exports: raw::Local, init: fn(ModuleContext) -> NeonResult<()>) { + // FIXME: this leaks if the module initialization panics let persistent = raw::Persistent::from_local(exports); ModuleContext::with(JsObject::from_raw(&persistent), |cx| { let _ = init(cx); diff --git a/src/context/mod.rs b/src/context/mod.rs index 568fd32fc..2476efbba 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -183,7 +183,6 @@ pub trait Context<'a>: ContextInternal<'a> { result } -/* /// Executes a computation in a new memory management scope and computes a single result value that outlives the computation. /// /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape, with the exception of the result value, which is rooted in the outer context. @@ -196,18 +195,12 @@ pub trait Context<'a>: ContextInternal<'a> { self.check_active(); self.deactivate(); let result = ComputeContext::with(|cx| { - unsafe { - let escapable_handle_scope = cx.scope.handle_scope as *mut raw::EscapableHandleScope; - let escapee = f(cx)?; - let mut result_local: raw::Local = std::mem::zeroed(); - neon_runtime::scope::escape(&mut result_local, escapable_handle_scope, escapee.to_raw()); - Ok(Handle::new_internal(V::from_raw(result_local))) - } + let escapee = f(cx)?; + Ok(V::from_raw(self.handles().clone(self.isolate().to_raw(), escapee.to_raw()))) }); self.activate(); result } -*/ /// Convenience method for creating a `JsBoolean` value. fn boolean(&mut self, b: bool) -> &'a JsBoolean { @@ -314,7 +307,7 @@ pub trait Context<'a>: ContextInternal<'a> { /// A view of the JS engine in the context of top-level initialization of a Neon module. pub struct ModuleContext<'a> { - scope: Scope<'a, raw::HandleScope>, + scope: Scope<'a>, exports: &'a JsObject, } @@ -322,8 +315,6 @@ impl<'a> UnwindSafe for ModuleContext<'a> { } impl<'a> ModuleContext<'a> { pub(crate) fn with FnOnce(ModuleContext<'b>) -> T>(exports: &'a JsObject, f: F) -> T { - debug_assert!(unsafe { neon_runtime::scope::size() } <= std::mem::size_of::()); - debug_assert!(unsafe { neon_runtime::scope::alignment() } <= std::mem::align_of::()); Scope::with(|scope| { f(ModuleContext { scope, @@ -372,7 +363,7 @@ impl<'a> Context<'a> for ModuleContext<'a> { } /// A view of the JS engine in the context of a scoped computation started by `Context::execute_scoped()`. pub struct ExecuteContext<'a> { - scope: Scope<'a, raw::HandleScope> + scope: Scope<'a> } impl<'a> ExecuteContext<'a> { @@ -395,10 +386,9 @@ impl<'a> ContextInternal<'a> for ExecuteContext<'a> { impl<'a> Context<'a> for ExecuteContext<'a> { } -/* /// A view of the JS engine in the context of a scoped computation started by `Context::compute_scoped()`. pub struct ComputeContext<'a, 'outer> { - scope: Scope<'a, raw::EscapableHandleScope>, + scope: Scope<'a>, phantom_inner: PhantomData<&'a ()>, phantom_outer: PhantomData<&'outer ()> } @@ -426,13 +416,12 @@ impl<'a, 'b> ContextInternal<'a> for ComputeContext<'a, 'b> { } impl<'a, 'b> Context<'a> for ComputeContext<'a, 'b> { } -*/ /// A view of the JS engine in the context of a function call. /// /// The type parameter `T` is the type of the `this`-binding. pub struct CallContext<'a, T: This> { - scope: Scope<'a, raw::HandleScope>, + scope: Scope<'a>, info: &'a CallbackInfo, phantom_type: PhantomData } @@ -497,7 +486,7 @@ pub type MethodContext<'a, T> = CallContext<'a, T>; pub struct TaskContext<'a> { /// We use an "inherited HandleScope" here because the C++ `neon::Task::complete` /// method sets up and tears down a `HandleScope` for us. - scope: Scope<'a, raw::InheritedHandleScope> + scope: Scope<'a> } impl<'a> TaskContext<'a> { diff --git a/src/lib.rs b/src/lib.rs index 15102f271..8319bceff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -250,10 +250,9 @@ macro_rules! declare_types { }; { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => { - #[derive(Copy, Clone)] #[repr(C)] $(#[$attr])* - pub struct $cls($crate::macro_internal::runtime::raw::Local); + pub struct $cls($crate::macro_internal::runtime::raw::Persistent); impl_managed!($cls); @@ -266,7 +265,7 @@ macro_rules! declare_types { #[derive(Copy, Clone)] #[repr(C)] $(#[$attr])* - struct $cls($crate::macro_internal::runtime::raw::Local); + struct $cls($crate::macro_internal::runtime::raw::Persistent); impl_managed!($cls); From 709037013a43bd27c189426ddc7bbb0243e54f98 Mon Sep 17 00:00:00 2001 From: David Herman Date: Wed, 20 Feb 2019 22:35:14 -1000 Subject: [PATCH 07/11] Remove remaining commented-out bits (CallContext::this, prelude re-exports) --- src/context/mod.rs | 10 ++++------ src/prelude.rs | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/context/mod.rs b/src/context/mod.rs index 2476efbba..2487974ef 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -11,7 +11,7 @@ use neon_runtime; use neon_runtime::raw; use borrow::{Ref, RefMut, Borrow, BorrowMut}; use borrow::internal::Ledger; -use types::{Value, JsValue, JsObject, JsArray, JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; +use types::{Managed, Value, JsValue, JsObject, JsArray, JsFunction, JsBoolean, JsNumber, JsString, StringResult, JsNull, JsUndefined}; use types::binary::{JsArrayBuffer, JsBuffer}; use types::error::JsError; use object::{Object, This}; @@ -456,12 +456,10 @@ impl<'a, T: This> CallContext<'a, T> { a.downcast_or_throw(self) } -/* - /// Produces a handle to the `this`-binding. - pub fn this(&mut self) -> Handle<'a, T> { - Handle::new_internal(T::as_this(self.info.this(self))) + /// Produces a handle to the called function's `this`-binding. + pub fn this(&mut self) -> &'a T { + T::as_this(self.info.this(self).to_raw()) } -*/ } impl<'a, T: This> ContextInternal<'a> for CallContext<'a, T> { diff --git a/src/prelude.rs b/src/prelude.rs index af51c3434..59bfaf816 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,8 +1,8 @@ //! A convenience module that re-exports the most commonly-used Neon APIs. -pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, /*JsObject,*/ /*JsArray,*/ JsFunction, Value}; +pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, JsObject, JsArray, JsFunction, Value}; pub use object::{Object, Class}; pub use borrow::{Borrow, BorrowMut}; -pub use context::{CallKind, Context, ModuleContext, /*ExecuteContext, ComputeContext,*/ CallContext, FunctionContext, MethodContext, TaskContext}; +pub use context::{CallKind, Context, ModuleContext, ExecuteContext, ComputeContext, CallContext, FunctionContext, MethodContext, TaskContext}; pub use result::NeonResult; pub use task::Task; From 32cfdd32017fe4dd0efaefae8f464f0a78821c22 Mon Sep 17 00:00:00 2001 From: David Herman Date: Wed, 20 Feb 2019 22:44:54 -1000 Subject: [PATCH 08/11] rename PersistentArena to HandleArena --- src/context/internal.rs | 13 ++++++------- src/context/mod.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/context/internal.rs b/src/context/internal.rs index 27c4e8bc4..bc43c0c61 100644 --- a/src/context/internal.rs +++ b/src/context/internal.rs @@ -52,17 +52,16 @@ pub struct ScopeMetadata { pub struct Scope<'a> { pub metadata: ScopeMetadata, - pub handles: &'a PersistentArena, + pub handles: &'a HandleArena, } -// FIXME: rename to HandleArena -pub struct PersistentArena { +pub struct HandleArena { handles: Arena, } -impl PersistentArena { +impl HandleArena { fn new() -> Self { - PersistentArena { + HandleArena { handles: Arena::with_capacity(16), } } @@ -88,7 +87,7 @@ impl PersistentArena { impl<'a> Scope<'a> { pub fn with FnOnce(Scope<'b>) -> T>(f: F) -> T { - let handles = PersistentArena::new(); + let handles = HandleArena::new(); let isolate = Isolate::current(); let scope = Scope { metadata: ScopeMetadata { @@ -103,7 +102,7 @@ impl<'a> Scope<'a> { pub trait ContextInternal<'a>: Sized { fn scope_metadata(&self) -> &ScopeMetadata; - fn handles(&self) -> &'a PersistentArena; + fn handles(&self) -> &'a HandleArena; fn isolate(&self) -> Isolate { self.scope_metadata().isolate diff --git a/src/context/mod.rs b/src/context/mod.rs index 2487974ef..81796240b 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -17,7 +17,7 @@ use types::error::JsError; use object::{Object, This}; use object::class::Class; use result::{NeonResult, Throw}; -use self::internal::{ContextInternal, Scope, ScopeMetadata, PersistentArena}; +use self::internal::{ContextInternal, HandleArena, Scope, ScopeMetadata}; #[repr(C)] pub(crate) struct CallbackInfo { @@ -354,7 +354,7 @@ impl<'a> ContextInternal<'a> for ModuleContext<'a> { &self.scope.metadata } - fn handles(&self) -> &'a PersistentArena { + fn handles(&self) -> &'a HandleArena { self.scope.handles } } @@ -379,7 +379,7 @@ impl<'a> ContextInternal<'a> for ExecuteContext<'a> { &self.scope.metadata } - fn handles(&self) -> &'a PersistentArena { + fn handles(&self) -> &'a HandleArena { self.scope.handles } } @@ -410,7 +410,7 @@ impl<'a, 'b> ContextInternal<'a> for ComputeContext<'a, 'b> { &self.scope.metadata } - fn handles(&self) -> &'a PersistentArena { + fn handles(&self) -> &'a HandleArena { self.scope.handles } } @@ -467,7 +467,7 @@ impl<'a, T: This> ContextInternal<'a> for CallContext<'a, T> { &self.scope.metadata } - fn handles(&self) -> &'a PersistentArena { + fn handles(&self) -> &'a HandleArena { self.scope.handles } } @@ -500,7 +500,7 @@ impl<'a> ContextInternal<'a> for TaskContext<'a> { &self.scope.metadata } - fn handles(&self) -> &'a PersistentArena { + fn handles(&self) -> &'a HandleArena { self.scope.handles } } From 9eb8bc5becd549f06572bfe3fb96b34c15cef8f1 Mon Sep 17 00:00:00 2001 From: David Herman Date: Thu, 21 Feb 2019 23:50:59 -1000 Subject: [PATCH 09/11] cleanup: - rename "init" functions back to idiomatic "new" names, removing old versions - rename "thin" functions back to idiomatic names, removing old versions - implement function call/construct - eliminate obsolete neon_runtime::convert module --- crates/neon-runtime/src/array.rs | 10 +- crates/neon-runtime/src/arraybuffer.rs | 12 +- crates/neon-runtime/src/buffer.rs | 20 +- crates/neon-runtime/src/call.rs | 26 +-- crates/neon-runtime/src/class.rs | 5 +- crates/neon-runtime/src/convert.rs | 19 -- crates/neon-runtime/src/error.rs | 26 +-- crates/neon-runtime/src/fun.rs | 26 +-- crates/neon-runtime/src/lib.rs | 1 - crates/neon-runtime/src/mem.rs | 4 - crates/neon-runtime/src/neon.cc | 242 ++++++------------------- crates/neon-runtime/src/neon.h | 79 +++----- crates/neon-runtime/src/object.rs | 44 +---- crates/neon-runtime/src/primitive.rs | 41 +---- crates/neon-runtime/src/tag.rs | 20 +- src/context/mod.rs | 8 +- src/object/mod.rs | 12 +- src/types/binary.rs | 6 +- src/types/error.rs | 6 +- src/types/mod.rs | 24 +-- 20 files changed, 158 insertions(+), 473 deletions(-) delete mode 100644 crates/neon-runtime/src/convert.rs diff --git a/crates/neon-runtime/src/array.rs b/crates/neon-runtime/src/array.rs index cda08da7e..e6d1ae245 100644 --- a/crates/neon-runtime/src/array.rs +++ b/crates/neon-runtime/src/array.rs @@ -1,16 +1,12 @@ //! Facilities for working with `v8::Array`s. -use raw::{Local, Isolate, Persistent}; +use raw::{Isolate, Persistent}; extern "C" { - /// Mutates the `out` argument provided to refer to a newly created `v8::Array`. - #[link_name = "Neon_Array_New"] - pub fn new(out: &mut Local, isolate: *mut Isolate, length: u32); - /// Initializes the `out` argument provided to refer to a newly created `v8::Array`. - #[link_name = "Neon_Array_Init"] - pub fn init(out: &Persistent, isolate: *mut Isolate, length: u32); + #[link_name = "Neon_Array_New"] + pub fn new(out: &Persistent, isolate: *mut Isolate, length: u32); /// Gets the length of an `v8::Array`. #[link_name = "Neon_Array_Length"] diff --git a/crates/neon-runtime/src/arraybuffer.rs b/crates/neon-runtime/src/arraybuffer.rs index e2f20f962..45ab4adff 100644 --- a/crates/neon-runtime/src/arraybuffer.rs +++ b/crates/neon-runtime/src/arraybuffer.rs @@ -1,23 +1,17 @@ //! Facilities for working with `v8::ArrayBuffer`s. -use raw::{Isolate, Local, Persistent}; +use raw::{Isolate, Persistent}; use std::os::raw::c_void; -// FIXME: rename init_xxx functions back to new_xxx - extern "C" { /// Initializes the `out` argument provided to refer to a newly created `v8::ArrayBuffer` object. /// Returns `false` if the value couldn't be created. - #[link_name = "Neon_ArrayBuffer_Init"] - pub fn init(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; - - /// Mutates the `out` argument provided to refer to a newly created `v8::ArrayBuffer` object. - /// Returns `false` if the value couldn't be created. #[link_name = "Neon_ArrayBuffer_New"] - pub fn new(out: &mut Local, isolate: *mut c_void, size: u32) -> bool; + pub fn new(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; /// Mutates the `base_out` and `size_out` arguments to access the data of a `v8::ArrayBuffer` object. #[link_name = "Neon_ArrayBuffer_Data"] pub fn data<'a, 'b>(base_out: &'a mut *mut c_void, size_out: &'a mut usize, obj: &Persistent); + } diff --git a/crates/neon-runtime/src/buffer.rs b/crates/neon-runtime/src/buffer.rs index 152e7afa4..4a20fbb60 100644 --- a/crates/neon-runtime/src/buffer.rs +++ b/crates/neon-runtime/src/buffer.rs @@ -1,29 +1,17 @@ //! Facilities for working with `node::Buffer`s. -use raw::{Isolate, Local, Persistent}; +use raw::{Isolate, Persistent}; use std::os::raw::c_void; -// FIXME: rename init_xxx functions back to new_xxx - extern "C" { - /// Mutates the `out` argument provided to refer to a newly created and zero-filled `node::Buffer` object. - /// Returns `false` if the value couldn't be created. - #[link_name = "Neon_Buffer_New"] - pub fn new(out: &mut Local, size: u32) -> bool; - /// Initializes the `out` argumnent with a newly created `v8::Buffer` using the safe constructor. - #[link_name = "Neon_Buffer_Init_Safe"] - pub fn init_safe(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; + #[link_name = "Neon_Buffer_New"] + pub fn new(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; /// Initializes the `out` argumnent with a newly created `v8::Buffer` using the unsafe constructor. - #[link_name = "Neon_Buffer_Init_Unsafe"] - pub fn init_unsafe(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; - - /// Mutates the `out` argument provided to refer to a newly created `node::Buffer` object. - /// Returns `false` if the value couldn't be created. #[link_name = "Neon_Buffer_Uninitialized"] - pub fn uninitialized(out: &mut Local, size: u32) -> bool; + pub fn uninitialized(out: &Persistent, isolate: *mut Isolate, size: u32) -> bool; /// Mutates the `base_out` and `size_out` arguments to access the data of a `node::Buffer` object. #[link_name = "Neon_Buffer_Data"] diff --git a/crates/neon-runtime/src/call.rs b/crates/neon-runtime/src/call.rs index f7d9c884d..c118b25e7 100644 --- a/crates/neon-runtime/src/call.rs +++ b/crates/neon-runtime/src/call.rs @@ -2,7 +2,7 @@ use std::os::raw::c_void; use std::ptr::null_mut; -use raw::{FunctionCallbackInfo, Isolate, Local, Persistent}; +use raw::{FunctionCallbackInfo, Isolate, Persistent}; #[repr(C)] pub struct CCallback { @@ -23,11 +23,7 @@ extern "C" { /// Sets the return value of the function call. #[link_name = "Neon_Call_SetReturn"] - pub fn set_return(info: &FunctionCallbackInfo, value: Local); - - /// Sets the return value of the function call. - #[link_name = "Neon_Call_SetReturnThin"] - pub fn set_return_thin(info: &FunctionCallbackInfo, value: &Persistent); + pub fn set_return(info: &FunctionCallbackInfo, value: &Persistent); /// Gets the isolate of the function call. #[link_name = "Neon_Call_GetIsolate"] @@ -46,27 +42,17 @@ extern "C" { #[link_name = "Neon_Call_This"] pub fn this(info: &FunctionCallbackInfo, out: &Persistent, isolate: *mut Isolate); - /// Mutates the `out` argument provided to refer to the `v8::Local` handle value of the - /// `v8::FunctionCallbackInfo` `Data`. - #[link_name = "Neon_Call_Data"] - pub fn data(info: &FunctionCallbackInfo, out: &mut Local); - /// Initializes the `out` argument provided to refer to the value of the /// `v8::FunctionCallbackInfo` `Data`. - #[link_name = "Neon_Call_InitData"] - pub fn init_data(info: &FunctionCallbackInfo, out: &Persistent, isolate: *mut Isolate); + #[link_name = "Neon_Call_Data"] + pub fn data(info: &FunctionCallbackInfo, out: &Persistent, isolate: *mut Isolate); /// Gets the number of arguments passed to the function. #[link_name = "Neon_Call_Length"] pub fn len(info: &FunctionCallbackInfo) -> i32; - /// Mutates the `out` argument provided to refer to the `v8::Local` handle value of the `i`th - /// argument passed to the function. - #[link_name = "Neon_Call_Get"] - pub fn get(info: &FunctionCallbackInfo, i: i32, out: &mut Local); - /// Initializes the `out` argument provided to refer to the `i`th argument passed to the function. - #[link_name = "Neon_Call_InitGet"] - pub fn init_get(info: &FunctionCallbackInfo, isolate: *mut Isolate, i: i32, out: &Persistent); + #[link_name = "Neon_Call_Get"] + pub fn get(info: &FunctionCallbackInfo, isolate: *mut Isolate, i: i32, out: &Persistent); } diff --git a/crates/neon-runtime/src/class.rs b/crates/neon-runtime/src/class.rs index 8fad085f3..e2ea28c0f 100644 --- a/crates/neon-runtime/src/class.rs +++ b/crates/neon-runtime/src/class.rs @@ -1,6 +1,6 @@ use std::os::raw::c_void; use call::CCallback; -use raw::{Isolate, Local, Persistent}; +use raw::{Isolate, Persistent}; extern "C" { @@ -46,9 +46,6 @@ extern "C" { #[link_name = "Neon_Class_GetCallKernel"] pub fn get_call_kernel(obj: &Persistent) -> *mut c_void; - #[link_name = "Neon_Class_Constructor"] - pub fn constructor(out: &mut Local, ft: Local) -> bool; - #[link_name = "Neon_Class_HasInstance"] pub fn has_instance(metadata: *mut c_void, v: &Persistent) -> bool; diff --git a/crates/neon-runtime/src/convert.rs b/crates/neon-runtime/src/convert.rs deleted file mode 100644 index d2a64bfb6..000000000 --- a/crates/neon-runtime/src/convert.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Helper functions for converting `v8::Local` values. - -use raw::Local; - -extern "C" { - - /// Casts the value provided to a `v8::Object` and mutates the `out` argument provided to refer - /// to `v8::Local` handle of the converted value. Returns `false` if the conversion didn't - /// succeed. - #[link_name = "Neon_Convert_ToObject"] - pub fn to_object(out: &mut Local, value: &Local) -> bool; - - /// Casts the value provided to a `v8::String` and mutates the `out` argument provided to refer - /// to `v8::Local` handle of the converted value. Returns `false` if the conversion didn't - /// succeed. - #[link_name = "Neon_Convert_ToString"] - pub fn to_string(out: &mut Local, value: Local) -> bool; - -} diff --git a/crates/neon-runtime/src/error.rs b/crates/neon-runtime/src/error.rs index f592a5bc9..b3c9fde8b 100644 --- a/crates/neon-runtime/src/error.rs +++ b/crates/neon-runtime/src/error.rs @@ -1,8 +1,6 @@ //! Facilities for creating and throwing JS errors. -use raw::{Isolate, Local, Persistent}; - -// FIXME: rename init_xxx functions back to new_xxx +use raw::{Isolate, Persistent}; extern "C" { @@ -10,29 +8,17 @@ extern "C" { #[link_name = "Neon_Error_Throw"] pub fn throw(val: &Persistent); - /// Mutates the `out` argument provided to refer to a newly created `Error` object. - #[link_name = "Neon_Error_NewError"] - pub fn new_error(out: &mut Local, msg: &Persistent); - - /// Initializes the `out` argument provided to refer to a newly created `Error` object. - #[link_name = "Neon_Error_InitError"] - pub fn init_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); - /// Initializes the `out` argument provided to refer to a newly created `Error` object. - #[link_name = "Neon_Error_InitTypeError"] - pub fn init_type_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); + #[link_name = "Neon_Error_NewError"] + pub fn new_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); /// Initializes the `out` argument provided to refer to a newly created `Error` object. - #[link_name = "Neon_Error_InitRangeError"] - pub fn init_range_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); - - /// Mutates the `out` argument provided to refer to a newly created `TypeError` object. #[link_name = "Neon_Error_NewTypeError"] - pub fn new_type_error(out: &mut Local, msg: &Persistent); + pub fn new_type_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); - /// Mutates the `out` argument provided to refer to a newly created `RangeError` object. + /// Initializes the `out` argument provided to refer to a newly created `Error` object. #[link_name = "Neon_Error_NewRangeError"] - pub fn new_range_error(out: &mut Local, msg: &Persistent); + pub fn new_range_error(out: &Persistent, isolate: *mut Isolate, msg: &Persistent); /// Throws an `Error` object in the current context. #[link_name = "Neon_Error_ThrowErrorFromUtf8"] diff --git a/crates/neon-runtime/src/fun.rs b/crates/neon-runtime/src/fun.rs index f280d6df6..61fc5d743 100644 --- a/crates/neon-runtime/src/fun.rs +++ b/crates/neon-runtime/src/fun.rs @@ -2,19 +2,14 @@ use std::os::raw::c_void; use call::CCallback; -use raw::{Local, Persistent}; +use raw::Persistent; extern "C" { - /// Mutates the `out` argument provided to refer to a newly created `v8::Function`. Returns - /// `false` if the value couldn't be created. - #[link_name = "Neon_Fun_New"] - pub fn new(out: &mut Local, isolate: *mut c_void, callback: CCallback) -> bool; - /// Initializes the `out` argument provided to refer to a newly created `v8::Function`. Returns /// `false` if the value couldn't be created. - #[link_name = "Neon_Fun_Init"] - pub fn init(out: &Persistent, isolate: *mut c_void, callback: CCallback) -> bool; + #[link_name = "Neon_Fun_New"] + pub fn new(out: &Persistent, isolate: *mut c_void, callback: CCallback) -> bool; /// Mutates the `out` argument provided to refer to a newly created `v8::FunctionTemplate`. /// Returns `false` if the value couldn't be created. @@ -28,23 +23,12 @@ extern "C" { /// Calls the function provided (`fun`) and mutates the `out` argument provided to refer to the /// result of the function call. Returns `false` if the result of the call was empty. #[link_name = "Neon_Fun_Call"] - pub fn call(out: &mut Local, isolate: *mut c_void, fun: Local, this: Local, argc: i32, argv: *mut c_void) -> bool; - - /// Calls the function provided (`fun`) and mutates the `out` argument provided to refer to the - /// result of the function call. Returns `false` if the result of the call was empty. - #[link_name = "Neon_Fun_CallThin"] - pub fn call_thin(out: &Persistent, isolate: *mut c_void, fun: &Persistent, this: &Persistent, argc: i32, argv: *mut c_void) -> bool; + pub fn call(out: &Persistent, isolate: *mut c_void, fun: &Persistent, this: &Persistent, argc: i32, argv: *mut c_void) -> bool; /// Makes a constructor call to with the function provided (`fun`) and mutates the `out` /// argument provided to refer to the result of the constructor call. Returns `false` if the /// result of the call was empty. #[link_name = "Neon_Fun_Construct"] - pub fn construct(out: &mut Local, isolate: *mut c_void, fun: Local, argc: i32, argv: *mut c_void) -> bool; - - /// Makes a constructor call to with the function provided (`fun`) and mutates the `out` - /// argument provided to refer to the result of the constructor call. Returns `false` if the - /// result of the call was empty. - #[link_name = "Neon_Fun_ConstructThin"] - pub fn construct_thin(out: &Persistent, isolate: *mut c_void, fun: &Persistent, argc: i32, argv: *mut c_void) -> bool; + pub fn construct(out: &Persistent, isolate: *mut c_void, fun: &Persistent, argc: i32, argv: *mut c_void) -> bool; } diff --git a/crates/neon-runtime/src/lib.rs b/crates/neon-runtime/src/lib.rs index 89d5b1edb..69da9bff4 100644 --- a/crates/neon-runtime/src/lib.rs +++ b/crates/neon-runtime/src/lib.rs @@ -12,6 +12,5 @@ pub mod tag; pub mod module; pub mod mem; pub mod fun; -pub mod convert; pub mod class; pub mod task; diff --git a/crates/neon-runtime/src/mem.rs b/crates/neon-runtime/src/mem.rs index 63597a876..684e1079f 100644 --- a/crates/neon-runtime/src/mem.rs +++ b/crates/neon-runtime/src/mem.rs @@ -3,10 +3,6 @@ use raw::{Local, Persistent}; extern "C" { - /// Indicates if two `v8::Local` handles are the same. - #[link_name = "Neon_Mem_SameHandle"] - pub fn same_handle(h1: Local, h2: Local) -> bool; - /// Initializes a pointer as a `v8::Persistent`. #[link_name = "Neon_Mem_NewPersistent"] pub fn new_persistent(out: &mut Persistent); diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index abc2b1bf1..a8d7cf5b9 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -9,11 +9,7 @@ #include "neon_class_metadata.h" #include "neon_task.h" -extern "C" void Neon_Call_SetReturn(v8::FunctionCallbackInfo *info, v8::Local value) { - info->GetReturnValue().Set(value); -} - -extern "C" void Neon_Call_SetReturnThin(v8::FunctionCallbackInfo *info, v8::Persistent *value) { +extern "C" void Neon_Call_SetReturn(v8::FunctionCallbackInfo *info, v8::Persistent *value) { info->GetReturnValue().Set(*value); } @@ -34,42 +30,23 @@ extern "C" void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Pe out->Reset(isolate, info->This()); } -extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out) { - /* - printf("Call_Data: v8 info = %p\n", *(void **)info); - dump((void *)info, 3); - printf("Call_Data: v8 info implicit:\n"); - dump_implicit((void *)info); - */ - *out = info->Data(); -} - -extern "C" void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate) { +extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate) { Nan::HandleScope scope; v8::Local data = info->Data(); out->Reset(isolate, data); } - extern "C" int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info) { return info->Length(); } -extern "C" void Neon_Call_Get(v8::FunctionCallbackInfo *info, int32_t i, v8::Local *out) { - *out = (*info)[i]; -} - -extern "C" void Neon_Call_InitGet(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out) { +extern "C" void Neon_Call_Get(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out) { Nan::HandleScope scope; v8::Local local = (*info)[i]; out->Reset(isolate, local); } -extern "C" void Neon_Object_New(v8::Local *out) { - *out = Nan::New(); -} - -extern "C" void Neon_Object_Init(v8::Persistent *out, v8::Isolate *isolate) { +extern "C" void Neon_Object_New(v8::Persistent *out, v8::Isolate *isolate) { Nan::HandleScope scope; v8::Local local = Nan::New(); out->Reset(isolate, local); @@ -84,27 +61,20 @@ extern "C" bool Neon_Object_GetOwnPropertyNames(v8::Persistent *out, return false; } out->Reset(isolate, larr); + return true; } -extern "C" void *Neon_Object_GetIsolate(v8::Local obj) { - return obj->GetIsolate(); -} - -extern "C" void Neon_Primitive_Undefined(v8::Local *out) { - *out = Nan::Undefined(); -} - -extern "C" void Neon_Primitive_InitUndefined(v8::Persistent *out, v8::Isolate *isolate) { +extern "C" void Neon_Primitive_Undefined(v8::Persistent *out, v8::Isolate *isolate) { Nan::HandleScope scope; out->Reset(isolate, Nan::Undefined()); } -extern "C" void Neon_Primitive_InitNull(v8::Persistent *out, v8::Isolate *isolate) { +extern "C" void Neon_Primitive_Null(v8::Persistent *out, v8::Isolate *isolate) { Nan::HandleScope scope; out->Reset(isolate, Nan::Null()); } -extern "C" void Neon_Primitive_InitBoolean(v8::Persistent *out, v8::Isolate *isolate, bool b) { +extern "C" void Neon_Primitive_Boolean(v8::Persistent *out, v8::Isolate *isolate, bool b) { Nan::HandleScope scope; out->Reset(isolate, b ? Nan::True() : Nan::False()); } @@ -121,7 +91,7 @@ extern "C" double Neon_Primitive_NumberValue(v8::Persistent *n) { return local->Value(); } -extern "C" void Neon_Primitive_InitNumber(v8::Persistent *out, v8::Isolate *isolate, double value) { +extern "C" void Neon_Primitive_Number(v8::Persistent *out, v8::Isolate *isolate, double value) { Nan::HandleScope scope; v8::Local n = v8::Number::New(isolate, value); out->Reset(isolate, n); @@ -160,22 +130,7 @@ bool Neon_ASCII_Key(v8::Local *key, const uint8_t *data, int32_t len return maybe_key.ToLocal(key); } -extern "C" bool Neon_Object_Get_String(v8::Local *out, v8::Local obj, const uint8_t *data, int32_t len) { - Nan::EscapableHandleScope scope; - v8::Local key; - if (!Neon_ASCII_Key(&key, data, len)) { - return false; - } - Nan::MaybeLocal maybe = Nan::Get(obj, key); - v8::Local result; - if (!maybe.ToLocal(&result)) { - return false; - } - *out = scope.Escape(result); - return true; -} - -extern "C" bool Neon_Object_Get_StringThin(v8::Persistent *p_out, v8::Isolate *isolate, v8::Persistent *p_obj, const uint8_t *data, int32_t len) { +extern "C" bool Neon_Object_Get_String(v8::Persistent *p_out, v8::Isolate *isolate, v8::Persistent *p_obj, const uint8_t *data, int32_t len) { Nan::HandleScope scope; v8::Local key; if (!Neon_ASCII_Key(&key, data, len)) { @@ -191,17 +146,7 @@ extern "C" bool Neon_Object_Get_StringThin(v8::Persistent *p_out, v8: return true; } -extern "C" bool Neon_Object_Set_String(bool *out, v8::Local obj, const uint8_t *data, int32_t len, v8::Local val) { - Nan::HandleScope scope; - v8::Local key; - if (!Neon_ASCII_Key(&key, data, len)) { - return false; - } - Nan::Maybe maybe = Nan::Set(obj, key, val); - return maybe.IsJust() && (*out = maybe.FromJust(), true); -} - -extern "C" bool Neon_Object_Set_StringThin(bool *out, v8::Isolate *isolate, v8::Persistent *p_obj, const uint8_t *data, int32_t len, v8::Persistent *p_val) { +extern "C" bool Neon_Object_Set_String(bool *out, v8::Isolate *isolate, v8::Persistent *p_obj, const uint8_t *data, int32_t len, v8::Persistent *p_val) { Nan::HandleScope scope; v8::Local key; if (!Neon_ASCII_Key(&key, data, len)) { @@ -213,12 +158,7 @@ extern "C" bool Neon_Object_Set_StringThin(bool *out, v8::Isolate *isolate, v8:: return maybe.IsJust() && (*out = maybe.FromJust(), true); } -extern "C" bool Neon_Object_Get(v8::Local *out, v8::Local obj, v8::Local key) { - Nan::MaybeLocal maybe = Nan::Get(obj, key); - return maybe.ToLocal(out); -} - -extern "C" bool Neon_Object_GetThin(v8::Persistent *p_out, v8::Isolate *isolate, v8::Persistent *p_obj, v8::Persistent *p_key) { +extern "C" bool Neon_Object_Get(v8::Persistent *p_out, v8::Isolate *isolate, v8::Persistent *p_obj, v8::Persistent *p_key) { Nan::HandleScope scope; v8::Local object = Nan::New(*p_obj); v8::Local key = Nan::New(*p_key); @@ -231,16 +171,7 @@ extern "C" bool Neon_Object_GetThin(v8::Persistent *p_out, v8::Isolat return true; } -extern "C" bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local key, v8::Local val) { - Nan::Maybe maybe = Nan::Set(obj, key, val); - if (maybe.IsJust()) { - *out = maybe.FromJust(); - return true; - } - return false; -} - -extern "C" bool Neon_Object_SetThin(bool *out, v8::Isolate *isolate, v8::Persistent *p_obj, v8::Persistent *p_key, v8::Persistent *p_val) { +extern "C" bool Neon_Object_Set(bool *out, v8::Isolate *isolate, v8::Persistent *p_obj, v8::Persistent *p_key, v8::Persistent *p_val) { Nan::HandleScope scope; v8::Local object = Nan::New(*p_obj); v8::Local key = Nan::New(*p_key); @@ -253,16 +184,12 @@ extern "C" bool Neon_Object_SetThin(bool *out, v8::Isolate *isolate, v8::Persist return false; } -extern "C" void Neon_Array_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t length) { +extern "C" void Neon_Array_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t length) { Nan::HandleScope scope; v8::Local local = v8::Array::New(isolate, length); out->Reset(isolate, local); } -extern "C" void Neon_Array_New(v8::Local *out, v8::Isolate *isolate, uint32_t length) { - *out = v8::Array::New(isolate, length); -} - extern "C" uint32_t Neon_Array_Length(v8::Persistent *array) { Nan::HandleScope scope; v8::Local local = Nan::New(*array); @@ -302,7 +229,7 @@ extern "C" bool Neon_Convert_ToObject(v8::Local *out, v8::Local *out, v8::Isolate *isolate, uint32_t len) { +extern "C" bool Neon_Buffer_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { Nan::HandleScope scope; Nan::MaybeLocal maybe = Nan::NewBuffer(len); v8::Local buffer; @@ -315,7 +242,7 @@ extern "C" bool Neon_Buffer_Init_Safe(v8::Persistent *out, v8::Isolat return true; } -extern "C" bool Neon_Buffer_Init_Unsafe(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { +extern "C" bool Neon_Buffer_Uninitialized(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { Nan::HandleScope scope; Nan::MaybeLocal maybe = Nan::NewBuffer(len); v8::Local buffer; @@ -326,22 +253,6 @@ extern "C" bool Neon_Buffer_Init_Unsafe(v8::Persistent *out, v8::Isol return true; } -extern "C" bool Neon_Buffer_New(v8::Local *out, uint32_t size) { - Nan::MaybeLocal maybe = Nan::NewBuffer(size); - if (!maybe.ToLocal(out)) { - return false; - } - - void *data = node::Buffer::Data(*out); - memset(data, 0, size); - return true; -} - -extern "C" bool Neon_Buffer_Uninitialized(v8::Local *out, uint32_t size) { - Nan::MaybeLocal maybe = Nan::NewBuffer(size); - return maybe.ToLocal(out); -} - extern "C" void Neon_Buffer_Data(void **base_out, size_t *len_out, v8::Persistent *obj) { Nan::HandleScope scope; v8::Local local = Nan::New(*obj); @@ -355,18 +266,13 @@ extern "C" bool Neon_Tag_IsBuffer(v8::Persistent *val) { return node::Buffer::HasInstance(local); } -extern "C" bool Neon_ArrayBuffer_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { +extern "C" bool Neon_ArrayBuffer_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { Nan::HandleScope scope; v8::Local local = v8::ArrayBuffer::New(isolate, len); out->Reset(isolate, local); return true; } -extern "C" bool Neon_ArrayBuffer_New(v8::Local *out, v8::Isolate *isolate, uint32_t size) { - *out = v8::ArrayBuffer::New(isolate, size); - return true; -} - extern "C" void Neon_ArrayBuffer_Data(void **base_out, size_t *len_out, v8::Persistent *buffer) { Nan::HandleScope scope; v8::Local local = Nan::New(*buffer); @@ -471,11 +377,6 @@ extern "C" void *Neon_Class_GetAllocateKernel(v8::Persistent *wrap return metadata->GetAllocateKernel(); } -extern "C" bool Neon_Class_Constructor(v8::Local *out, v8::Local ft) { - v8::MaybeLocal maybe = ft->GetFunction(); - return maybe.ToLocal(out); -} - extern "C" bool Neon_Class_HasInstance(void *metadata_pointer, v8::Persistent *v) { Nan::HandleScope scope; v8::Local local = Nan::New(*v); @@ -564,18 +465,7 @@ extern "C" bool Neon_Fun_Template_New(v8::Persistent *out, return true; } -extern "C" bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback) { - v8::Local wrapper = v8::External::New(isolate, callback.dynamic_callback); - if (wrapper.IsEmpty()) { - return false; - } - - v8::FunctionCallback static_callback = reinterpret_cast(callback.static_callback); - v8::MaybeLocal maybe_result = v8::Function::New(isolate->GetCurrentContext(), static_callback, wrapper); - return maybe_result.ToLocal(out); -} - -extern "C" bool Neon_Fun_Init(v8::Persistent *out, v8::Isolate *isolate, callback_t callback) { +extern "C" bool Neon_Fun_New(v8::Persistent *out, v8::Isolate *isolate, callback_t callback) { Nan::HandleScope scope; v8::Local wrapper = v8::External::New(isolate, callback.dynamic_callback); if (wrapper.IsEmpty()) { @@ -598,39 +488,44 @@ extern "C" void *Neon_Fun_GetDynamicCallback(v8::Persistent *data) return local->Value(); } -extern "C" bool Neon_Fun_Call(v8::Local *out, v8::Isolate *isolate, v8::Local fun, v8::Local self, int32_t argc, v8::Local argv[]) { - v8::MaybeLocal maybe_result = fun->Call(isolate->GetCurrentContext(), self, argc, argv); - return maybe_result.ToLocal(out); -} - -extern "C" bool Neon_Fun_CallThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]) { -/* - v8::MaybeLocal maybe_result = fun->Call(isolate->GetCurrentContext(), self, argc, argv); - return maybe_result.ToLocal(out); -*/ - // FIXME: implement me - return false; -} +extern "C" bool Neon_Fun_Call(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]) { + Nan::HandleScope scope; + v8::Local lfun = Nan::New(*fun); + v8::Local lself = Nan::New(*self); + v8::Local *largv = new v8::Local[argc]; + for (int32_t i = 0; i < argc; i++) { + largv[i] = Nan::New(*argv[i]); + } + v8::MaybeLocal maybe_result = lfun->Call(isolate->GetCurrentContext(), lself, argc, largv); + delete[] largv; + v8::Local lout; + if (!maybe_result.ToLocal(&lout)) { + return false; + } -extern "C" bool Neon_Fun_Construct(v8::Local *out, v8::Isolate *isolate, v8::Local fun, int32_t argc, v8::Local argv[]) { - v8::MaybeLocal maybe_result = fun->NewInstance(isolate->GetCurrentContext(), argc, argv); - return maybe_result.ToLocal(out); + out->Reset(isolate, lout); + return true; } -extern "C" bool Neon_Fun_ConstructThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, int32_t argc, v8::Persistent *argv[]) { - /* - v8::MaybeLocal maybe_result = fun->NewInstance(isolate->GetCurrentContext(), argc, argv); - return maybe_result.ToLocal(out); - */ - // FIXME: implement me - return false; -} +extern "C" bool Neon_Fun_Construct(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, int32_t argc, v8::Persistent *argv[]) { + Nan::HandleScope scope; + v8::Local lfun = Nan::New(*fun); + v8::Local *largv = new v8::Local[argc]; + for (int32_t i = 0; i < argc; i++) { + largv[i] = Nan::New(*argv[i]); + } + v8::MaybeLocal maybe_result = lfun->NewInstance(isolate->GetCurrentContext(), argc, largv); + delete[] largv; + v8::Local lout; + if (!maybe_result.ToLocal(&lout)) { + return false; + } -extern "C" bool Neon_Tag_IsUndefined(v8::Local val) { - return val->IsUndefined(); + out->Reset(isolate, lout); + return true; } -extern "C" bool Neon_Tag_IsUndefinedThin(v8::Persistent *val) { +extern "C" bool Neon_Tag_IsUndefined(v8::Persistent *val) { Nan::HandleScope scope; v8::Local local = Nan::New(*val); return local->IsUndefined(); @@ -660,11 +555,7 @@ extern "C" bool Neon_Tag_IsString(v8::Persistent *val) { return local->IsString(); } -extern "C" bool Neon_Tag_IsObject(v8::Local val) { - return val->IsObject(); -} - -extern "C" bool Neon_Tag_IsObjectThin(v8::Persistent *val) { +extern "C" bool Neon_Tag_IsObject(v8::Persistent *val) { Nan::HandleScope scope; v8::Local local = Nan::New(*val); return local->IsObject(); @@ -676,11 +567,7 @@ extern "C" bool Neon_Tag_IsArray(v8::Persistent *val) { return local->IsArray(); } -extern "C" bool Neon_Tag_IsFunction(v8::Local val) { - return val->IsFunction(); -} - -extern "C" bool Neon_Tag_IsFunctionThin(v8::Persistent *val) { +extern "C" bool Neon_Tag_IsFunction(v8::Persistent *val) { Nan::HandleScope scope; v8::Local local = Nan::New(*val); return local->IsFunction(); @@ -698,42 +585,27 @@ extern "C" void Neon_Error_Throw(v8::Persistent *val) { Nan::ThrowError(local); } -extern "C" void Neon_Error_InitError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { +extern "C" void Neon_Error_NewError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { Nan::HandleScope scope; v8::Local lmsg = Nan::New(*msg); v8::Local lerr = v8::Exception::Error(lmsg); out->Reset(isolate, lerr); } -extern "C" void Neon_Error_InitTypeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { +extern "C" void Neon_Error_NewTypeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { Nan::HandleScope scope; v8::Local lmsg = Nan::New(*msg); v8::Local lerr = v8::Exception::TypeError(lmsg); out->Reset(isolate, lerr); } -extern "C" void Neon_Error_InitRangeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { +extern "C" void Neon_Error_NewRangeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg) { Nan::HandleScope scope; v8::Local lmsg = Nan::New(*msg); v8::Local lerr = v8::Exception::RangeError(lmsg); out->Reset(isolate, lerr); } -extern "C" void Neon_Error_NewError(v8::Local *out, v8::Persistent *msg) { - v8::Local local = Nan::New(*msg); - *out = v8::Exception::Error(local); -} - -extern "C" void Neon_Error_NewTypeError(v8::Local *out, v8::Persistent *msg) { - v8::Local local = Nan::New(*msg); - *out = v8::Exception::TypeError(local); -} - -extern "C" void Neon_Error_NewRangeError(v8::Local *out, v8::Persistent *msg) { - v8::Local local = Nan::New(*msg); - *out = v8::Exception::RangeError(local); -} - extern "C" void Neon_Error_ThrowErrorFromUtf8(const uint8_t *data, int32_t len) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); Nan::MaybeLocal maybe = v8::String::NewFromUtf8(isolate, (const char*)data, v8::NewStringType::kNormal, len); @@ -748,10 +620,6 @@ extern "C" void Neon_Error_ThrowErrorFromUtf8(const uint8_t *data, int32_t len) Nan::ThrowError(err); } -extern "C" bool Neon_Mem_SameHandle(v8::Local v1, v8::Local v2) { - return v1 == v2; -} - extern "C" void Neon_Mem_NewPersistent(v8::Persistent *out) { ::new (out) v8::Persistent(); } diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index bbc68e545..096b5f388 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -13,43 +13,32 @@ typedef struct { extern "C" { - void Neon_Call_SetReturn(v8::FunctionCallbackInfo *info, v8::Local value); - void Neon_Call_SetReturnThin(v8::FunctionCallbackInfo *info, v8::Persistent *value); + void Neon_Call_SetReturn(v8::FunctionCallbackInfo *info, v8::Persistent *value); void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo *info); void *Neon_Call_CurrentIsolate(); bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo *info); void Neon_Call_This(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate); - void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Local *out); - void Neon_Call_InitData(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate); + void Neon_Call_Data(v8::FunctionCallbackInfo *info, v8::Persistent *out, v8::Isolate *isolate); int32_t Neon_Call_Length(v8::FunctionCallbackInfo *info); - void Neon_Call_Get(v8::FunctionCallbackInfo *info, int32_t i, v8::Local *out); - void Neon_Call_InitGet(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out); - - void Neon_Primitive_InitNumber(v8::Persistent *out, v8::Isolate *isolate, double value); - void Neon_Primitive_Undefined(v8::Local *out); - void Neon_Primitive_InitUndefinedThin(v8::Persistent *out, v8::Isolate *isolate); - void Neon_Primitive_Init_Null(v8::Persistent *out, v8::Isolate *isolate); - void Neon_Primitive_InitBoolean(v8::Persistent *out, v8::Isolate *isolate, bool b); + void Neon_Call_Get(v8::FunctionCallbackInfo *info, v8::Isolate *isolate, int32_t i, v8::Persistent *out); + + void Neon_Primitive_Number(v8::Persistent *out, v8::Isolate *isolate, double value); + void Neon_Primitive_Undefined(v8::Persistent *out, v8::Isolate *isolate); + void Neon_Primitive_Null(v8::Persistent *out, v8::Isolate *isolate); + void Neon_Primitive_Boolean(v8::Persistent *out, v8::Isolate *isolate, bool b); bool Neon_Primitive_IsUint32(v8::Local p); bool Neon_Primitive_IsInt32(v8::Local p); - void Neon_Object_New(v8::Local *out); - void Neon_Object_Init(v8::Persistent *out, v8::Isolate *isolate); + void Neon_Object_New(v8::Persistent *out, v8::Isolate *isolate); bool Neon_Object_GetOwnPropertyNames(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *obj); - void *Neon_Object_GetIsolate(v8::Local obj); bool Neon_Object_Get_Index(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index); bool Neon_Object_Set_Index(bool *out, v8::Isolate *isolate, v8::Persistent *object, uint32_t index, v8::Persistent *val); - bool Neon_Object_Get_String(v8::Local *out, v8::Local object, const uint8_t *key, int32_t len); - bool Neon_Object_Get_StringThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, const uint8_t *key, int32_t len); - bool Neon_Object_Set_String(bool *out, v8::Local object, const uint8_t *key, int32_t len, v8::Local val); - bool Neon_Object_Set_StringThin(bool *out, v8::Isolate *isolate, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); - bool Neon_Object_Get(v8::Local *out, v8::Local object, v8::Local key); - bool Neon_Object_GetThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, v8::Persistent *key); - bool Neon_Object_Set(bool *out, v8::Local obj, v8::Local key, v8::Local val); - bool Neon_Object_SetThin(bool *out, v8::Isolate *isolate, v8::Persistent *obj, v8::Persistent *key, v8::Persistent *val); - - void Neon_Array_New(v8::Local *out, v8::Isolate *isolate, uint32_t length); - void Neon_Array_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t length); + bool Neon_Object_Get_String(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, const uint8_t *key, int32_t len); + bool Neon_Object_Set_String(bool *out, v8::Isolate *isolate, v8::Persistent *object, const uint8_t *key, int32_t len, v8::Persistent *val); + bool Neon_Object_Get(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *object, v8::Persistent *key); + bool Neon_Object_Set(bool *out, v8::Isolate *isolate, v8::Persistent *obj, v8::Persistent *key, v8::Persistent *val); + + void Neon_Array_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t length); uint32_t Neon_Array_Length(v8::Persistent *array); bool Neon_String_New(v8::Persistent *out, v8::Isolate *isolate, const uint8_t *data, int32_t len); @@ -59,14 +48,11 @@ extern "C" { bool Neon_Convert_ToString(v8::Local *out, v8::Local value); bool Neon_Convert_ToObject(v8::Local *out, v8::Local *value); - bool Neon_Buffer_New(v8::Local *out, uint32_t size); + bool Neon_Buffer_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); + bool Neon_Buffer_Uninitialized(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); void Neon_Buffer_Data(void **base_out, size_t *len_out, v8::Persistent *obj); - bool Neon_Buffer_Init_Safe(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); - bool Neon_Buffer_Init_Unsafe(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); - bool Neon_ArrayBuffer_New(v8::Local *out, v8::Isolate *isolate, uint32_t size); - bool Neon_ArrayBuffer_Init(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); - bool Neon_ArrayBuffer_Uninitialized(v8::Local *out, v8::Isolate *isolate, uint32_t size); + bool Neon_ArrayBuffer_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); void Neon_ArrayBuffer_Data(void **base_out, size_t *len_out, v8::Persistent *buffer); typedef void(*Neon_ChainedScopeCallback)(void *, void *, void *, void *); @@ -77,14 +63,11 @@ extern "C" { void Neon_Scope_Nested(void *out, void *closure, Neon_NestedScopeCallback callback, void *realm); void Neon_Scope_GetGlobal(v8::Isolate *isolate, v8::Persistent *out); - bool Neon_Fun_New(v8::Local *out, v8::Isolate *isolate, callback_t callback); - bool Neon_Fun_Init(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); + bool Neon_Fun_New(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); bool Neon_Fun_Template_New(v8::Persistent *out, v8::Isolate *isolate, callback_t callback); void *Neon_Fun_GetDynamicCallback(v8::Persistent *obj); - bool Neon_Fun_Call(v8::Local *out, v8::Isolate *isolate, v8::Local fun, v8::Local self, int32_t argc, v8::Local argv[]); - bool Neon_Fun_CallThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]); - bool Neon_Fun_Construct(v8::Local *out, v8::Isolate *isolate, v8::Local fun, int32_t argc, v8::Local argv[]); - bool Neon_Fun_ConstructThin(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, int32_t argc, v8::Persistent *argv[]); + bool Neon_Fun_Call(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, v8::Persistent *self, int32_t argc, v8::Persistent *argv[]); + bool Neon_Fun_Construct(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *fun, int32_t argc, v8::Persistent *argv[]); typedef void *(*Neon_AllocateCallback)(const v8::FunctionCallbackInfo *info); typedef bool (*Neon_ConstructCallback)(const v8::FunctionCallbackInfo *info); @@ -105,7 +88,6 @@ extern "C" { void *Neon_Class_GetCallKernel(v8::Persistent *wrapper); void *Neon_Class_GetConstructKernel(v8::Persistent *wrapper); void *Neon_Class_GetAllocateKernel(v8::Persistent *wrapper); - bool Neon_Class_Constructor(v8::Local *out, v8::Local ft); bool Neon_Class_HasInstance(void *metadata, v8::Persistent *v); bool Neon_Class_SetName(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length); void Neon_Class_GetName(const char **chars_out, size_t *len_out, v8::Isolate *isolate, void *metadata); @@ -116,31 +98,24 @@ extern "C" { uint32_t Neon_Module_GetVersion(); - bool Neon_Tag_IsUndefined(v8::Local val); - bool Neon_Tag_IsUndefinedThin(v8::Persistent *val); + bool Neon_Tag_IsUndefined(v8::Persistent *val); bool Neon_Tag_IsNull(v8::Persistent *val); bool Neon_Tag_IsBoolean(v8::Persistent *val); bool Neon_Tag_IsNumber(v8::Persistent *val); bool Neon_Tag_IsString(v8::Persistent *val); - bool Neon_Tag_IsObject(v8::Local val); - bool Neon_Tag_IsObjectThin(v8::Persistent *val); + bool Neon_Tag_IsObject(v8::Persistent *val); bool Neon_Tag_IsArray(v8::Persistent *val); - bool Neon_Tag_IsFunction(v8::Local val); - bool Neon_Tag_IsFunctionThin(v8::Persistent *val); + bool Neon_Tag_IsFunction(v8::Persistent *val); bool Neon_Tag_IsBuffer(v8::Persistent *val); bool Neon_Tag_IsArrayBuffer(v8::Persistent *val); bool Neon_Tag_IsError(v8::Persistent *val); - void Neon_Error_InitError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); - void Neon_Error_InitTypeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); - void Neon_Error_InitRangeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); - void Neon_Error_NewError(v8::Local *out, v8::Persistent *msg); - void Neon_Error_NewTypeError(v8::Local *out, v8::Persistent *msg); - void Neon_Error_NewRangeError(v8::Local *out, v8::Persistent *msg); + void Neon_Error_NewError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); + void Neon_Error_NewTypeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); + void Neon_Error_NewRangeError(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *msg); void Neon_Error_Throw(v8::Persistent *val); void Neon_Error_ThrowErrorFromUtf8(const uint8_t *data, int32_t len); - bool Neon_Mem_SameHandle(v8::Local v1, v8::Local v2); void Neon_Mem_NewPersistent(v8::Persistent *out); void Neon_Mem_DropPersistent(v8::Persistent *p); void Neon_Mem_ResetPersistent(v8::Persistent *p, v8::Local h); diff --git a/crates/neon-runtime/src/object.rs b/crates/neon-runtime/src/object.rs index 58dd5760c..77644343d 100644 --- a/crates/neon-runtime/src/object.rs +++ b/crates/neon-runtime/src/object.rs @@ -1,26 +1,18 @@ //! Facilities for working with `v8::Object`s. -use raw::{Isolate, Local, Persistent}; +use raw::{Isolate, Persistent}; extern "C" { - /// Mutates the `out` argument provided to refer to a newly created `v8::Object`. - #[link_name = "Neon_Object_New"] - pub fn new(out: &mut Local); - /// Initializes the `out` argumnent with a newly created `v8::Object`. - #[link_name = "Neon_Object_Init"] - pub fn init(out: &Persistent, isolate: *mut Isolate); + #[link_name = "Neon_Object_New"] + pub fn new(out: &Persistent, isolate: *mut Isolate); /// Mutates the `out` argument provided to refer to a newly created `v8::Array` containing the /// names of the `v8::Object`'s own property names. Returns `false` if the result is empty. #[link_name = "Neon_Object_GetOwnPropertyNames"] pub fn get_own_property_names(out: &Persistent, isolate: *mut Isolate, object: &Persistent) -> bool; - /// Gets the `v8::Isolate` of a `v8::Object`. - #[link_name = "Neon_Object_GetIsolate"] - pub fn get_isolate(obj: Local) -> *mut Isolate; - /// Mutates the `out` argument provided to refer to the `v8::Local` value at the `index` /// provided of the `v8::Object`. Returns `false` if the result couldn't be retrieved. #[link_name = "Neon_Object_Get_Index"] @@ -35,41 +27,21 @@ extern "C" { /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `v8::String`'s /// underlying content. Returns `false` if the value couldn't be retrieved. #[link_name = "Neon_Object_Get_String"] - pub fn get_string(out: &mut Local, object: Local, key: *const u8, len: i32) -> bool; - - /// Mutates the `out` argument provided to refer to the `v8::Local` value of the `v8::String`'s - /// underlying content. Returns `false` if the value couldn't be retrieved. - #[link_name = "Neon_Object_Get_StringThin"] - pub fn get_string_thin(out: &Persistent, isolate: *mut Isolate, object: &Persistent, key: *const u8, len: i32) -> bool; + pub fn get_string(out: &Persistent, isolate: *mut Isolate, object: &Persistent, key: *const u8, len: i32) -> bool; /// Sets the underlying content of a `v8::String` object. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. #[link_name = "Neon_Object_Set_String"] - pub fn set_string(out: &mut bool, object: Local, key: *const u8, len: i32, val: Local) -> bool; - - /// Sets the underlying content of a `v8::String` object. Also mutates the `out` argument - /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. - #[link_name = "Neon_Object_Set_StringThin"] - pub fn set_string_thin(out: &mut bool, isolate: *mut Isolate, object: &Persistent, key: *const u8, len: i32, val: &Persistent) -> bool; - - /// Mutates the `out` argument provided to refer to the `v8::Local` value at the `key` - /// provided. Returns `false` if the result couldn't be retrieved. - #[link_name = "Neon_Object_Get"] - pub fn get(out: &mut Local, object: Local, key: Local) -> bool; + pub fn set_string(out: &mut bool, isolate: *mut Isolate, object: &Persistent, key: *const u8, len: i32, val: &Persistent) -> bool; /// Mutates the `out` argument provided to refer to the property value at the `key` /// provided. Returns `false` if the result couldn't be retrieved. - #[link_name = "Neon_Object_GetThin"] - pub fn get_thin(out: &Persistent, isolate: *mut Isolate, object: &Persistent, key: &Persistent) -> bool; + #[link_name = "Neon_Object_Get"] + pub fn get(out: &Persistent, isolate: *mut Isolate, object: &Persistent, key: &Persistent) -> bool; /// Sets the key value of a `v8::Object` at the `key` provided. Also mutates the `out` argument /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. #[link_name = "Neon_Object_Set"] - pub fn set(out: &mut bool, object: Local, key: Local, val: Local) -> bool; - - /// Sets the key value of a `v8::Object` at the `key` provided. Also mutates the `out` argument - /// provided to refer to a `v8::Local` boolean value, `true` if the set was successful. - #[link_name = "Neon_Object_SetThin"] - pub fn set_thin(out: &mut bool, isolate: *mut Isolate, object: &Persistent, key: &Persistent, val: &Persistent) -> bool; + pub fn set(out: &mut bool, isolate: *mut Isolate, object: &Persistent, key: &Persistent, val: &Persistent) -> bool; } diff --git a/crates/neon-runtime/src/primitive.rs b/crates/neon-runtime/src/primitive.rs index 8ef8fe73c..e8bcd2e53 100644 --- a/crates/neon-runtime/src/primitive.rs +++ b/crates/neon-runtime/src/primitive.rs @@ -1,52 +1,31 @@ //! Facilities for working with primitive values. -use raw::{Local, Isolate, Persistent}; +use raw::{Isolate, Persistent}; extern "C" { - /// Mutates the `out` argument provided to refer to the `v8::Undefined` object. - #[link_name = "Neon_Primitive_Undefined"] - pub fn undefined(out: &mut Local); - /// Initializes the `out` argument with a newly created `v8::Undefined` object. - #[link_name = "Neon_Primitive_InitUndefined"] - pub fn init_undefined(out: &Persistent, isolate: *mut Isolate); + #[link_name = "Neon_Primitive_Undefined"] + pub fn undefined(out: &Persistent, isolate: *mut Isolate); /// Mutates the `out` argument provided to refer to the `v8::Null` object. - #[link_name = "Neon_Primitive_InitNull"] - pub fn init_null(out: &Persistent, isolate: *mut Isolate); + #[link_name = "Neon_Primitive_Null"] + pub fn null(out: &Persistent, isolate: *mut Isolate); /// Initializes the `out` argument with a newly created `v8::Boolean` object. - #[link_name = "Neon_Primitive_InitBoolean"] - pub fn init_boolean(out: &Persistent, isolate: *mut Isolate, b: bool); + #[link_name = "Neon_Primitive_Boolean"] + pub fn boolean(out: &Persistent, isolate: *mut Isolate, b: bool); /// Gets the underlying value of a `v8::Boolean` object. #[link_name = "Neon_Primitive_BooleanValue"] pub fn boolean_value(p: &Persistent) -> bool; - // DEPRECATE(0.2) - /// Mutates the `out` argument provided to refer to a newly created `v8::Integer` object. - #[link_name = "Neon_Primitive_Integer"] - pub fn integer(out: &mut Local, isolate: *mut Isolate, x: i32); - - /// Indicates if the value is a 32-bit unsigned integer. - #[link_name = "Neon_Primitive_IsUint32"] - pub fn is_u32(p: Local) -> bool; - - /// Indicates if the value is a 32-bit signed integer. - #[link_name = "Neon_Primitive_IsInt32"] - pub fn is_i32(p: Local) -> bool; - - // DEPRECATE(0.2) - /// Gets the underlying value of a `v8::Integer` object. - #[link_name = "Neon_Primitive_IntegerValue"] - pub fn integer_value(p: Local) -> i64; - /// Initializes the `out` argument with a newly created `v8::Number` object. - #[link_name = "Neon_Primitive_InitNumber"] - pub fn init_number(out: &Persistent, isolate: *mut Isolate, v: f64); + #[link_name = "Neon_Primitive_Number"] + pub fn number(out: &Persistent, isolate: *mut Isolate, v: f64); /// Gets the underlying value of a `v8::Number` object. #[link_name = "Neon_Primitive_NumberValue"] pub fn number_value(p: &Persistent) -> f64; + } diff --git a/crates/neon-runtime/src/tag.rs b/crates/neon-runtime/src/tag.rs index aac819a1b..1442b69b1 100644 --- a/crates/neon-runtime/src/tag.rs +++ b/crates/neon-runtime/src/tag.rs @@ -1,16 +1,12 @@ //! Facilities for identifying the type of a `v8::Local` handle. -use raw::{Local, Persistent}; +use raw::Persistent; extern "C" { /// Indicates if the value type is `Undefined`. #[link_name = "Neon_Tag_IsUndefined"] - pub fn is_undefined(val: Local) -> bool; - - /// Indicates if the value type is `Undefined`. - #[link_name = "Neon_Tag_IsUndefinedThin"] - pub fn is_undefined_thin(val: &Persistent) -> bool; + pub fn is_undefined(val: &Persistent) -> bool; /// Indicates if the value type is `Null`. #[link_name = "Neon_Tag_IsNull"] @@ -30,11 +26,7 @@ extern "C" { /// Indicates if the value type is `Object`. #[link_name = "Neon_Tag_IsObject"] - pub fn is_object(val: Local) -> bool; - - /// Indicates if the value type is `Object`. - #[link_name = "Neon_Tag_IsObjectThin"] - pub fn is_object_thin(val: &Persistent) -> bool; + pub fn is_object(val: &Persistent) -> bool; /// Indicates if the value type is `Array`. #[link_name = "Neon_Tag_IsArray"] @@ -42,11 +34,7 @@ extern "C" { /// Indicates if the value type is `Function`. #[link_name = "Neon_Tag_IsFunction"] - pub fn is_function(val: Local) -> bool; - - /// Indicates if the value type is `Function`. - #[link_name = "Neon_Tag_IsFunctionThin"] - pub fn is_function_thin(val: &Persistent) -> bool; + pub fn is_function(val: &Persistent) -> bool; /// Indicates if the value type is `Error`. #[link_name = "Neon_Tag_IsError"] diff --git a/src/context/mod.rs b/src/context/mod.rs index 81796240b..17a8d7844 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -28,7 +28,7 @@ impl CallbackInfo { pub fn data<'a, C: Context<'a>>(&self, cx: &mut C) -> &'a JsValue { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::call::init_data(&self.info, out, isolate) + neon_runtime::call::data(&self.info, out, isolate) }) } @@ -38,7 +38,7 @@ impl CallbackInfo { pub fn set_return<'a, 'b, T: Value>(&'a self, value: &'b T) { unsafe { - neon_runtime::call::set_return_thin(&self.info, value.to_raw()); + neon_runtime::call::set_return(&self.info, value.to_raw()); } } @@ -62,7 +62,7 @@ impl CallbackInfo { } unsafe { Some(cx.new_infallible(|out, isolate| { - neon_runtime::call::init_get(&self.info, isolate, i, out) + neon_runtime::call::get(&self.info, isolate, i, out) })) } } @@ -72,7 +72,7 @@ impl CallbackInfo { return cx.throw_type_error("not enough arguments"); } Ok(cx.new_infallible(|out, isolate| unsafe { - neon_runtime::call::init_get(&self.info, isolate, i, out) + neon_runtime::call::get(&self.info, isolate, i, out) })) } diff --git a/src/object/mod.rs b/src/object/mod.rs index 88c91feef..802a2eaca 100644 --- a/src/object/mod.rs +++ b/src/object/mod.rs @@ -30,26 +30,22 @@ impl PropertyKey for u32 { impl<'a> PropertyKey for &'a str { unsafe fn get_from(self, out: &raw::Persistent, isolate: *mut raw::Isolate, obj: &raw::Persistent) -> bool { let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); - // FIXME: rename the `_thin` back to normal - neon_runtime::object::get_string_thin(out, isolate, obj, ptr, len) + neon_runtime::object::get_string(out, isolate, obj, ptr, len) } unsafe fn set_from(self, out: &mut bool, isolate: *mut raw::Isolate, obj: &raw::Persistent, val: &raw::Persistent) -> bool { let (ptr, len) = Utf8::from(self).into_small_unwrap().lower(); - // FIXME: rename the `_thin` back to normal - neon_runtime::object::set_string_thin(out, isolate, obj, ptr, len, val) + neon_runtime::object::set_string(out, isolate, obj, ptr, len, val) } } impl<'a, T: Value> PropertyKey for &'a T { unsafe fn get_from(self, out: &raw::Persistent, isolate: *mut raw::Isolate, obj: &raw::Persistent) -> bool { - // FIXME: rename the `_thin` back to normal - neon_runtime::object::get_thin(out, isolate, obj, self.to_raw()) + neon_runtime::object::get(out, isolate, obj, self.to_raw()) } unsafe fn set_from(self, out: &mut bool, isolate: *mut raw::Isolate, obj: &raw::Persistent, val: &raw::Persistent) -> bool { - // FIXME: rename the `_thin` back to normal - neon_runtime::object::set_thin(out, isolate, obj, self.to_raw(), val) + neon_runtime::object::set(out, isolate, obj, self.to_raw(), val) } } diff --git a/src/types/binary.rs b/src/types/binary.rs index 5a2d60b43..01f445c28 100644 --- a/src/types/binary.rs +++ b/src/types/binary.rs @@ -22,14 +22,14 @@ impl JsBuffer { /// Constructs a new `Buffer` object, safely zero-filled. pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { cx.new(|out, isolate| unsafe { - neon_runtime::buffer::init_safe(out, isolate, size) + neon_runtime::buffer::new(out, isolate, size) }) } /// Constructs a new `Buffer` object, unsafely filled with uninitialized data. pub unsafe fn uninitialized<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsBuffer> { cx.new(|out, isolate| { - neon_runtime::buffer::init_unsafe(out, isolate, size) + neon_runtime::buffer::uninitialized(out, isolate, size) }) } @@ -58,7 +58,7 @@ impl JsArrayBuffer { /// Constructs a new `ArrayBuffer` object with the given size, in bytes. pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> NeonResult<&'a JsArrayBuffer> { cx.new(|out, isolate| unsafe { - neon_runtime::arraybuffer::init(out, isolate, size) + neon_runtime::arraybuffer::new(out, isolate, size) }) } diff --git a/src/types/error.rs b/src/types/error.rs index fd1828258..bbcd60a88 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -34,7 +34,7 @@ impl JsError { pub fn error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; cx.new(|out, isolate| unsafe { - neon_runtime::error::init_error(out, isolate, msg); + neon_runtime::error::new_error(out, isolate, msg); true }) } @@ -43,7 +43,7 @@ impl JsError { pub fn type_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; cx.new(|out, isolate| unsafe { - neon_runtime::error::init_type_error(out, isolate, msg); + neon_runtime::error::new_type_error(out, isolate, msg); true }) } @@ -52,7 +52,7 @@ impl JsError { pub fn range_error<'a, C: Context<'a>, S: AsRef>(cx: &mut C, msg: S) -> NeonResult<&'a JsError> { let msg = { cx.string(msg.as_ref()).to_raw() }; cx.new(|out, isolate| unsafe { - neon_runtime::error::init_range_error(out, isolate, msg); + neon_runtime::error::new_range_error(out, isolate, msg); true }) } diff --git a/src/types/mod.rs b/src/types/mod.rs index 15b673f38..f42718eba 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -169,7 +169,7 @@ pub struct JsUndefined(raw::Persistent); impl JsUndefined { pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsUndefined { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::primitive::init_undefined(out, isolate) + neon_runtime::primitive::undefined(out, isolate) }) } } @@ -180,7 +180,7 @@ impl ValueInternal for JsUndefined { fn name() -> String { "undefined".to_string() } fn is_typeof(other: &Other) -> bool { - unsafe { neon_runtime::tag::is_undefined_thin(other.to_raw()) } + unsafe { neon_runtime::tag::is_undefined(other.to_raw()) } } } @@ -195,7 +195,7 @@ pub struct JsNull(raw::Persistent); impl JsNull { pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsNull { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::primitive::init_null(out, isolate) + neon_runtime::primitive::null(out, isolate) }) } } @@ -219,7 +219,7 @@ pub struct JsBoolean(raw::Persistent); impl JsBoolean { pub fn new<'a, C: Context<'a>>(cx: &mut C, b: bool) -> &'a JsBoolean { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::primitive::init_boolean(out, isolate, b) + neon_runtime::primitive::boolean(out, isolate, b) }) } @@ -329,7 +329,7 @@ pub struct JsNumber(raw::Persistent); impl JsNumber { pub fn new<'a, C: Context<'a>, T: Into>(cx: &mut C, x: T) -> &'a JsNumber { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::primitive::init_number(out, isolate, x.into()) + neon_runtime::primitive::number(out, isolate, x.into()) }) } @@ -361,7 +361,7 @@ impl ValueInternal for JsObject { fn name() -> String { "object".to_string() } fn is_typeof(other: &Other) -> bool { - unsafe { neon_runtime::tag::is_object_thin(other.to_raw()) } + unsafe { neon_runtime::tag::is_object(other.to_raw()) } } } @@ -374,7 +374,7 @@ unsafe impl This for JsObject { } impl JsObject { pub fn new<'a, C: Context<'a>>(cx: &mut C) -> &'a JsObject { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::object::init(out, isolate) + neon_runtime::object::new(out, isolate) }) } } @@ -388,7 +388,7 @@ impl JsArray { pub fn new<'a, C: Context<'a>>(cx: &mut C, len: u32) -> &'a JsArray { cx.new_infallible(|out, isolate| unsafe { - neon_runtime::array::init(out, isolate, len) + neon_runtime::array::new(out, isolate, len) }) } @@ -445,7 +445,7 @@ impl JsFunction { cx.new(|out, isolate| unsafe { let isolate: *mut c_void = std::mem::transmute(isolate); let callback = FunctionCallback(f).into_c_callback(); - neon_runtime::fun::init(out, isolate, callback) + neon_runtime::fun::new(out, isolate, callback) }) } } @@ -470,7 +470,7 @@ impl JsFunction { let mut args = args.into_iter().collect::>(); let (argc, argv) = unsafe { prepare_args(cx, &mut args) }?; cx.new(|out, isolate| unsafe { - neon_runtime::fun::call_thin(out, isolate, self.to_raw(), this.to_raw(), argc, argv) + neon_runtime::fun::call(out, isolate, self.to_raw(), this.to_raw(), argc, argv) }) } @@ -481,7 +481,7 @@ impl JsFunction { let mut args = args.into_iter().collect::>(); let (argc, argv) = unsafe { prepare_args(cx, &mut args) }?; cx.new(|out, isolate| unsafe { - neon_runtime::fun::construct_thin(out, isolate, self.to_raw(), argc, argv) + neon_runtime::fun::construct(out, isolate, self.to_raw(), argc, argv) }) } } @@ -492,7 +492,7 @@ impl ValueInternal for JsFunction { fn name() -> String { "function".to_string() } fn is_typeof(other: &Other) -> bool { - unsafe { neon_runtime::tag::is_function_thin(other.to_raw()) } + unsafe { neon_runtime::tag::is_function(other.to_raw()) } } } From 749cd6fb8bff1d8405758b68ccfc859d8266f906 Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 22 Feb 2019 22:10:27 -1000 Subject: [PATCH 10/11] All tests passing again! \o/ --- src/context/mod.rs | 6 +-- src/prelude.rs | 2 +- src/types/binary.rs | 12 ++--- src/types/mod.rs | 6 +-- test/dynamic/native/src/js/arrays.rs | 10 ++--- test/dynamic/native/src/js/classes.rs | 6 +-- test/dynamic/native/src/js/functions.rs | 37 +++++++-------- test/dynamic/native/src/js/numbers.rs | 26 +++++------ test/dynamic/native/src/js/objects.rs | 60 ++++++++++++------------- test/dynamic/native/src/js/strings.rs | 2 +- test/dynamic/native/src/js/tasks.rs | 8 ++-- test/static/Cargo.toml | 2 +- 12 files changed, 89 insertions(+), 88 deletions(-) diff --git a/src/context/mod.rs b/src/context/mod.rs index 17a8d7844..154f5d3ac 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -149,9 +149,9 @@ pub trait Context<'a>: ContextInternal<'a> { /// /// ```no_run /// # use neon::prelude::*; - /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult { - /// let mut b: &JsArrayBuffer = cx.argument(0)?; - /// cx.borrow_mut(&b, |data| { + /// # fn my_neon_function(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + /// let b: &JsArrayBuffer = cx.argument(0)?; + /// cx.borrow_mut(b, |data| { /// let slice = data.as_mut_slice::(); /// slice[0] += 1; /// }); diff --git a/src/prelude.rs b/src/prelude.rs index 59bfaf816..e0a570e94 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,6 +1,6 @@ //! A convenience module that re-exports the most commonly-used Neon APIs. -pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, JsObject, JsArray, JsFunction, Value}; +pub use types::{JsBuffer, JsArrayBuffer, BinaryData, JsError, JsUndefined, JsNull, JsBoolean, JsString, JsNumber, JsObject, JsArray, JsFunction, JsValue, Value}; pub use object::{Object, Class}; pub use borrow::{Borrow, BorrowMut}; pub use context::{CallKind, Context, ModuleContext, ExecuteContext, ComputeContext, CallContext, FunctionContext, MethodContext, TaskContext}; diff --git a/src/types/binary.rs b/src/types/binary.rs index 01f445c28..fd451945d 100644 --- a/src/types/binary.rs +++ b/src/types/binary.rs @@ -119,9 +119,9 @@ impl<'a> BinaryData<'a> { /// /// ```no_run /// # use neon::prelude::*; - /// # fn get_x_and_y(mut cx: FunctionContext) -> JsResult { - /// let b: Handle = cx.argument(0)?; - /// let (x, y) = cx.borrow(&b, |data| { + /// # fn get_x_and_y(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + /// let b: &JsArrayBuffer = cx.argument(0)?; + /// let (x, y) = cx.borrow(b, |data| { /// let slice = data.as_slice::(); /// (slice[0], slice[1]) /// }); @@ -141,9 +141,9 @@ impl<'a> BinaryData<'a> { /// /// ```no_run /// # use neon::prelude::*; - /// # fn modify_buffer(mut cx: FunctionContext) -> JsResult { - /// let mut b: Handle = cx.argument(0)?; - /// cx.borrow_mut(&mut b, |data| { + /// # fn modify_buffer(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + /// let b: &JsArrayBuffer = cx.argument(0)?; + /// cx.borrow_mut(b, |data| { /// let slice = data.as_mut_slice::(); /// slice[0] /= 2.0; /// slice[1] *= 2.0; diff --git a/src/types/mod.rs b/src/types/mod.rs index f42718eba..af6f4888c 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -63,8 +63,8 @@ pub trait Value: ValueInternal { /// /// ```no_run /// # use neon::prelude::*; - /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult { - /// let v: Handle = cx.number(17).upcast(); + /// # fn my_neon_function(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + /// let v: &JsValue = cx.number(17).upcast(); /// v.is_a::(); // false /// v.is_a::(); // true /// v.is_a::(); // true @@ -287,7 +287,7 @@ impl JsString { } } - pub fn value(self) -> String { + pub fn value(&self) -> String { unsafe { let capacity = neon_runtime::string::utf8_len(self.to_raw()); let mut buffer: Vec = Vec::with_capacity(capacity as usize); diff --git a/test/dynamic/native/src/js/arrays.rs b/test/dynamic/native/src/js/arrays.rs index 6bbcac7d8..ba3e03463 100644 --- a/test/dynamic/native/src/js/arrays.rs +++ b/test/dynamic/native/src/js/arrays.rs @@ -1,18 +1,18 @@ use neon::prelude::*; -pub fn return_js_array(mut cx: FunctionContext) -> JsResult { +pub fn return_js_array(mut cx: FunctionContext) -> NeonResult<&JsArray> { Ok(cx.empty_array()) } -pub fn return_js_array_with_number(mut cx: FunctionContext) -> JsResult { - let array: Handle = JsArray::new(&mut cx, 1); +pub fn return_js_array_with_number(mut cx: FunctionContext) -> NeonResult<&JsArray> { + let array: &JsArray = JsArray::new(&mut cx, 1); let n = cx.number(9000.0); array.set(&mut cx, 0, n)?; Ok(array) } -pub fn return_js_array_with_string(mut cx: FunctionContext) -> JsResult { - let array: Handle = JsArray::new(&mut cx, 1); +pub fn return_js_array_with_string(mut cx: FunctionContext) -> NeonResult<&JsArray> { + let array: &JsArray = JsArray::new(&mut cx, 1); let s = cx.string("hello node"); array.set(&mut cx, 0, s)?; Ok(array) diff --git a/test/dynamic/native/src/js/classes.rs b/test/dynamic/native/src/js/classes.rs index 54cc839fa..54584f494 100644 --- a/test/dynamic/native/src/js/classes.rs +++ b/test/dynamic/native/src/js/classes.rs @@ -33,9 +33,9 @@ declare_types! { pub class JsUser for User { init(mut cx) { let id = cx.argument::(0)?; - let first_name: Handle = cx.argument::(1)?; - let last_name: Handle = cx.argument::(2)?; - let email: Handle = cx.argument::(3)?; + let first_name: &JsString = cx.argument::(1)?; + let last_name: &JsString = cx.argument::(2)?; + let email: &JsString = cx.argument::(3)?; Ok(User { id: id.value() as i32, diff --git a/test/dynamic/native/src/js/functions.rs b/test/dynamic/native/src/js/functions.rs index 351c6f400..f5a47d213 100644 --- a/test/dynamic/native/src/js/functions.rs +++ b/test/dynamic/native/src/js/functions.rs @@ -1,66 +1,67 @@ use neon::prelude::*; use neon::object::This; +use neon::result::NeonResultExt; -fn add1(mut cx: FunctionContext) -> JsResult { +fn add1(mut cx: FunctionContext) -> NeonResult<&JsNumber> { let x = cx.argument::(0)?.value(); Ok(cx.number(x + 1.0)) } -pub fn return_js_function(mut cx: FunctionContext) -> JsResult { +pub fn return_js_function(mut cx: FunctionContext) -> NeonResult<&JsFunction> { JsFunction::new(&mut cx, add1) } -pub fn call_js_function(mut cx: FunctionContext) -> JsResult { +pub fn call_js_function(mut cx: FunctionContext) -> NeonResult<&JsNumber> { let f = cx.argument::(0)?; - let args: Vec> = vec![cx.number(16.0)]; + let args: Vec<&JsNumber> = vec![cx.number(16.0)]; let null = cx.null(); f.call(&mut cx, null, args)?.downcast::().or_throw(&mut cx) } -pub fn construct_js_function(mut cx: FunctionContext) -> JsResult { +pub fn construct_js_function(mut cx: FunctionContext) -> NeonResult<&JsNumber> { 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::().or_throw(&mut cx)?; - let args: Vec> = vec![]; + let args: Vec<&JsValue> = vec![]; get_utc_full_year_method.call(&mut cx, o.upcast::(), args)?.downcast::().or_throw(&mut cx) } trait CheckArgument<'a> { - fn check_argument(&mut self, i: i32) -> JsResult<'a, V>; + fn check_argument(&mut self, i: i32) -> NeonResult<&'a V>; } impl<'a, T: This> CheckArgument<'a> for CallContext<'a, T> { - fn check_argument(&mut self, i: i32) -> JsResult<'a, V> { + fn check_argument(&mut self, i: i32) -> NeonResult<&'a V> { self.argument::(i) } } -pub fn check_string_and_number(mut cx: FunctionContext) -> JsResult { +pub fn check_string_and_number(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { cx.check_argument::(0)?; cx.check_argument::(1)?; Ok(cx.undefined()) } -pub fn panic(_: FunctionContext) -> JsResult { +pub fn panic(_: FunctionContext) -> NeonResult<&JsUndefined> { panic!("zomg") } -pub fn panic_after_throw(mut cx: FunctionContext) -> JsResult { +pub fn panic_after_throw(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { cx.throw_range_error::<_, ()>("entering throw state with a RangeError").unwrap_err(); panic!("this should override the RangeError") } -pub fn num_arguments(mut cx: FunctionContext) -> JsResult { +pub fn num_arguments(mut cx: FunctionContext) -> NeonResult<&JsNumber> { let n = cx.len(); Ok(cx.number(n)) } -pub fn return_this(mut cx: FunctionContext) -> JsResult { +pub fn return_this(mut cx: FunctionContext) -> NeonResult<&JsValue> { Ok(cx.this().upcast()) } -pub fn require_object_this(mut cx: FunctionContext) -> JsResult { +pub fn require_object_this(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { let this = cx.this(); let this = this.downcast::().or_throw(&mut cx)?; let t = cx.boolean(true); @@ -68,17 +69,17 @@ pub fn require_object_this(mut cx: FunctionContext) -> JsResult { Ok(cx.undefined()) } -pub fn is_argument_zero_some(mut cx: FunctionContext) -> JsResult { +pub fn is_argument_zero_some(mut cx: FunctionContext) -> NeonResult<&JsBoolean> { let b = cx.argument_opt(0).is_some(); Ok(cx.boolean(b)) } -pub fn require_argument_zero_string(mut cx: FunctionContext) -> JsResult { +pub fn require_argument_zero_string(mut cx: FunctionContext) -> NeonResult<&JsString> { let s = cx.argument(0)?; Ok(s) } -pub fn execute_scoped(mut cx: FunctionContext) -> JsResult { +pub fn execute_scoped(mut cx: FunctionContext) -> NeonResult<&JsNumber> { let mut i = 0; for _ in 1..100 { cx.execute_scoped(|mut cx| { @@ -89,7 +90,7 @@ pub fn execute_scoped(mut cx: FunctionContext) -> JsResult { Ok(cx.number(i)) } -pub fn compute_scoped(mut cx: FunctionContext) -> JsResult { +pub fn compute_scoped(mut cx: FunctionContext) -> NeonResult<&JsNumber> { let mut i = cx.number(0); for _ in 1..100 { i = cx.compute_scoped(|mut cx| { diff --git a/test/dynamic/native/src/js/numbers.rs b/test/dynamic/native/src/js/numbers.rs index 9da7c79eb..26b9ff976 100644 --- a/test/dynamic/native/src/js/numbers.rs +++ b/test/dynamic/native/src/js/numbers.rs @@ -1,41 +1,41 @@ use neon::prelude::*; -pub fn return_js_number(mut cx: FunctionContext) -> JsResult { +pub fn return_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { Ok(cx.number(9000_f64)) } -pub fn return_large_js_number(mut cx: FunctionContext) -> JsResult { +pub fn return_large_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { Ok(cx.number(4294967296_f64)) } -pub fn return_negative_js_number(mut cx: FunctionContext) -> JsResult { +pub fn return_negative_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { Ok(cx.number(-9000_f64)) } -pub fn return_float_js_number(mut cx: FunctionContext) -> JsResult { +pub fn return_float_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { Ok(cx.number(1.4747_f64)) } -pub fn return_negative_float_js_number(mut cx: FunctionContext) -> JsResult { +pub fn return_negative_float_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { Ok(cx.number(-1.4747_f64)) } -pub fn accept_and_return_js_number(mut cx: FunctionContext) -> JsResult { - let number: Handle = cx.argument(0)?; +pub fn accept_and_return_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let number: &JsNumber = cx.argument(0)?; Ok(number) } -pub fn accept_and_return_large_js_number(mut cx: FunctionContext) -> JsResult { - let number: Handle = cx.argument(0)?; +pub fn accept_and_return_large_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let number: &JsNumber = cx.argument(0)?; Ok(number) } -pub fn accept_and_return_float_js_number(mut cx: FunctionContext) -> JsResult { - let number: Handle = cx.argument(0)?; +pub fn accept_and_return_float_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let number: &JsNumber = cx.argument(0)?; Ok(number) } -pub fn accept_and_return_negative_js_number(mut cx: FunctionContext) -> JsResult { - let number: Handle = cx.argument(0)?; +pub fn accept_and_return_negative_js_number(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let number: &JsNumber = cx.argument(0)?; Ok(number) } diff --git a/test/dynamic/native/src/js/objects.rs b/test/dynamic/native/src/js/objects.rs index e6a2fc436..6a7cd73c8 100644 --- a/test/dynamic/native/src/js/objects.rs +++ b/test/dynamic/native/src/js/objects.rs @@ -1,15 +1,15 @@ use neon::prelude::*; -pub fn return_js_global_object(mut cx: FunctionContext) -> JsResult { +pub fn return_js_global_object(mut cx: FunctionContext) -> NeonResult<&JsObject> { Ok(cx.global()) } -pub fn return_js_object(mut cx: FunctionContext) -> JsResult { +pub fn return_js_object(mut cx: FunctionContext) -> NeonResult<&JsObject> { Ok(cx.empty_object()) } -pub fn return_js_object_with_mixed_content(mut cx: FunctionContext) -> JsResult { - let js_object: Handle = cx.empty_object(); +pub fn return_js_object_with_mixed_content(mut cx: FunctionContext) -> NeonResult<&JsObject> { + let js_object: &JsObject = cx.empty_object(); let n = cx.number(9000.0); js_object.set(&mut cx, "number", n)?; let s = cx.string("hello node"); @@ -17,27 +17,27 @@ pub fn return_js_object_with_mixed_content(mut cx: FunctionContext) -> JsResult< Ok(js_object) } -pub fn return_js_object_with_number(mut cx: FunctionContext) -> JsResult { - let js_object: Handle = cx.empty_object(); +pub fn return_js_object_with_number(mut cx: FunctionContext) -> NeonResult<&JsObject> { + let js_object: &JsObject = cx.empty_object(); let n = cx.number(9000.0); js_object.set(&mut cx, "number", n)?; Ok(js_object) } -pub fn return_js_object_with_string(mut cx: FunctionContext) -> JsResult { - let js_object: Handle = cx.empty_object(); +pub fn return_js_object_with_string(mut cx: FunctionContext) -> NeonResult<&JsObject> { + let js_object: &JsObject = cx.empty_object(); let s = cx.string("hello node"); js_object.set(&mut cx, "string", s)?; Ok(js_object) } -pub fn return_array_buffer(mut cx: FunctionContext) -> JsResult { - let b: Handle = cx.array_buffer(16)?; +pub fn return_array_buffer(mut cx: FunctionContext) -> NeonResult<&JsArrayBuffer> { + let b: &JsArrayBuffer = cx.array_buffer(16)?; Ok(b) } -pub fn read_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult { - let b: Handle = cx.argument(0)?; +pub fn read_array_buffer_with_lock(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let b: &JsArrayBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; let x = { let guard = cx.lock(); @@ -48,15 +48,15 @@ pub fn read_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult JsResult { - let b: Handle = cx.argument(0)?; +pub fn read_array_buffer_with_borrow(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let b: &JsArrayBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; - let x = cx.borrow(&b, |data| { data.as_slice::()[i] }); + let x = cx.borrow(b, |data| { data.as_slice::()[i] }); Ok(cx.number(x)) } -pub fn write_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult { - let mut b: Handle = cx.argument(0)?; +pub fn write_array_buffer_with_lock(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + let b: &JsArrayBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; let x = cx.argument::(2)?.value() as u32; { @@ -68,16 +68,16 @@ pub fn write_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult JsResult { - let mut b: Handle = cx.argument(0)?; +pub fn write_array_buffer_with_borrow_mut(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + let b: &JsArrayBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; let x = cx.argument::(2)?.value() as u32; - cx.borrow_mut(&mut b, |data| { data.as_mut_slice::()[i] = x; }); + cx.borrow_mut(b, |data| { data.as_mut_slice::()[i] = x; }); Ok(cx.undefined()) } -pub fn read_buffer_with_lock(mut cx: FunctionContext) -> JsResult { - let b: Handle = cx.argument(0)?; +pub fn read_buffer_with_lock(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let b: &JsBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; let x = { let guard = cx.lock(); @@ -88,15 +88,15 @@ pub fn read_buffer_with_lock(mut cx: FunctionContext) -> JsResult { Ok(cx.number(x)) } -pub fn read_buffer_with_borrow(mut cx: FunctionContext) -> JsResult { - let b: Handle = cx.argument(0)?; +pub fn read_buffer_with_borrow(mut cx: FunctionContext) -> NeonResult<&JsNumber> { + let b: &JsBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; - let x = cx.borrow(&b, |data| { data.as_slice::()[i] }); + let x = cx.borrow(b, |data| { data.as_slice::()[i] }); Ok(cx.number(x)) } -pub fn write_buffer_with_lock(mut cx: FunctionContext) -> JsResult { - let mut b: Handle = cx.argument(0)?; +pub fn write_buffer_with_lock(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + let b: &JsBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; let x = cx.argument::(2)?.value() as u32; { @@ -108,10 +108,10 @@ pub fn write_buffer_with_lock(mut cx: FunctionContext) -> JsResult Ok(cx.undefined()) } -pub fn write_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult { - let mut b: Handle = cx.argument(0)?; +pub fn write_buffer_with_borrow_mut(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { + let b: &JsBuffer = cx.argument(0)?; let i = cx.argument::(1)?.value() as u32 as usize; let x = cx.argument::(2)?.value() as u32; - cx.borrow_mut(&mut b, |data| { data.as_mut_slice::()[i] = x; }); + cx.borrow_mut(b, |data| { data.as_mut_slice::()[i] = x; }); Ok(cx.undefined()) } diff --git a/test/dynamic/native/src/js/strings.rs b/test/dynamic/native/src/js/strings.rs index 7fcb0b14b..94fb334c1 100644 --- a/test/dynamic/native/src/js/strings.rs +++ b/test/dynamic/native/src/js/strings.rs @@ -1,5 +1,5 @@ use neon::prelude::*; -pub fn return_js_string(mut cx: FunctionContext) -> JsResult { +pub fn return_js_string(mut cx: FunctionContext) -> NeonResult<&JsString> { Ok(cx.string("hello node")) } diff --git a/test/dynamic/native/src/js/tasks.rs b/test/dynamic/native/src/js/tasks.rs index 40e6b5d87..81d968ebb 100644 --- a/test/dynamic/native/src/js/tasks.rs +++ b/test/dynamic/native/src/js/tasks.rs @@ -11,12 +11,12 @@ impl Task for SuccessTask { Ok(17) } - fn complete(self, mut cx: TaskContext, result: Result) -> JsResult { + fn complete(self, mut cx: TaskContext, result: Result) -> NeonResult<&Self::JsEvent> { Ok(cx.number(result.unwrap())) } } -pub fn perform_async_task(mut cx: FunctionContext) -> JsResult { +pub fn perform_async_task(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { let f = cx.argument::(0)?; SuccessTask.schedule(f); Ok(cx.undefined()) @@ -33,12 +33,12 @@ impl Task for FailureTask { Err(format!("I am a failing task")) } - fn complete(self, mut cx: TaskContext, result: Result) -> JsResult { + fn complete(self, mut cx: TaskContext, result: Result) -> NeonResult<&Self::JsEvent> { cx.throw_error(&result.unwrap_err()) } } -pub fn perform_failing_task(mut cx: FunctionContext) -> JsResult { +pub fn perform_failing_task(mut cx: FunctionContext) -> NeonResult<&JsUndefined> { let f = cx.argument::(0)?; FailureTask.schedule(f); Ok(cx.undefined()) diff --git a/test/static/Cargo.toml b/test/static/Cargo.toml index 6a94cde14..0838c6d35 100644 --- a/test/static/Cargo.toml +++ b/test/static/Cargo.toml @@ -6,4 +6,4 @@ license = "MIT/Apache-2.0" [dependencies] neon = { path = "../../" } -compiletest_rs = "0.3.2" +compiletest_rs = "0.3.18" From aea5dc07131b0023d83d8095aee77d59f919326b Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 22 Feb 2019 22:37:07 -1000 Subject: [PATCH 11/11] Add back accidentally-removed JS [[ToString]] operation (`Value::to_string()`) --- crates/neon-runtime/src/neon.cc | 18 ++++++++++-------- crates/neon-runtime/src/neon.h | 4 +--- crates/neon-runtime/src/string.rs | 5 +++++ src/types/mod.rs | 5 +++++ 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/crates/neon-runtime/src/neon.cc b/crates/neon-runtime/src/neon.cc index a8d7cf5b9..316e2d535 100644 --- a/crates/neon-runtime/src/neon.cc +++ b/crates/neon-runtime/src/neon.cc @@ -219,14 +219,16 @@ extern "C" size_t Neon_String_Data(char *out, size_t len, v8::Persistent *out, v8::Local value) { - Nan::MaybeLocal maybe = Nan::To(value); - return maybe.ToLocal(out); -} - -extern "C" bool Neon_Convert_ToObject(v8::Local *out, v8::Local *value) { - Nan::MaybeLocal maybe = Nan::To(*value); - return maybe.ToLocal(out); +extern "C" bool Neon_String_ToString(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *value) { + Nan::HandleScope scope; + v8::Local lvalue = Nan::New(*value); + Nan::MaybeLocal maybe = Nan::To(lvalue); + v8::Local lout; + if (!maybe.ToLocal(&lout)) { + return false; + } + out->Reset(isolate, lout); + return true; } extern "C" bool Neon_Buffer_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t len) { diff --git a/crates/neon-runtime/src/neon.h b/crates/neon-runtime/src/neon.h index 096b5f388..c6e20ec76 100644 --- a/crates/neon-runtime/src/neon.h +++ b/crates/neon-runtime/src/neon.h @@ -44,9 +44,7 @@ extern "C" { bool Neon_String_New(v8::Persistent *out, v8::Isolate *isolate, const uint8_t *data, int32_t len); int32_t Neon_String_Utf8Length(v8::Persistent *str); size_t Neon_String_Data(char *out, size_t len, v8::Persistent *str); - - bool Neon_Convert_ToString(v8::Local *out, v8::Local value); - bool Neon_Convert_ToObject(v8::Local *out, v8::Local *value); + bool Neon_String_ToString(v8::Persistent *out, v8::Isolate *isolate, v8::Persistent *value); bool Neon_Buffer_New(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); bool Neon_Buffer_Uninitialized(v8::Persistent *out, v8::Isolate *isolate, uint32_t len); diff --git a/crates/neon-runtime/src/string.rs b/crates/neon-runtime/src/string.rs index 199f41702..db202267c 100644 --- a/crates/neon-runtime/src/string.rs +++ b/crates/neon-runtime/src/string.rs @@ -17,4 +17,9 @@ extern "C" { #[link_name = "Neon_String_Data"] pub fn data(out: *mut u8, len: isize, str: &Persistent) -> isize; + /// Mutates the `out` argument to the result of applying the standard JS string conversion + /// operation on the `from` argument. + #[link_name = "Neon_String_ToString"] + pub fn to_string(out: &Persistent, isolate: *mut Isolate, from: &Persistent) -> bool; + } diff --git a/src/types/mod.rs b/src/types/mod.rs index af6f4888c..9039cc423 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -94,6 +94,11 @@ pub trait Value: ValueInternal { self.downcast().or_throw(cx) } + fn to_string<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&'a JsString> { + cx.new(|out, isolate| unsafe { + neon_runtime::string::to_string(out, isolate, self.to_raw()) + }) + } } /// An error representing a failed downcast.