0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-12-25 00:29:14 -05:00

Add complete V8 type hierarchy (#148)

This commit is contained in:
Bert Belder 2019-12-30 15:28:39 +01:00
parent 43b3438cb1
commit 9a72f62bd6
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
16 changed files with 1262 additions and 178 deletions

View file

@ -4,6 +4,7 @@ use crate::support::Opaque;
use crate::support::Shared; use crate::support::Shared;
use crate::support::SharedRef; use crate::support::SharedRef;
use crate::support::UniqueRef; use crate::support::UniqueRef;
use crate::ArrayBuffer;
use crate::InIsolate; use crate::InIsolate;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
@ -146,10 +147,6 @@ impl Shared for BackingStore {
} }
} }
/// An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5).
#[repr(C)]
pub struct ArrayBuffer(Opaque);
impl ArrayBuffer { impl ArrayBuffer {
/// Create a new ArrayBuffer. Allocate |byte_length| bytes. /// Create a new ArrayBuffer. Allocate |byte_length| bytes.
/// Allocated memory will be owned by a created ArrayBuffer and /// Allocated memory will be owned by a created ArrayBuffer and

View file

@ -2,8 +2,8 @@ use std::convert::TryInto;
use std::ops::Deref; use std::ops::Deref;
use crate::support::int; use crate::support::int;
use crate::support::Opaque;
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::ArrayBufferView;
use crate::Local; use crate::Local;
use crate::Object; use crate::Object;
@ -20,11 +20,6 @@ extern "C" {
) -> usize; ) -> usize;
} }
/// A base class for an instance of one of "views" over ArrayBuffer,
/// including TypedArrays and DataView (ES6 draft 15.13).
#[repr(C)]
pub struct ArrayBufferView(Opaque);
impl ArrayBufferView { impl ArrayBufferView {
/// Returns underlying ArrayBuffer. /// Returns underlying ArrayBuffer.
pub fn buffer<'sc>(&self) -> Option<Local<'sc, ArrayBuffer>> { pub fn buffer<'sc>(&self) -> Option<Local<'sc, ArrayBuffer>> {

1190
src/data.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,8 @@ use std::mem::MaybeUninit;
use crate::support::{int, Opaque}; use crate::support::{int, Opaque};
use crate::Context; use crate::Context;
use crate::Function;
use crate::FunctionTemplate;
use crate::InIsolate; use crate::InIsolate;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
@ -117,29 +119,6 @@ impl FunctionCallbackInfo {
} }
} }
/// A FunctionTemplate is used to create functions at runtime. There
/// can only be one function created from a FunctionTemplate in a
/// context. The lifetime of the created function is equal to the
/// lifetime of the context. So in case the embedder needs to create
/// temporary functions that can be collected using Scripts is
/// preferred.
///
/// Any modification of a FunctionTemplate after first instantiation will trigger
/// a crash.
///
/// A FunctionTemplate can have properties, these properties are added to the
/// function object when it is created.
///
/// A FunctionTemplate has a corresponding instance template which is
/// used to create object instances when the function is used as a
/// constructor. Properties added to the instance template are added to
/// each object instance.
///
/// A FunctionTemplate can have a prototype template. The prototype template
/// is used to create the prototype object of the function.
#[repr(C)]
pub struct FunctionTemplate(Opaque);
impl FunctionTemplate { impl FunctionTemplate {
/// Creates a function template. /// Creates a function template.
pub fn new<'sc>( pub fn new<'sc>(
@ -163,10 +142,6 @@ impl FunctionTemplate {
} }
} }
/// A JavaScript function object (ECMA-262, 15.3).
#[repr(C)]
pub struct Function(Opaque);
impl Function { impl Function {
// TODO: add remaining arguments from C++ // TODO: add remaining arguments from C++
/// Create a function in the current execution context /// Create a function in the current execution context

View file

@ -44,6 +44,7 @@ extern crate libc;
mod array_buffer; mod array_buffer;
mod callback_scope; mod callback_scope;
mod context; mod context;
mod data;
mod exception; mod exception;
mod external_references; mod external_references;
mod function; mod function;
@ -83,35 +84,25 @@ pub mod V8;
pub use array_buffer::*; pub use array_buffer::*;
pub use callback_scope::CallbackScope; pub use callback_scope::CallbackScope;
pub use context::Context; pub use context::Context;
pub use data::*;
pub use exception::*; pub use exception::*;
pub use external_references::ExternalReferences; pub use external_references::ExternalReferences;
pub use function::{ pub use function::{FunctionCallbackInfo, ReturnValue};
Function, FunctionCallbackInfo, FunctionTemplate, ReturnValue,
};
pub use global::Global; pub use global::Global;
pub use handle_scope::{EscapableHandleScope, HandleScope, ToLocal}; pub use handle_scope::{EscapableHandleScope, HandleScope, ToLocal};
pub use isolate::*; pub use isolate::*;
pub use local::Local; pub use local::Local;
pub use locker::Locker; pub use locker::Locker;
pub use module::*; pub use module::*;
pub use number::{Integer, Number};
pub use object::Object;
pub use primitive_array::PrimitiveArray; pub use primitive_array::PrimitiveArray;
pub use primitives::*; pub use primitives::*;
pub use promise::{ pub use promise::{PromiseRejectEvent, PromiseRejectMessage, PromiseState};
Promise, PromiseRejectEvent, PromiseRejectMessage, PromiseResolver,
PromiseState,
};
pub use property::PropertyCallbackInfo; pub use property::PropertyCallbackInfo;
pub use script::{Script, ScriptOrigin}; pub use script::{Script, ScriptOrigin};
pub use script_or_module::ScriptOrModule; pub use script_or_module::ScriptOrModule;
pub use shared_array_buffer::SharedArrayBuffer;
pub use snapshot::{FunctionCodeHandling, SnapshotCreator, StartupData}; pub use snapshot::{FunctionCodeHandling, SnapshotCreator, StartupData};
pub use string::NewStringType; pub use string::NewStringType;
pub use string::String;
pub use support::MaybeBool; pub use support::MaybeBool;
pub use support::SharedRef; pub use support::SharedRef;
pub use support::UniqueRef; pub use support::UniqueRef;
pub use try_catch::{TryCatch, TryCatchScope}; pub use try_catch::{TryCatch, TryCatchScope};
pub use uint8_array::Uint8Array;
pub use value::Value;

View file

@ -1,5 +1,5 @@
use crate::value::Value;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::ptr::NonNull; use std::ptr::NonNull;
@ -49,6 +49,15 @@ impl<'sc, T> Clone for Local<'sc, T> {
} }
impl<'sc, T> Local<'sc, T> { impl<'sc, T> Local<'sc, T> {
/// Create a local handle by downcasting from one of its super types.
/// This function is unsafe because the cast is unchecked.
pub unsafe fn cast<A>(other: Local<'sc, A>) -> Self
where
Local<'sc, A>: From<Self>,
{
transmute(other)
}
pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option<Self> { pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
Some(Self(NonNull::new(ptr)?, PhantomData)) Some(Self(NonNull::new(ptr)?, PhantomData))
} }
@ -75,19 +84,9 @@ impl<'sc, T> DerefMut for Local<'sc, T> {
} }
} }
// TODO make it possible for targets other than Local<Value>. For example
// Local<String> should be able to be down cast to Local<Name>.
impl<'sc, T> From<Local<'sc, T>> for Local<'sc, Value>
where
T: Deref<Target = Value>,
{
fn from(v: Local<'sc, T>) -> Local<'sc, Value> {
unsafe { std::mem::transmute(v) }
}
}
#[test] #[test]
fn test_size_of_local() { fn test_size_of_local() {
use crate::Value;
use std::mem::size_of; use std::mem::size_of;
assert_eq!(size_of::<Local<Value>>(), size_of::<*const Value>()); assert_eq!(size_of::<Local<Value>>(), size_of::<*const Value>());
assert_eq!(size_of::<Option<Local<Value>>>(), size_of::<*const Value>()); assert_eq!(size_of::<Option<Local<Value>>>(), size_of::<*const Value>());

View file

@ -1,8 +1,8 @@
use crate::support::int; use crate::support::int;
use crate::support::MaybeBool; use crate::support::MaybeBool;
use crate::support::Opaque;
use crate::Context; use crate::Context;
use crate::Local; use crate::Local;
use crate::Module;
use crate::String; use crate::String;
use crate::ToLocal; use crate::ToLocal;
use crate::Value; use crate::Value;
@ -75,10 +75,6 @@ pub enum ModuleStatus {
Errored, Errored,
} }
/// A compiled JavaScript module.
#[repr(C)]
pub struct Module(Opaque);
impl Module { impl Module {
/// Returns the module's current status. /// Returns the module's current status.
pub fn get_status(&self) -> ModuleStatus { pub fn get_status(&self) -> ModuleStatus {

View file

@ -1,10 +1,11 @@
use std::ops::Deref; use std::ops::Deref;
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::support::Opaque; use crate::Integer;
use crate::value::Value;
use crate::Local; use crate::Local;
use crate::Number;
use crate::ToLocal; use crate::ToLocal;
use crate::Value;
extern "C" { extern "C" {
fn v8__Number__New(isolate: *mut Isolate, value: f64) -> *mut Number; fn v8__Number__New(isolate: *mut Isolate, value: f64) -> *mut Number;
@ -17,10 +18,6 @@ extern "C" {
fn v8__Integer__Value(this: *const Integer) -> i64; fn v8__Integer__Value(this: *const Integer) -> i64;
} }
/// A JavaScript number value (ECMA-262, 4.3.20)
#[repr(C)]
pub struct Number(Opaque);
impl Number { impl Number {
pub fn new<'sc>( pub fn new<'sc>(
scope: &mut impl ToLocal<'sc>, scope: &mut impl ToLocal<'sc>,
@ -42,10 +39,6 @@ impl Deref for Number {
} }
} }
/// A JavaScript value representing a signed integer.
#[repr(C)]
pub struct Integer(Opaque);
impl Integer { impl Integer {
pub fn new<'sc>( pub fn new<'sc>(
scope: &mut impl ToLocal<'sc>, scope: &mut impl ToLocal<'sc>,

View file

@ -2,17 +2,13 @@ use std::ops::Deref;
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::support::MaybeBool; use crate::support::MaybeBool;
use crate::support::Opaque;
use crate::Context; use crate::Context;
use crate::Local; use crate::Local;
use crate::Name; use crate::Name;
use crate::Object;
use crate::ToLocal; use crate::ToLocal;
use crate::Value; use crate::Value;
/// A JavaScript object (ECMA-262, 4.3.3)
#[repr(C)]
pub struct Object(Opaque);
extern "C" { extern "C" {
fn v8__Object__New(isolate: *mut Isolate) -> *mut Object; fn v8__Object__New(isolate: *mut Isolate) -> *mut Object;
fn v8__Object__New2( fn v8__Object__New2(

View file

@ -1,24 +1,13 @@
use std::ops::Deref; use std::ops::Deref;
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::support::Opaque; use crate::Boolean;
use crate::Local; use crate::Local;
use crate::Name;
use crate::Primitive;
use crate::ToLocal; use crate::ToLocal;
use crate::Value; use crate::Value;
/// The superclass of primitive values. See ECMA-262 4.3.2.
#[repr(C)]
pub struct Primitive(Opaque);
/// A primitive boolean value (ECMA-262, 4.3.14). Either the true
/// or false value.
#[repr(C)]
pub struct Boolean(Opaque);
/// A superclass for symbols and strings.
#[repr(C)]
pub struct Name(Opaque);
extern "C" { extern "C" {
fn v8__Null(isolate: *mut Isolate) -> *mut Primitive; fn v8__Null(isolate: *mut Isolate) -> *mut Primitive;

View file

@ -1,10 +1,11 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::support::MaybeBool; use crate::support::MaybeBool;
use crate::support::Opaque;
use crate::Context; use crate::Context;
use crate::Function; use crate::Function;
use crate::Local; use crate::Local;
use crate::Promise;
use crate::PromiseResolver;
use crate::ToLocal; use crate::ToLocal;
use crate::Value; use crate::Value;
@ -62,10 +63,6 @@ pub enum PromiseState {
Rejected, Rejected,
} }
/// An instance of the built-in Promise constructor (ES6 draft).
#[repr(C)]
pub struct Promise(Opaque);
impl Promise { impl Promise {
/// Returns the value of the [[PromiseState]] field. /// Returns the value of the [[PromiseState]] field.
pub fn state(&mut self) -> PromiseState { pub fn state(&mut self) -> PromiseState {
@ -142,9 +139,6 @@ impl Promise {
} }
} }
#[repr(C)]
pub struct PromiseResolver(Opaque);
impl PromiseResolver { impl PromiseResolver {
/// Create a new resolver, along with an associated promise in pending state. /// Create a new resolver, along with an associated promise in pending state.
pub fn new<'sc>( pub fn new<'sc>(

View file

@ -1,10 +1,10 @@
use std::ops::Deref; use std::ops::Deref;
use crate::support::Opaque;
use crate::support::SharedRef; use crate::support::SharedRef;
use crate::BackingStore; use crate::BackingStore;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::SharedArrayBuffer;
use crate::ToLocal; use crate::ToLocal;
use crate::Value; use crate::Value;
@ -21,11 +21,6 @@ extern "C" {
) -> SharedRef<BackingStore>; ) -> SharedRef<BackingStore>;
} }
/// An instance of the built-in SharedArrayBuffer constructor.
/// This API is experimental and may change significantly.
#[repr(C)]
pub struct SharedArrayBuffer(Opaque);
impl SharedArrayBuffer { impl SharedArrayBuffer {
/// Create a new SharedArrayBuffer. Allocate |byte_length| bytes. /// Create a new SharedArrayBuffer. Allocate |byte_length| bytes.
/// Allocated memory will be owned by a created SharedArrayBuffer and /// Allocated memory will be owned by a created SharedArrayBuffer and

View file

@ -6,10 +6,10 @@ use std::slice;
use crate::support::char; use crate::support::char;
use crate::support::int; use crate::support::int;
use crate::support::Opaque;
use crate::InIsolate; use crate::InIsolate;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
use crate::String;
use crate::ToLocal; use crate::ToLocal;
use crate::Value; use crate::Value;
@ -62,10 +62,6 @@ bitflags! {
} }
} }
/// A JavaScript string value (ECMA-262, 4.3.17).
#[repr(C)]
pub struct String(Opaque);
impl String { impl String {
pub fn new_from_utf8<'sc>( pub fn new_from_utf8<'sc>(
scope: &mut impl ToLocal<'sc>, scope: &mut impl ToLocal<'sc>,

View file

@ -1,8 +1,8 @@
use std::ops::DerefMut; use std::ops::DerefMut;
use crate::support::Opaque;
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::Local; use crate::Local;
use crate::Uint8Array;
extern "C" { extern "C" {
fn v8__Uint8Array__New( fn v8__Uint8Array__New(
@ -12,10 +12,6 @@ extern "C" {
) -> *mut Uint8Array; ) -> *mut Uint8Array;
} }
/// An instance of Uint8Array constructor (ES6 draft 15.13.6).
#[repr(C)]
pub struct Uint8Array(Opaque);
impl Uint8Array { impl Uint8Array {
pub fn new<'sc>( pub fn new<'sc>(
mut buf: Local<ArrayBuffer>, mut buf: Local<ArrayBuffer>,

View file

@ -1,5 +1,5 @@
use crate::support;
use crate::Local; use crate::Local;
use crate::Value;
extern "C" { extern "C" {
fn v8__Value__IsUndefined(this: &Value) -> bool; fn v8__Value__IsUndefined(this: &Value) -> bool;
@ -14,10 +14,6 @@ extern "C" {
fn v8__Value__SameValue(this: &Value, that: &Value) -> bool; fn v8__Value__SameValue(this: &Value, that: &Value) -> bool;
} }
/// The superclass of all JavaScript values and objects.
#[repr(C)]
pub struct Value(support::Opaque);
impl Value { impl Value {
/// Returns true if this value is the undefined value. See ECMA-262 4.3.10. /// Returns true if this value is the undefined value. See ECMA-262 4.3.10.
pub fn is_undefined(&self) -> bool { pub fn is_undefined(&self) -> bool {

View file

@ -5,6 +5,7 @@ extern crate lazy_static;
use rusty_v8 as v8; use rusty_v8 as v8;
use rusty_v8::{new_null, FunctionCallbackInfo, InIsolate, Local, ToLocal}; use rusty_v8::{new_null, FunctionCallbackInfo, InIsolate, Local, ToLocal};
use std::convert::Into;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex; use std::sync::Mutex;
@ -165,14 +166,12 @@ fn escapable_handle_scope() {
let scope1 = hs.enter(); let scope1 = hs.enter();
// After dropping EscapableHandleScope, we should be able to // After dropping EscapableHandleScope, we should be able to
// read escaped values. // read escaped values.
let number_val = { let number = {
let mut hs = v8::EscapableHandleScope::new(scope1); let mut hs = v8::EscapableHandleScope::new(scope1);
let escapable_scope = hs.enter(); let escapable_scope = hs.enter();
let number: Local<v8::Value> = let number = v8::Number::new(escapable_scope, 78.9);
cast(v8::Number::new(escapable_scope, 78.9));
escapable_scope.escape(number) escapable_scope.escape(number)
}; };
let number: Local<v8::Number> = cast(number_val);
assert_eq!(number.value(), 78.9); assert_eq!(number.value(), 78.9);
let string = { let string = {
@ -457,7 +456,7 @@ fn set_host_initialize_import_meta_object_callback() {
let scope = hs.enter(); let scope = hs.enter();
let key = v8::String::new(scope, "foo").unwrap(); let key = v8::String::new(scope, "foo").unwrap();
let value = v8::String::new(scope, "bar").unwrap(); let value = v8::String::new(scope, "bar").unwrap();
meta.create_data_property(context, cast(key), value.into()); meta.create_data_property(context, key.into(), value.into());
} }
isolate.set_host_initialize_import_meta_object_callback(callback); isolate.set_host_initialize_import_meta_object_callback(callback);
@ -475,7 +474,7 @@ fn set_host_initialize_import_meta_object_callback() {
assert!(result.is_some()); assert!(result.is_some());
let meta = module.evaluate(s, context).unwrap(); let meta = module.evaluate(s, context).unwrap();
assert!(meta.is_object()); assert!(meta.is_object());
let meta: Local<v8::Object> = cast(meta); let meta = unsafe { Local::<v8::Object>::cast(meta) };
let key = v8::String::new(s, "foo").unwrap(); let key = v8::String::new(s, "foo").unwrap();
let expected = v8::String::new(s, "bar").unwrap(); let expected = v8::String::new(s, "bar").unwrap();
let actual = meta.get(s, context, key.into()).unwrap(); let actual = meta.get(s, context, key.into()).unwrap();
@ -698,12 +697,6 @@ fn json() {
drop(locker); drop(locker);
} }
// TODO Safer casts https://github.com/denoland/rusty_v8/issues/51
fn cast<U, T>(local: v8::Local<T>) -> v8::Local<U> {
let cast_local: v8::Local<U> = unsafe { std::mem::transmute_copy(&local) };
cast_local
}
#[test] #[test]
fn object() { fn object() {
setup(); setup();
@ -719,8 +712,8 @@ fn object() {
let null: v8::Local<v8::Value> = new_null(scope).into(); let null: v8::Local<v8::Value> = new_null(scope).into();
let s1 = v8::String::new(scope, "a").unwrap(); let s1 = v8::String::new(scope, "a").unwrap();
let s2 = v8::String::new(scope, "b").unwrap(); let s2 = v8::String::new(scope, "b").unwrap();
let name1: Local<v8::Name> = cast(s1); let name1 = s1.into();
let name2: Local<v8::Name> = cast(s2); let name2 = s2.into();
let names = vec![name1, name2]; let names = vec![name1, name2];
let v1: v8::Local<v8::Value> = v8::Number::new(scope, 1.0).into(); let v1: v8::Local<v8::Value> = v8::Number::new(scope, 1.0).into();
let v2: v8::Local<v8::Value> = v8::Number::new(scope, 2.0).into(); let v2: v8::Local<v8::Value> = v8::Number::new(scope, 2.0).into();
@ -757,22 +750,22 @@ fn create_data_property() {
.get(scope, context, key.into()) .get(scope, context, key.into())
.unwrap(); .unwrap();
assert!(obj.is_object()); assert!(obj.is_object());
let obj: Local<v8::Object> = cast(obj); let obj = unsafe { Local::<v8::Object>::cast(obj) };
let key = v8_str(scope, "foo"); let key = v8_str(scope, "foo");
let value = v8_str(scope, "bar"); let value = v8_str(scope, "bar");
assert_eq!( assert_eq!(
obj.create_data_property(context, cast(key), cast(value)), obj.create_data_property(context, key.into(), value.into()),
v8::MaybeBool::JustTrue v8::MaybeBool::JustTrue
); );
let actual = obj.get(scope, context, cast(key)).unwrap(); let actual = obj.get(scope, context, key.into()).unwrap();
assert!(value.strict_equals(actual)); assert!(value.strict_equals(actual));
let key2 = v8_str(scope, "foo2"); let key2 = v8_str(scope, "foo2");
assert_eq!( assert_eq!(
obj.set(context, cast(key2), cast(value)), obj.set(context, key2.into(), value.into()),
v8::MaybeBool::JustTrue v8::MaybeBool::JustTrue
); );
let actual = obj.get(scope, context, cast(key2)).unwrap(); let actual = obj.get(scope, context, key2.into()).unwrap();
assert!(value.strict_equals(actual)); assert!(value.strict_equals(actual));
context.exit(); context.exit();
@ -798,20 +791,18 @@ fn promise_resolved() {
let mut promise = resolver.get_promise(scope); let mut promise = resolver.get_promise(scope);
assert!(!promise.has_handler()); assert!(!promise.has_handler());
assert_eq!(promise.state(), v8::PromiseState::Pending); assert_eq!(promise.state(), v8::PromiseState::Pending);
let str = v8::String::new(scope, "test").unwrap(); let value = v8::String::new(scope, "test").unwrap();
let value: Local<v8::Value> = cast(str); resolver.resolve(context, value.into());
resolver.resolve(context, value);
assert_eq!(promise.state(), v8::PromiseState::Fulfilled); assert_eq!(promise.state(), v8::PromiseState::Fulfilled);
let result = promise.result(scope); let result = promise.result(scope);
let result_str: v8::Local<v8::String> = cast(result); let result_str = unsafe { Local::<v8::String>::cast(result) };
assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string());
// Resolve again with different value, since promise is already in `Fulfilled` state // Resolve again with different value, since promise is already in `Fulfilled` state
// it should be ignored. // it should be ignored.
let str = v8::String::new(scope, "test2").unwrap(); let value = v8::String::new(scope, "test2").unwrap();
let value: Local<v8::Value> = cast(str); resolver.resolve(context, value.into());
resolver.resolve(context, value);
let result = promise.result(scope); let result = promise.result(scope);
let result_str: v8::Local<v8::String> = cast(result); let result_str = unsafe { Local::<v8::String>::cast(result) };
assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string());
context.exit(); context.exit();
} }
@ -836,21 +827,19 @@ fn promise_rejected() {
let mut promise = resolver.get_promise(scope); let mut promise = resolver.get_promise(scope);
assert!(!promise.has_handler()); assert!(!promise.has_handler());
assert_eq!(promise.state(), v8::PromiseState::Pending); assert_eq!(promise.state(), v8::PromiseState::Pending);
let str = v8::String::new(scope, "test").unwrap(); let value = v8::String::new(scope, "test").unwrap();
let value: Local<v8::Value> = cast(str); let rejected = resolver.reject(context, value.into());
let rejected = resolver.reject(context, value);
assert!(rejected.unwrap()); assert!(rejected.unwrap());
assert_eq!(promise.state(), v8::PromiseState::Rejected); assert_eq!(promise.state(), v8::PromiseState::Rejected);
let result = promise.result(scope); let result = promise.result(scope);
let result_str: v8::Local<v8::String> = cast(result); let result_str = unsafe { Local::<v8::String>::cast(result) };
assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string());
// Reject again with different value, since promise is already in `Rejected` state // Reject again with different value, since promise is already in `Rejected` state
// it should be ignored. // it should be ignored.
let str = v8::String::new(scope, "test2").unwrap(); let value = v8::String::new(scope, "test2").unwrap();
let value: Local<v8::Value> = cast(str); resolver.reject(context, value.into());
resolver.reject(context, value);
let result = promise.result(scope); let result = promise.result(scope);
let result_str: v8::Local<v8::String> = cast(result); let result_str = unsafe { Local::<v8::String>::cast(result) };
assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string());
context.exit(); context.exit();
} }
@ -904,7 +893,7 @@ fn function() {
let maybe_value = let maybe_value =
v8::Function::call(&mut *function, scope, context, recv, 0, vec![]); v8::Function::call(&mut *function, scope, context, recv, 0, vec![]);
let value = maybe_value.unwrap(); let value = maybe_value.unwrap();
let value_str: v8::Local<v8::String> = cast(value); let value_str = unsafe { Local::<v8::String>::cast(value) };
let rust_str = value_str.to_rust_string_lossy(scope); let rust_str = value_str.to_rust_string_lossy(scope);
assert_eq!(rust_str, "Hello callback!".to_string()); assert_eq!(rust_str, "Hello callback!".to_string());
context.exit(); context.exit();
@ -917,14 +906,14 @@ extern "C" fn promise_reject_callback(msg: v8::PromiseRejectMessage) {
assert_eq!(event, v8::PromiseRejectEvent::PromiseRejectWithNoHandler); assert_eq!(event, v8::PromiseRejectEvent::PromiseRejectWithNoHandler);
let mut promise = msg.get_promise(); let mut promise = msg.get_promise();
assert_eq!(promise.state(), v8::PromiseState::Rejected); assert_eq!(promise.state(), v8::PromiseState::Rejected);
let mut promise_obj: v8::Local<v8::Object> = cast(promise); let mut promise_obj: Local<v8::Object> = promise.into();
let isolate = promise_obj.get_isolate(); let isolate = promise_obj.get_isolate();
let value = msg.get_value(); let value = msg.get_value();
let mut locker = v8::Locker::new(isolate); let mut locker = v8::Locker::new(isolate);
{ {
let mut hs = v8::HandleScope::new(&mut locker); let mut hs = v8::HandleScope::new(&mut locker);
let scope = hs.enter(); let scope = hs.enter();
let value_str: v8::Local<v8::String> = cast(value); let value_str = unsafe { Local::<v8::String>::cast(value) };
let rust_str = value_str.to_rust_string_lossy(scope); let rust_str = value_str.to_rust_string_lossy(scope);
assert_eq!(rust_str, "promise rejected".to_string()); assert_eq!(rust_str, "promise rejected".to_string());
} }
@ -946,9 +935,8 @@ fn set_promise_reject_callback() {
let mut context = v8::Context::new(scope); let mut context = v8::Context::new(scope);
context.enter(); context.enter();
let mut resolver = v8::PromiseResolver::new(scope, context).unwrap(); let mut resolver = v8::PromiseResolver::new(scope, context).unwrap();
let str_ = v8::String::new(scope, "promise rejected").unwrap(); let value = v8::String::new(scope, "promise rejected").unwrap();
let value: Local<v8::Value> = cast(str_); resolver.reject(context, value.into());
resolver.reject(context, value);
context.exit(); context.exit();
} }
drop(locker); drop(locker);
@ -1109,7 +1097,7 @@ fn compile_specifier_as_module_resolve_callback(
let source = v8::script_compiler::Source::new(specifier, &origin); let source = v8::script_compiler::Source::new(specifier, &origin);
let module = let module =
v8::script_compiler::compile_module(scope.isolate(), source).unwrap(); v8::script_compiler::compile_module(scope.isolate(), source).unwrap();
&mut *cast(scope.escape(module)) &mut *scope.escape(module)
} }
#[test] #[test]
@ -1185,12 +1173,12 @@ fn primitive_array() {
} }
let string = v8_str(scope, "test"); let string = v8_str(scope, "test");
array.set(scope, 1, cast(string)); array.set(scope, 1, string.into());
assert!(array.get(scope, 0).is_undefined()); assert!(array.get(scope, 0).is_undefined());
assert!(array.get(scope, 1).is_string()); assert!(array.get(scope, 1).is_string());
let num = v8::Number::new(scope, 0.42); let num = v8::Number::new(scope, 0.42);
array.set(scope, 2, cast(num)); array.set(scope, 2, num.into());
assert!(array.get(scope, 0).is_undefined()); assert!(array.get(scope, 0).is_undefined());
assert!(array.get(scope, 1).is_string()); assert!(array.get(scope, 1).is_string());
assert!(array.get(scope, 2).is_number()); assert!(array.get(scope, 2).is_number());
@ -1257,8 +1245,7 @@ fn array_buffer_view() {
source.to_rust_string_lossy(s); source.to_rust_string_lossy(s);
let result = script.run(s, context).unwrap(); let result = script.run(s, context).unwrap();
// TODO: safer casts. // TODO: safer casts.
let result: v8::Local<v8::array_buffer_view::ArrayBufferView> = let result = unsafe { Local::<v8::ArrayBufferView>::cast(result) };
cast(result);
assert_eq!(result.byte_length(), 4); assert_eq!(result.byte_length(), 4);
assert_eq!(result.byte_offset(), 0); assert_eq!(result.byte_offset(), 0);
let mut dest = [0; 4]; let mut dest = [0; 4];
@ -1323,7 +1310,7 @@ fn snapshot_creator() {
let mut script = let mut script =
v8::Script::compile(scope, context, source, None).unwrap(); v8::Script::compile(scope, context, source, None).unwrap();
let result = script.run(scope, context).unwrap(); let result = script.run(scope, context).unwrap();
let true_val: Local<v8::Value> = cast(v8::new_true(scope)); let true_val = v8::new_true(scope).into();
assert!(result.same_value(true_val)); assert!(result.same_value(true_val));
context.exit(); context.exit();
} }
@ -1363,7 +1350,7 @@ fn external_references() {
.expect("Unable to create function"); .expect("Unable to create function");
let global = context.global(scope); let global = context.global(scope);
global.set(context, cast(v8_str(scope, "F")), cast(function)); global.set(context, v8_str(scope, "F").into(), function.into());
snapshot_creator.set_default_context(context); snapshot_creator.set_default_context(context);
@ -1426,8 +1413,7 @@ fn uint8_array() {
source.to_rust_string_lossy(s); source.to_rust_string_lossy(s);
let result = script.run(s, context).unwrap(); let result = script.run(s, context).unwrap();
// TODO: safer casts. // TODO: safer casts.
let result: v8::Local<v8::array_buffer_view::ArrayBufferView> = let result = unsafe { Local::<v8::ArrayBufferView>::cast(result) };
cast(result);
assert_eq!(result.byte_length(), 4); assert_eq!(result.byte_length(), 4);
assert_eq!(result.byte_offset(), 0); assert_eq!(result.byte_offset(), 0);
let mut dest = [0; 4]; let mut dest = [0; 4];
@ -1520,8 +1506,8 @@ fn shared_array_buffer() {
assert_eq!( assert_eq!(
global.create_data_property( global.create_data_property(
context, context,
cast(v8_str(s, "shared")), v8_str(s, "shared").into(),
cast(sab) sab.into()
), ),
v8::MaybeBool::JustTrue v8::MaybeBool::JustTrue
); );
@ -1534,7 +1520,7 @@ fn shared_array_buffer() {
source.to_rust_string_lossy(s); source.to_rust_string_lossy(s);
let result = script.run(s, context).unwrap(); let result = script.run(s, context).unwrap();
// TODO: safer casts. // TODO: safer casts.
let result: v8::Local<v8::Integer> = cast(result); let result = unsafe { Local::<v8::Integer>::cast(result) };
assert_eq!(result.value(), 64); assert_eq!(result.value(), 64);
assert_eq!(shared_buf[2], 16); assert_eq!(shared_buf[2], 16);
assert_eq!(shared_buf[14], 62); assert_eq!(shared_buf[14], 62);