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:
parent
43b3438cb1
commit
9a72f62bd6
16 changed files with 1262 additions and 178 deletions
|
@ -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
|
||||||
|
|
|
@ -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
1190
src/data.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||||
|
|
17
src/lib.rs
17
src/lib.rs
|
@ -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;
|
|
||||||
|
|
23
src/local.rs
23
src/local.rs
|
@ -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>());
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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>(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue