1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-03 12:58:54 -05:00

tidy up deno_core modules (#5923)

This commit is contained in:
Ryan Dahl 2020-05-28 13:36:43 -04:00 committed by GitHub
parent 86c6f05404
commit 2610ceac20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 235 additions and 225 deletions

View file

@ -1,71 +0,0 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use std::any::Any;
use std::any::TypeId;
use std::convert::From;
use std::error::Error;
use std::fmt;
use std::ops::Deref;
// The Send and Sync traits are required because deno is multithreaded and we
// need to be able to handle errors across threads.
pub trait AnyError: Any + Error + Send + Sync + 'static {}
impl<T> AnyError for T where T: Any + Error + Send + Sync + Sized + 'static {}
#[derive(Debug)]
pub struct ErrBox(Box<dyn AnyError>);
impl dyn AnyError {
pub fn downcast_ref<T: AnyError>(&self) -> Option<&T> {
if Any::type_id(self) == TypeId::of::<T>() {
let target = self as *const Self as *const T;
let target = unsafe { &*target };
Some(target)
} else {
None
}
}
}
impl ErrBox {
pub fn downcast<T: AnyError>(self) -> Result<T, Self> {
if Any::type_id(&*self.0) == TypeId::of::<T>() {
let target = Box::into_raw(self.0) as *mut T;
let target = unsafe { Box::from_raw(target) };
Ok(*target)
} else {
Err(self)
}
}
}
impl AsRef<dyn AnyError> for ErrBox {
fn as_ref(&self) -> &dyn AnyError {
self.0.as_ref()
}
}
impl Deref for ErrBox {
type Target = Box<dyn AnyError>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: AnyError> From<T> for ErrBox {
fn from(error: T) -> Self {
Self(Box::new(error))
}
}
impl From<Box<dyn AnyError>> for ErrBox {
fn from(boxed: Box<dyn AnyError>) -> Self {
Self(boxed)
}
}
impl fmt::Display for ErrBox {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}

View file

@ -1,9 +1,9 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::es_isolate::EsIsolate; use crate::CoreIsolate;
use crate::isolate::CoreIsolate; use crate::EsIsolate;
use crate::isolate::ZeroCopyBuf; use crate::JSError;
use crate::js_errors::JSError; use crate::ZeroCopyBuf;
use rusty_v8 as v8; use rusty_v8 as v8;
use v8::MapFnTo; use v8::MapFnTo;

View file

@ -7,13 +7,14 @@
use rusty_v8 as v8; use rusty_v8 as v8;
use crate::any_error::ErrBox;
use crate::bindings; use crate::bindings;
use crate::js_errors::JSError;
use crate::ops::*; use crate::ops::*;
use crate::shared_queue::SharedQueue; use crate::shared_queue::SharedQueue;
use crate::shared_queue::RECOMMENDED_SIZE; use crate::shared_queue::RECOMMENDED_SIZE;
use crate::ErrBox;
use crate::JSError;
use crate::ResourceTable; use crate::ResourceTable;
use crate::ZeroCopyBuf;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::stream::select; use futures::stream::select;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
@ -24,10 +25,7 @@ use libc::c_void;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From; use std::convert::From;
use std::error::Error;
use std::fmt;
use std::mem::forget; use std::mem::forget;
use std::ops::{Deref, DerefMut};
use std::option::Option; use std::option::Option;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
@ -37,69 +35,6 @@ use std::task::Poll;
type PendingOpFuture = Pin<Box<dyn Future<Output = (OpId, Buf)>>>; type PendingOpFuture = Pin<Box<dyn Future<Output = (OpId, Buf)>>>;
/// A ZeroCopyBuf encapsulates a slice that's been borrowed from a JavaScript
/// ArrayBuffer object. JavaScript objects can normally be garbage collected,
/// but the existence of a ZeroCopyBuf inhibits this until it is dropped. It
/// behaves much like an Arc<[u8]>, although a ZeroCopyBuf currently can't be
/// cloned.
pub struct ZeroCopyBuf {
backing_store: v8::SharedRef<v8::BackingStore>,
byte_offset: usize,
byte_length: usize,
}
unsafe impl Send for ZeroCopyBuf {}
impl ZeroCopyBuf {
pub fn new(view: v8::Local<v8::ArrayBufferView>) -> Self {
let backing_store = view.buffer().unwrap().get_backing_store();
let byte_offset = view.byte_offset();
let byte_length = view.byte_length();
Self {
backing_store,
byte_offset,
byte_length,
}
}
}
impl Deref for ZeroCopyBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
bindings::get_backing_store_slice(
&self.backing_store,
self.byte_offset,
self.byte_length,
)
}
}
}
impl DerefMut for ZeroCopyBuf {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
bindings::get_backing_store_slice_mut(
&self.backing_store,
self.byte_offset,
self.byte_length,
)
}
}
}
impl AsRef<[u8]> for ZeroCopyBuf {
fn as_ref(&self) -> &[u8] {
&*self
}
}
impl AsMut<[u8]> for ZeroCopyBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut *self
}
}
/// Stores a script used to initialize a Isolate /// Stores a script used to initialize a Isolate
pub struct Script<'a> { pub struct Script<'a> {
pub source: &'a str, pub source: &'a str,
@ -627,14 +562,6 @@ fn drain_macrotasks<'s>(
Ok(()) Ok(())
} }
pub(crate) fn attach_handle_to_error(
scope: &mut impl v8::InIsolate,
err: ErrBox,
handle: v8::Local<v8::Value>,
) -> ErrBox {
ErrWithV8Handle::new(scope, err, handle).into()
}
pub(crate) fn exception_to_err_result<'s, T>( pub(crate) fn exception_to_err_result<'s, T>(
scope: &mut impl v8::ToLocal<'s>, scope: &mut impl v8::ToLocal<'s>,
exception: v8::Local<v8::Value>, exception: v8::Local<v8::Value>,
@ -1183,42 +1110,3 @@ pub mod tests {
js_check(isolate2.execute("check.js", "if (a != 3) throw Error('x')")); js_check(isolate2.execute("check.js", "if (a != 3) throw Error('x')"));
} }
} }
// TODO(piscisaureus): rusty_v8 should implement the Error trait on
// values of type v8::Global<T>.
pub struct ErrWithV8Handle {
err: ErrBox,
handle: v8::Global<v8::Value>,
}
impl ErrWithV8Handle {
pub fn new(
scope: &mut impl v8::InIsolate,
err: ErrBox,
handle: v8::Local<v8::Value>,
) -> Self {
let handle = v8::Global::new_from(scope, handle);
Self { err, handle }
}
pub fn get_handle(&self) -> &v8::Global<v8::Value> {
&self.handle
}
}
unsafe impl Send for ErrWithV8Handle {}
unsafe impl Sync for ErrWithV8Handle {}
impl Error for ErrWithV8Handle {}
impl fmt::Display for ErrWithV8Handle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}
impl fmt::Debug for ErrWithV8Handle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}

View file

@ -1,11 +1,76 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::ErrBox;
use rusty_v8 as v8; use rusty_v8 as v8;
use std::any::Any;
use std::any::TypeId;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::convert::TryInto; use std::convert::TryInto;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::ops::Deref;
// The Send and Sync traits are required because deno is multithreaded and we
// need to be able to handle errors across threads.
pub trait AnyError: Any + Error + Send + Sync + 'static {}
impl<T> AnyError for T where T: Any + Error + Send + Sync + Sized + 'static {}
#[derive(Debug)]
pub struct ErrBox(Box<dyn AnyError>);
impl dyn AnyError {
pub fn downcast_ref<T: AnyError>(&self) -> Option<&T> {
if Any::type_id(self) == TypeId::of::<T>() {
let target = self as *const Self as *const T;
let target = unsafe { &*target };
Some(target)
} else {
None
}
}
}
impl ErrBox {
pub fn downcast<T: AnyError>(self) -> Result<T, Self> {
if Any::type_id(&*self.0) == TypeId::of::<T>() {
let target = Box::into_raw(self.0) as *mut T;
let target = unsafe { Box::from_raw(target) };
Ok(*target)
} else {
Err(self)
}
}
}
impl AsRef<dyn AnyError> for ErrBox {
fn as_ref(&self) -> &dyn AnyError {
self.0.as_ref()
}
}
impl Deref for ErrBox {
type Target = Box<dyn AnyError>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: AnyError> From<T> for ErrBox {
fn from(error: T) -> Self {
Self(Box::new(error))
}
}
impl From<Box<dyn AnyError>> for ErrBox {
fn from(boxed: Box<dyn AnyError>) -> Self {
Self(boxed)
}
}
impl fmt::Display for ErrBox {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
/// A `JSError` represents an exception coming from V8, with stack frames and /// A `JSError` represents an exception coming from V8, with stack frames and
/// line numbers. The deno_cli crate defines another `JSError` type, which wraps /// line numbers. The deno_cli crate defines another `JSError` type, which wraps
@ -298,3 +363,50 @@ impl fmt::Display for JSError {
Ok(()) Ok(())
} }
} }
pub(crate) fn attach_handle_to_error(
scope: &mut impl v8::InIsolate,
err: ErrBox,
handle: v8::Local<v8::Value>,
) -> ErrBox {
ErrWithV8Handle::new(scope, err, handle).into()
}
// TODO(piscisaureus): rusty_v8 should implement the Error trait on
// values of type v8::Global<T>.
pub struct ErrWithV8Handle {
err: ErrBox,
handle: v8::Global<v8::Value>,
}
impl ErrWithV8Handle {
pub fn new(
scope: &mut impl v8::InIsolate,
err: ErrBox,
handle: v8::Local<v8::Value>,
) -> Self {
let handle = v8::Global::new_from(scope, handle);
Self { err, handle }
}
pub fn get_handle(&self) -> &v8::Global<v8::Value> {
&self.handle
}
}
unsafe impl Send for ErrWithV8Handle {}
unsafe impl Sync for ErrWithV8Handle {}
impl Error for ErrWithV8Handle {}
impl fmt::Display for ErrWithV8Handle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}
impl fmt::Debug for ErrWithV8Handle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}

View file

@ -6,10 +6,10 @@
use rusty_v8 as v8; use rusty_v8 as v8;
use crate::any_error::ErrBox;
use crate::bindings; use crate::bindings;
use crate::errors::ErrBox;
use crate::errors::ErrWithV8Handle;
use crate::futures::FutureExt; use crate::futures::FutureExt;
use crate::ErrWithV8Handle;
use futures::ready; use futures::ready;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -26,20 +26,19 @@ use std::rc::Rc;
use std::task::Context; use std::task::Context;
use std::task::Poll; use std::task::Poll;
use crate::isolate::attach_handle_to_error; use crate::core_isolate::exception_to_err_result;
use crate::isolate::exception_to_err_result; use crate::errors::attach_handle_to_error;
use crate::isolate::CoreIsolate;
use crate::isolate::StartupData;
use crate::module_specifier::ModuleSpecifier; use crate::module_specifier::ModuleSpecifier;
use crate::modules::LoadState; use crate::modules::LoadState;
use crate::modules::ModuleId;
use crate::modules::ModuleLoadId;
use crate::modules::ModuleLoader; use crate::modules::ModuleLoader;
use crate::modules::ModuleSource; use crate::modules::ModuleSource;
use crate::modules::Modules; use crate::modules::Modules;
use crate::modules::PrepareLoadFuture; use crate::modules::PrepareLoadFuture;
use crate::modules::RecursiveModuleLoad; use crate::modules::RecursiveModuleLoad;
use crate::CoreIsolate;
pub type ModuleId = i32; use crate::StartupData;
pub type ModuleLoadId = i32;
/// More specialized version of `CoreIsolate` that provides loading /// More specialized version of `CoreIsolate` that provides loading
/// and execution of ES Modules. /// and execution of ES Modules.
@ -597,11 +596,11 @@ impl Future for EsIsolate {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::isolate::js_check; use crate::core_isolate::tests::run_in_task;
use crate::isolate::tests::run_in_task; use crate::js_check;
use crate::isolate::ZeroCopyBuf;
use crate::modules::ModuleSourceFuture; use crate::modules::ModuleSourceFuture;
use crate::ops::*; use crate::ops::*;
use crate::ZeroCopyBuf;
use std::io; use std::io;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;

View file

@ -8,30 +8,44 @@ extern crate lazy_static;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
mod any_error;
mod bindings; mod bindings;
mod core_isolate;
mod errors;
mod es_isolate; mod es_isolate;
mod flags; mod flags;
mod isolate;
mod js_errors;
mod module_specifier; mod module_specifier;
mod modules; mod modules;
mod ops; mod ops;
pub mod plugin_api; pub mod plugin_api;
mod resources; mod resources;
mod shared_queue; mod shared_queue;
mod zero_copy_buf;
pub use rusty_v8 as v8; pub use rusty_v8 as v8;
pub use crate::any_error::*; pub use crate::core_isolate::js_check;
pub use crate::es_isolate::*; pub use crate::core_isolate::CoreIsolate;
pub use crate::core_isolate::Script;
pub use crate::core_isolate::Snapshot;
pub use crate::core_isolate::StartupData;
pub use crate::errors::ErrBox;
pub use crate::errors::JSError;
pub use crate::es_isolate::EsIsolate;
pub use crate::flags::v8_set_flags; pub use crate::flags::v8_set_flags;
pub use crate::isolate::*; pub use crate::module_specifier::ModuleResolutionError;
pub use crate::js_errors::*; pub use crate::module_specifier::ModuleSpecifier;
pub use crate::module_specifier::*; pub use crate::modules::ModuleId;
pub use crate::modules::*; pub use crate::modules::ModuleLoadId;
pub use crate::ops::*; pub use crate::modules::ModuleLoader;
pub use crate::resources::*; pub use crate::modules::ModuleSource;
pub use crate::modules::ModuleSourceFuture;
pub use crate::modules::RecursiveModuleLoad;
pub use crate::ops::Buf;
pub use crate::ops::Op;
pub use crate::ops::OpAsyncFuture;
pub use crate::ops::OpId;
pub use crate::resources::ResourceTable;
pub use crate::zero_copy_buf::ZeroCopyBuf;
pub fn v8_version() -> &'static str { pub fn v8_version() -> &'static str {
v8::V8::get_version() v8::V8::get_version()

View file

@ -2,10 +2,8 @@
use rusty_v8 as v8; use rusty_v8 as v8;
use crate::any_error::ErrBox;
use crate::es_isolate::ModuleId;
use crate::es_isolate::ModuleLoadId;
use crate::module_specifier::ModuleSpecifier; use crate::module_specifier::ModuleSpecifier;
use crate::ErrBox;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::stream::Stream; use futures::stream::Stream;
@ -25,6 +23,9 @@ lazy_static! {
pub static ref NEXT_LOAD_ID: AtomicI32 = AtomicI32::new(0); pub static ref NEXT_LOAD_ID: AtomicI32 = AtomicI32::new(0);
} }
pub type ModuleId = i32;
pub type ModuleLoadId = i32;
/// EsModule source code that will be loaded into V8. /// EsModule source code that will be loaded into V8.
/// ///
/// Users can implement `Into<ModuleInfo>` for different file types that /// Users can implement `Into<ModuleInfo>` for different file types that
@ -548,7 +549,8 @@ macro_rules! include_crate_modules {
mod tests { mod tests {
use super::*; use super::*;
use crate::es_isolate::EsIsolate; use crate::es_isolate::EsIsolate;
use crate::isolate::js_check; use crate::js_check;
use crate::StartupData;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
@ -556,6 +558,12 @@ mod tests {
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
// TODO(ry) Sadly FuturesUnordered requires the current task to be set. So
// even though we are only using poll() in these tests and not Tokio, we must
// nevertheless run it in the tokio executor. Ideally run_in_task can be
// removed in the future.
use crate::core_isolate::tests::run_in_task;
struct MockLoader { struct MockLoader {
pub loads: Arc<Mutex<Vec<String>>>, pub loads: Arc<Mutex<Vec<String>>>,
} }
@ -716,13 +724,6 @@ mod tests {
if (import.meta.url != 'file:///d.js') throw Error(); if (import.meta.url != 'file:///d.js') throw Error();
"#; "#;
// TODO(ry) Sadly FuturesUnordered requires the current task to be set. So
// even though we are only using poll() in these tests and not Tokio, we must
// nevertheless run it in the tokio executor. Ideally run_in_task can be
// removed in the future.
use crate::isolate::tests::run_in_task;
use crate::isolate::StartupData;
#[test] #[test]
fn test_recursive_load() { fn test_recursive_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();

67
core/zero_copy_buf.rs Normal file
View file

@ -0,0 +1,67 @@
use crate::bindings;
use rusty_v8 as v8;
use std::ops::Deref;
use std::ops::DerefMut;
/// A ZeroCopyBuf encapsulates a slice that's been borrowed from a JavaScript
/// ArrayBuffer object. JavaScript objects can normally be garbage collected,
/// but the existence of a ZeroCopyBuf inhibits this until it is dropped. It
/// behaves much like an Arc<[u8]>, although a ZeroCopyBuf currently can't be
/// cloned.
pub struct ZeroCopyBuf {
backing_store: v8::SharedRef<v8::BackingStore>,
byte_offset: usize,
byte_length: usize,
}
unsafe impl Send for ZeroCopyBuf {}
impl ZeroCopyBuf {
pub fn new(view: v8::Local<v8::ArrayBufferView>) -> Self {
let backing_store = view.buffer().unwrap().get_backing_store();
let byte_offset = view.byte_offset();
let byte_length = view.byte_length();
Self {
backing_store,
byte_offset,
byte_length,
}
}
}
impl Deref for ZeroCopyBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
bindings::get_backing_store_slice(
&self.backing_store,
self.byte_offset,
self.byte_length,
)
}
}
}
impl DerefMut for ZeroCopyBuf {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
bindings::get_backing_store_slice_mut(
&self.backing_store,
self.byte_offset,
self.byte_length,
)
}
}
}
impl AsRef<[u8]> for ZeroCopyBuf {
fn as_ref(&self) -> &[u8] {
&*self
}
}
impl AsMut<[u8]> for ZeroCopyBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut *self
}
}