-
Notifications
You must be signed in to change notification settings - Fork 286
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #324 from dherman/module-reorg
Module reorganization
- Loading branch information
Showing
27 changed files
with
881 additions
and
878 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
use std; | ||
use std::os::raw::c_void; | ||
use std::collections::HashSet; | ||
use borrow::LoanError; | ||
|
||
pub unsafe trait Pointer { | ||
unsafe fn as_ptr(&self) -> *const c_void; | ||
unsafe fn as_mut(&mut self) -> *mut c_void; | ||
} | ||
|
||
unsafe impl<T> Pointer for *mut T { | ||
unsafe fn as_ptr(&self) -> *const c_void { | ||
*self as *const c_void | ||
} | ||
|
||
unsafe fn as_mut(&mut self) -> *mut c_void { | ||
*self as *mut c_void | ||
} | ||
} | ||
unsafe impl<'a, T> Pointer for &'a mut T { | ||
unsafe fn as_ptr(&self) -> *const c_void { | ||
let r: &T = &**self; | ||
std::mem::transmute(r) | ||
} | ||
|
||
unsafe fn as_mut(&mut self) -> *mut c_void { | ||
let r: &mut T = &mut **self; | ||
std::mem::transmute(r) | ||
} | ||
} | ||
|
||
pub struct Ledger { | ||
immutable_loans: HashSet<*const c_void>, | ||
mutable_loans: HashSet<*const c_void> | ||
} | ||
|
||
impl Ledger { | ||
pub fn new() -> Self { | ||
Ledger { | ||
immutable_loans: HashSet::new(), | ||
mutable_loans: HashSet::new() | ||
} | ||
} | ||
|
||
pub fn try_borrow<T>(&mut self, p: *const T) -> Result<(), LoanError> { | ||
let p = p as *const c_void; | ||
if self.mutable_loans.contains(&p) { | ||
return Err(LoanError::Mutating(p)); | ||
} | ||
self.immutable_loans.insert(p); | ||
Ok(()) | ||
} | ||
|
||
pub fn settle<T>(&mut self, p: *const T) { | ||
let p = p as *const c_void; | ||
self.immutable_loans.remove(&p); | ||
} | ||
|
||
pub fn try_borrow_mut<T>(&mut self, p: *mut T) -> Result<(), LoanError> { | ||
let p = p as *const c_void; | ||
if self.mutable_loans.contains(&p) { | ||
return Err(LoanError::Mutating(p)); | ||
} else if self.immutable_loans.contains(&p) { | ||
return Err(LoanError::Frozen(p)); | ||
} | ||
self.mutable_loans.insert(p); | ||
Ok(()) | ||
} | ||
|
||
pub fn settle_mut<T>(&mut self, p: *mut T) { | ||
let p = p as *const c_void; | ||
self.mutable_loans.remove(&p); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
//! Types and traits for obtaining temporary access to the internals of JavaScript values. | ||
pub(crate) mod internal; | ||
|
||
use std::ops::{Deref, DerefMut, Drop}; | ||
use std::fmt; | ||
use std::os::raw::c_void; | ||
|
||
use context::Lock; | ||
use self::internal::Pointer; | ||
|
||
/// A trait for JS values whose internal contents can be borrowed immutably by Rust while the JS engine is locked. | ||
pub trait Borrow: Sized { | ||
|
||
/// The type of the value's internal contents. | ||
type Target: Pointer; | ||
|
||
/// Borrow the contents of this value immutably. | ||
/// | ||
/// If there is already an outstanding mutable loan for this value, this method panics. | ||
fn borrow<'a>(self, lock: &'a Lock<'a>) -> Ref<'a, Self::Target> { | ||
match self.try_borrow(lock) { | ||
Ok(r) => r, | ||
Err(e) => panic!("{}", e) | ||
} | ||
} | ||
|
||
/// Borrow the contents of this value immutably. | ||
/// | ||
/// If there is already an outstanding mutable loan for this value, this method fails with a `LoanError`. | ||
fn try_borrow<'a>(self, lock: &'a Lock<'a>) -> Result<Ref<'a, Self::Target>, LoanError>; | ||
|
||
} | ||
|
||
/// A trait for JS values whose internal contents can be borrowed mutably by Rust while the JS engine is locked. | ||
pub trait BorrowMut: Borrow { | ||
|
||
/// Borrow the contents of this value mutably. | ||
/// | ||
/// If there is already an outstanding loan for this value, this method panics. | ||
fn borrow_mut<'a>(self, lock: &'a Lock<'a>) -> RefMut<'a, Self::Target> { | ||
match self.try_borrow_mut(lock) { | ||
Ok(r) => r, | ||
Err(e) => panic!("{}", e) | ||
} | ||
} | ||
|
||
/// Borrow the contents of this value mutably. | ||
/// | ||
/// If there is already an outstanding loan for this value, this method panics. | ||
fn try_borrow_mut<'a>(self, lock: &'a Lock<'a>) -> Result<RefMut<'a, Self::Target>, LoanError>; | ||
|
||
} | ||
|
||
/// An error produced by a failed loan in the `Borrow` or `BorrowMut` traits. | ||
pub enum LoanError { | ||
|
||
/// Indicates that there is already an outstanding mutable loan for the object at this address. | ||
Mutating(*const c_void), | ||
|
||
/// Indicates that there is already an outstanding immutable loan for the object at this address. | ||
Frozen(*const c_void) | ||
|
||
} | ||
|
||
impl fmt::Display for LoanError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
match *self { | ||
LoanError::Mutating(p) => { | ||
write!(f, "outstanding mutable loan exists for object at {:?}", p) | ||
} | ||
LoanError::Frozen(p) => { | ||
write!(f, "object at {:?} is frozen", p) | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// An immutable reference to the contents of a borrowed JS value. | ||
pub struct Ref<'a, T: Pointer> { | ||
pointer: T, | ||
lock: &'a Lock<'a> | ||
} | ||
|
||
impl<'a, T: Pointer> Ref<'a, T> { | ||
pub(crate) unsafe fn new(lock: &'a Lock<'a>, pointer: T) -> Result<Self, LoanError> { | ||
let mut ledger = lock.ledger.borrow_mut(); | ||
ledger.try_borrow(pointer.as_ptr())?; | ||
Ok(Ref { pointer, lock }) | ||
} | ||
} | ||
|
||
impl<'a, T: Pointer> Drop for Ref<'a, T> { | ||
fn drop(&mut self) { | ||
let mut ledger = self.lock.ledger.borrow_mut(); | ||
ledger.settle(unsafe { self.pointer.as_ptr() }); | ||
} | ||
} | ||
|
||
impl<'a, T: Pointer> Deref for Ref<'a, T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.pointer | ||
} | ||
} | ||
|
||
/// A mutable reference to the contents of a borrowed JS value. | ||
pub struct RefMut<'a, T: Pointer> { | ||
pointer: T, | ||
lock: &'a Lock<'a> | ||
} | ||
|
||
impl<'a, T: Pointer> RefMut<'a, T> { | ||
pub(crate) unsafe fn new(lock: &'a Lock<'a>, mut pointer: T) -> Result<Self, LoanError> { | ||
let mut ledger = lock.ledger.borrow_mut(); | ||
ledger.try_borrow_mut(pointer.as_mut())?; | ||
Ok(RefMut { pointer, lock }) | ||
} | ||
} | ||
|
||
impl<'a, T: Pointer> Drop for RefMut<'a, T> { | ||
fn drop(&mut self) { | ||
let mut ledger = self.lock.ledger.borrow_mut(); | ||
ledger.settle_mut(unsafe { self.pointer.as_mut() }); | ||
} | ||
} | ||
|
||
impl<'a, T: Pointer> Deref for RefMut<'a, T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.pointer | ||
} | ||
} | ||
|
||
impl<'a, T: Pointer> DerefMut for RefMut<'a, T> { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.pointer | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use std; | ||
use std::cell::Cell; | ||
use std::os::raw::c_void; | ||
use neon_runtime; | ||
use neon_runtime::raw; | ||
use neon_runtime::scope::Root; | ||
use value::JsObject; | ||
use value::mem::Handle; | ||
use object::class::ClassMap; | ||
use result::NeonResult; | ||
use super::ModuleContext; | ||
|
||
#[repr(C)] | ||
#[derive(Clone, Copy)] | ||
pub struct Isolate(*mut raw::Isolate); | ||
|
||
extern "C" fn drop_class_map(map: Box<ClassMap>) { | ||
std::mem::drop(map); | ||
} | ||
|
||
impl Isolate { | ||
pub(crate) fn to_raw(self) -> *mut raw::Isolate { | ||
let Isolate(ptr) = self; | ||
ptr | ||
} | ||
|
||
pub(crate) fn class_map(&mut self) -> &mut ClassMap { | ||
let mut ptr: *mut c_void = unsafe { neon_runtime::class::get_class_map(self.to_raw()) }; | ||
if ptr.is_null() { | ||
let b: Box<ClassMap> = Box::new(ClassMap::new()); | ||
let raw = Box::into_raw(b); | ||
ptr = unsafe { std::mem::transmute(raw) }; | ||
let free_map: *mut c_void = unsafe { std::mem::transmute(drop_class_map as usize) }; | ||
unsafe { | ||
neon_runtime::class::set_class_map(self.to_raw(), ptr, free_map); | ||
} | ||
} | ||
unsafe { std::mem::transmute(ptr) } | ||
} | ||
|
||
pub(crate) fn current() -> Isolate { | ||
unsafe { | ||
std::mem::transmute(neon_runtime::call::current_isolate()) | ||
} | ||
} | ||
} | ||
|
||
pub struct ScopeMetadata { | ||
isolate: Isolate, | ||
active: Cell<bool> | ||
} | ||
|
||
pub struct Scope<'a, R: Root + 'static> { | ||
pub metadata: ScopeMetadata, | ||
pub handle_scope: &'a mut R | ||
} | ||
|
||
impl<'a, R: Root + 'static> Scope<'a, R> { | ||
pub fn with<T, F: for<'b> FnOnce(Scope<'b, R>) -> T>(f: F) -> T { | ||
let mut handle_scope: R = unsafe { R::allocate() }; | ||
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 | ||
}; | ||
f(scope) | ||
}; | ||
unsafe { | ||
handle_scope.exit(); | ||
} | ||
result | ||
} | ||
} | ||
|
||
pub trait ContextInternal<'a>: Sized { | ||
fn scope_metadata(&self) -> &ScopeMetadata; | ||
|
||
fn isolate(&self) -> Isolate { | ||
self.scope_metadata().isolate | ||
} | ||
|
||
fn is_active(&self) -> bool { | ||
self.scope_metadata().active.get() | ||
} | ||
|
||
fn check_active(&self) { | ||
if !self.is_active() { | ||
panic!("execution context is inactive"); | ||
} | ||
} | ||
|
||
fn activate(&self) { self.scope_metadata().active.set(true); } | ||
fn deactivate(&self) { self.scope_metadata().active.set(false); } | ||
} | ||
|
||
pub fn initialize_module(exports: Handle<JsObject>, init: fn(ModuleContext) -> NeonResult<()>) { | ||
ModuleContext::with(exports, |cx| { | ||
let _ = init(cx); | ||
}); | ||
} |
Oops, something went wrong.