diff --git a/src/array_buffer.rs b/src/array_buffer.rs index 08bcbd59..e435dcb2 100644 --- a/src/array_buffer.rs +++ b/src/array_buffer.rs @@ -4,6 +4,7 @@ use crate::support::Opaque; use crate::support::Shared; use crate::support::SharedRef; use crate::support::UniqueRef; +use crate::ArrayBuffer; use crate::InIsolate; use crate::Isolate; 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 { /// Create a new ArrayBuffer. Allocate |byte_length| bytes. /// Allocated memory will be owned by a created ArrayBuffer and diff --git a/src/array_buffer_view.rs b/src/array_buffer_view.rs index 4927e413..ee975499 100644 --- a/src/array_buffer_view.rs +++ b/src/array_buffer_view.rs @@ -2,8 +2,8 @@ use std::convert::TryInto; use std::ops::Deref; use crate::support::int; -use crate::support::Opaque; use crate::ArrayBuffer; +use crate::ArrayBufferView; use crate::Local; use crate::Object; @@ -20,11 +20,6 @@ extern "C" { ) -> 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 { /// Returns underlying ArrayBuffer. pub fn buffer<'sc>(&self) -> Option> { diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 00000000..78dc061b --- /dev/null +++ b/src/data.rs @@ -0,0 +1,1190 @@ +use std::convert::From; +use std::mem::transmute; + +use crate::support::Opaque; +use crate::Local; + +/// The superclass of objects that can reside on V8's heap. +#[repr(C)] +pub struct Data(Opaque); + +/// An AccessorSignature specifies which receivers are valid parameters +/// to an accessor callback. +#[repr(C)] +pub struct AccessorSignature(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, AccessorSignature>) -> Self { + unsafe { transmute(l) } + } +} + +/// A compiled JavaScript module. +#[repr(C)] +pub struct Module(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Module>) -> Self { + unsafe { transmute(l) } + } +} + +/// A private symbol +/// +/// This is an experimental feature. Use at your own risk. +#[repr(C)] +pub struct Private(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Private>) -> Self { + unsafe { transmute(l) } + } +} + +/// A Signature specifies which receiver is valid for a function. +/// +/// A receiver matches a given signature if the receiver (or any of its +/// hidden prototypes) was created from the signature's FunctionTemplate, or +/// from a FunctionTemplate that inherits directly or indirectly from the +/// signature's FunctionTemplate. +#[repr(C)] +pub struct Signature(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Signature>) -> Self { + unsafe { transmute(l) } + } +} + +/// The superclass of object and function templates. +#[repr(C)] +pub struct Template(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Template>) -> Self { + unsafe { transmute(l) } + } +} + +/// 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. +/// +/// The following example shows how to use a FunctionTemplate: +/// +/// ```ignore +/// v8::Local t = v8::FunctionTemplate::New(isolate); +/// t->Set(isolate, "func_property", v8::Number::New(isolate, 1)); +/// +/// v8::Local proto_t = t->PrototypeTemplate(); +/// proto_t->Set(isolate, +/// "proto_method", +/// v8::FunctionTemplate::New(isolate, InvokeCallback)); +/// proto_t->Set(isolate, "proto_const", v8::Number::New(isolate, 2)); +/// +/// v8::Local instance_t = t->InstanceTemplate(); +/// instance_t->SetAccessor(String::NewFromUtf8(isolate, "instance_accessor"), +/// InstanceAccessorCallback); +/// instance_t->SetHandler( +/// NamedPropertyHandlerConfiguration(PropertyHandlerCallback)); +/// instance_t->Set(String::NewFromUtf8(isolate, "instance_property"), +/// Number::New(isolate, 3)); +/// +/// v8::Local function = t->GetFunction(); +/// v8::Local instance = function->NewInstance(); +/// ``` +/// +/// Let's use "function" as the JS variable name of the function object +/// and "instance" for the instance object created above. The function +/// and the instance will have the following properties: +/// +/// ```ignore +/// func_property in function == true; +/// function.func_property == 1; +/// +/// function.prototype.proto_method() invokes 'InvokeCallback' +/// function.prototype.proto_const == 2; +/// +/// instance instanceof function == true; +/// instance.instance_accessor calls 'InstanceAccessorCallback' +/// instance.instance_property == 3; +/// ``` +/// +/// A FunctionTemplate can inherit from another one by calling the +/// FunctionTemplate::Inherit method. The following graph illustrates +/// the semantics of inheritance: +/// +/// ```ignore +/// FunctionTemplate Parent -> Parent() . prototype -> { } +/// ^ ^ +/// | Inherit(Parent) | .__proto__ +/// | | +/// FunctionTemplate Child -> Child() . prototype -> { } +/// ``` +/// +/// A FunctionTemplate 'Child' inherits from 'Parent', the prototype +/// object of the Child() function has __proto__ pointing to the +/// Parent() function's prototype object. An instance of the Child +/// function has all properties on Parent's instance templates. +/// +/// Let Parent be the FunctionTemplate initialized in the previous +/// section and create a Child FunctionTemplate by: +/// +/// ```ignore +/// Local parent = t; +/// Local child = FunctionTemplate::New(); +/// child->Inherit(parent); +/// +/// Local child_function = child->GetFunction(); +/// Local child_instance = child_function->NewInstance(); +/// ``` +/// +/// The Child function and Child instance will have the following +/// properties: +/// +/// ```ignore +/// child_func.prototype.__proto__ == function.prototype; +/// child_instance.instance_accessor calls 'InstanceAccessorCallback' +/// child_instance.instance_property == 3; +/// ``` +#[repr(C)] +pub struct FunctionTemplate(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, FunctionTemplate>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Template> { + fn from(l: Local<'sc, FunctionTemplate>) -> Self { + unsafe { transmute(l) } + } +} + +/// An ObjectTemplate is used to create objects at runtime. +/// +/// Properties added to an ObjectTemplate are added to each object +/// created from the ObjectTemplate. +#[repr(C)] +pub struct ObjectTemplate(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, ObjectTemplate>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Template> { + fn from(l: Local<'sc, ObjectTemplate>) -> Self { + unsafe { transmute(l) } + } +} + +/// A compiled JavaScript module, not yet tied to a Context. +#[repr(C)] +pub struct UnboundModuleScript(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, UnboundModuleScript>) -> Self { + unsafe { transmute(l) } + } +} + +/// The superclass of all JavaScript values and objects. +#[repr(C)] +pub struct Value(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Value>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript value that wraps a C++ void*. This type of value is mainly used +/// to associate C++ data structures with JavaScript objects. +#[repr(C)] +pub struct External(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, External>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, External>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript object (ECMA-262, 4.3.3) +#[repr(C)] +pub struct Object(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Object>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Object>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in array constructor (ECMA-262, 15.4.2). +#[repr(C)] +pub struct Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5). +#[repr(C)] +pub struct ArrayBuffer(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, ArrayBuffer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, ArrayBuffer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, ArrayBuffer>) -> Self { + unsafe { transmute(l) } + } +} + +/// 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<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, ArrayBufferView>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, ArrayBufferView>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, ArrayBufferView>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of DataView constructor (ES6 draft 15.13.7). +#[repr(C)] +pub struct DataView(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, DataView>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, DataView>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, DataView>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, DataView>) -> Self { + unsafe { transmute(l) } + } +} + +/// A base class for an instance of TypedArray series of constructors +/// (ES6 draft 15.13.6). +#[repr(C)] +pub struct TypedArray(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, TypedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, TypedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, TypedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, TypedArray>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of BigInt64Array constructor. +#[repr(C)] +pub struct BigInt64Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, BigInt64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, BigInt64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, BigInt64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, BigInt64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, BigInt64Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of BigUint64Array constructor. +#[repr(C)] +pub struct BigUint64Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, BigUint64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, BigUint64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, BigUint64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, BigUint64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, BigUint64Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Float32Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Float32Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Float32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Float32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Float32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Float32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Float32Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Float64Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Float64Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Float64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Float64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Float64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Float64Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Float64Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Int16Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Int16Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Int16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Int16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Int16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Int16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Int16Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Int32Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Int32Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Int32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Int32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Int32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Int32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Int32Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Int8Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Int8Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Int8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Int8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Int8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Int8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Int8Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Uint16Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Uint16Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Uint16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Uint16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Uint16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Uint16Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Uint16Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Uint32Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Uint32Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Uint32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Uint32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Uint32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Uint32Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Uint32Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Uint8Array constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Uint8Array(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Uint8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Uint8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Uint8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Uint8Array>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Uint8Array>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of Uint8ClampedArray constructor (ES6 draft 15.13.6). +#[repr(C)] +pub struct Uint8ClampedArray(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Uint8ClampedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Uint8ClampedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Uint8ClampedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, ArrayBufferView> { + fn from(l: Local<'sc, Uint8ClampedArray>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, TypedArray> { + fn from(l: Local<'sc, Uint8ClampedArray>) -> Self { + unsafe { transmute(l) } + } +} + +/// A BigInt object (https://tc39.github.io/proposal-bigint) +#[repr(C)] +pub struct BigIntObject(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, BigIntObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, BigIntObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, BigIntObject>) -> Self { + unsafe { transmute(l) } + } +} + +/// A Boolean object (ECMA-262, 4.3.15). +#[repr(C)] +pub struct BooleanObject(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, BooleanObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, BooleanObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, BooleanObject>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in Date constructor (ECMA-262, 15.9). +#[repr(C)] +pub struct Date(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Date>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Date>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Date>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in FinalizationGroup constructor. +/// +/// This API is experimental and may change significantly. +#[repr(C)] +pub struct FinalizationGroup(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, FinalizationGroup>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, FinalizationGroup>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, FinalizationGroup>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript function object (ECMA-262, 15.3). +#[repr(C)] +pub struct Function(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Function>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Function>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Function>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in Map constructor (ECMA-262, 6th Edition, 23.1.1). +#[repr(C)] +pub struct Map(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Map>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Map>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Map>) -> Self { + unsafe { transmute(l) } + } +} + +/// A Number object (ECMA-262, 4.3.21). +#[repr(C)] +pub struct NumberObject(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, NumberObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, NumberObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, NumberObject>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in Promise constructor (ES6 draft). +#[repr(C)] +pub struct Promise(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Promise>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Promise>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Promise>) -> Self { + unsafe { transmute(l) } + } +} + +#[repr(C)] +pub struct PromiseResolver(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, PromiseResolver>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, PromiseResolver>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, PromiseResolver>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in Proxy constructor (ECMA-262, 6th Edition, +/// 26.2.1). +#[repr(C)] +pub struct Proxy(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Proxy>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Proxy>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Proxy>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in RegExp constructor (ECMA-262, 15.10). +#[repr(C)] +pub struct RegExp(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, RegExp>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, RegExp>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, RegExp>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in Set constructor (ECMA-262, 6th Edition, 23.2.1). +#[repr(C)] +pub struct Set(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Set>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Set>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, Set>) -> Self { + unsafe { transmute(l) } + } +} + +/// An instance of the built-in SharedArrayBuffer constructor. +/// This API is experimental and may change significantly. +#[repr(C)] +pub struct SharedArrayBuffer(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, SharedArrayBuffer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, SharedArrayBuffer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, SharedArrayBuffer>) -> Self { + unsafe { transmute(l) } + } +} + +/// A String object (ECMA-262, 4.3.18). +#[repr(C)] +pub struct StringObject(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, StringObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, StringObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, StringObject>) -> Self { + unsafe { transmute(l) } + } +} + +/// A Symbol object (ECMA-262 edition 6). +#[repr(C)] +pub struct SymbolObject(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, SymbolObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, SymbolObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, SymbolObject>) -> Self { + unsafe { transmute(l) } + } +} + +#[repr(C)] +pub struct WasmModuleObject(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, WasmModuleObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, WasmModuleObject>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Object> { + fn from(l: Local<'sc, WasmModuleObject>) -> Self { + unsafe { transmute(l) } + } +} + +/// The superclass of primitive values. See ECMA-262 4.3.2. +#[repr(C)] +pub struct Primitive(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Primitive>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Primitive>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript BigInt value (https://tc39.github.io/proposal-bigint) +#[repr(C)] +pub struct BigInt(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, BigInt>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, BigInt>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, BigInt>) -> Self { + unsafe { transmute(l) } + } +} + +/// A primitive boolean value (ECMA-262, 4.3.14). Either the true +/// or false value. +#[repr(C)] +pub struct Boolean(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Boolean>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Boolean>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Boolean>) -> Self { + unsafe { transmute(l) } + } +} + +/// A superclass for symbols and strings. +#[repr(C)] +pub struct Name(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Name>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Name>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Name>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript string value (ECMA-262, 4.3.17). +#[repr(C)] +pub struct String(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, String>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, String>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, String>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Name> { + fn from(l: Local<'sc, String>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript symbol (ECMA-262 edition 6) +#[repr(C)] +pub struct Symbol(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Symbol>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Symbol>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Symbol>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Name> { + fn from(l: Local<'sc, Symbol>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript number value (ECMA-262, 4.3.20) +#[repr(C)] +pub struct Number(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Number>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Number>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Number>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript value representing a signed integer. +#[repr(C)] +pub struct Integer(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Integer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Integer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Integer>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Number> { + fn from(l: Local<'sc, Integer>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript value representing a 32-bit signed integer. +#[repr(C)] +pub struct Int32(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Int32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Int32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Int32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Number> { + fn from(l: Local<'sc, Int32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Integer> { + fn from(l: Local<'sc, Int32>) -> Self { + unsafe { transmute(l) } + } +} + +/// A JavaScript value representing a 32-bit unsigned integer. +#[repr(C)] +pub struct Uint32(Opaque); +impl<'sc> From> for Local<'sc, Data> { + fn from(l: Local<'sc, Uint32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Value> { + fn from(l: Local<'sc, Uint32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Primitive> { + fn from(l: Local<'sc, Uint32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Number> { + fn from(l: Local<'sc, Uint32>) -> Self { + unsafe { transmute(l) } + } +} +impl<'sc> From> for Local<'sc, Integer> { + fn from(l: Local<'sc, Uint32>) -> Self { + unsafe { transmute(l) } + } +} diff --git a/src/function.rs b/src/function.rs index 0ae3f904..de614bd3 100644 --- a/src/function.rs +++ b/src/function.rs @@ -3,6 +3,8 @@ use std::mem::MaybeUninit; use crate::support::{int, Opaque}; use crate::Context; +use crate::Function; +use crate::FunctionTemplate; use crate::InIsolate; use crate::Isolate; 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 { /// Creates a function template. 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 { // TODO: add remaining arguments from C++ /// Create a function in the current execution context diff --git a/src/lib.rs b/src/lib.rs index 66317de0..3178c310 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,7 @@ extern crate libc; mod array_buffer; mod callback_scope; mod context; +mod data; mod exception; mod external_references; mod function; @@ -83,35 +84,25 @@ pub mod V8; pub use array_buffer::*; pub use callback_scope::CallbackScope; pub use context::Context; +pub use data::*; pub use exception::*; pub use external_references::ExternalReferences; -pub use function::{ - Function, FunctionCallbackInfo, FunctionTemplate, ReturnValue, -}; +pub use function::{FunctionCallbackInfo, ReturnValue}; pub use global::Global; pub use handle_scope::{EscapableHandleScope, HandleScope, ToLocal}; pub use isolate::*; pub use local::Local; pub use locker::Locker; pub use module::*; -pub use number::{Integer, Number}; -pub use object::Object; pub use primitive_array::PrimitiveArray; pub use primitives::*; -pub use promise::{ - Promise, PromiseRejectEvent, PromiseRejectMessage, PromiseResolver, - PromiseState, -}; +pub use promise::{PromiseRejectEvent, PromiseRejectMessage, PromiseState}; pub use property::PropertyCallbackInfo; pub use script::{Script, ScriptOrigin}; pub use script_or_module::ScriptOrModule; -pub use shared_array_buffer::SharedArrayBuffer; pub use snapshot::{FunctionCodeHandling, SnapshotCreator, StartupData}; pub use string::NewStringType; -pub use string::String; pub use support::MaybeBool; pub use support::SharedRef; pub use support::UniqueRef; pub use try_catch::{TryCatch, TryCatchScope}; -pub use uint8_array::Uint8Array; -pub use value::Value; diff --git a/src/local.rs b/src/local.rs index e13dbf08..0a2a8c52 100644 --- a/src/local.rs +++ b/src/local.rs @@ -1,5 +1,5 @@ -use crate::value::Value; use std::marker::PhantomData; +use std::mem::transmute; use std::ops::Deref; use std::ops::DerefMut; use std::ptr::NonNull; @@ -49,6 +49,15 @@ impl<'sc, T> Clone for 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(other: Local<'sc, A>) -> Self + where + Local<'sc, A>: From, + { + transmute(other) + } + pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option { 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. For example -// Local should be able to be down cast to Local. -impl<'sc, T> From> for Local<'sc, Value> -where - T: Deref, -{ - fn from(v: Local<'sc, T>) -> Local<'sc, Value> { - unsafe { std::mem::transmute(v) } - } -} - #[test] fn test_size_of_local() { + use crate::Value; use std::mem::size_of; assert_eq!(size_of::>(), size_of::<*const Value>()); assert_eq!(size_of::>>(), size_of::<*const Value>()); diff --git a/src/module.rs b/src/module.rs index c886ba80..2aad9ea7 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,8 +1,8 @@ use crate::support::int; use crate::support::MaybeBool; -use crate::support::Opaque; use crate::Context; use crate::Local; +use crate::Module; use crate::String; use crate::ToLocal; use crate::Value; @@ -75,10 +75,6 @@ pub enum ModuleStatus { Errored, } -/// A compiled JavaScript module. -#[repr(C)] -pub struct Module(Opaque); - impl Module { /// Returns the module's current status. pub fn get_status(&self) -> ModuleStatus { diff --git a/src/number.rs b/src/number.rs index 17d875cf..a0b0f4fa 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,10 +1,11 @@ use std::ops::Deref; use crate::isolate::Isolate; -use crate::support::Opaque; -use crate::value::Value; +use crate::Integer; use crate::Local; +use crate::Number; use crate::ToLocal; +use crate::Value; extern "C" { 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; } -/// A JavaScript number value (ECMA-262, 4.3.20) -#[repr(C)] -pub struct Number(Opaque); - impl Number { pub fn new<'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 { pub fn new<'sc>( scope: &mut impl ToLocal<'sc>, diff --git a/src/object.rs b/src/object.rs index b7b2f6b6..6313b18a 100644 --- a/src/object.rs +++ b/src/object.rs @@ -2,17 +2,13 @@ use std::ops::Deref; use crate::isolate::Isolate; use crate::support::MaybeBool; -use crate::support::Opaque; use crate::Context; use crate::Local; use crate::Name; +use crate::Object; use crate::ToLocal; use crate::Value; -/// A JavaScript object (ECMA-262, 4.3.3) -#[repr(C)] -pub struct Object(Opaque); - extern "C" { fn v8__Object__New(isolate: *mut Isolate) -> *mut Object; fn v8__Object__New2( diff --git a/src/primitives.rs b/src/primitives.rs index c41a6c8f..70e91a35 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -1,24 +1,13 @@ use std::ops::Deref; use crate::isolate::Isolate; -use crate::support::Opaque; +use crate::Boolean; use crate::Local; +use crate::Name; +use crate::Primitive; use crate::ToLocal; 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" { fn v8__Null(isolate: *mut Isolate) -> *mut Primitive; diff --git a/src/promise.rs b/src/promise.rs index 587a6d35..548c3500 100644 --- a/src/promise.rs +++ b/src/promise.rs @@ -1,10 +1,11 @@ use std::marker::PhantomData; use crate::support::MaybeBool; -use crate::support::Opaque; use crate::Context; use crate::Function; use crate::Local; +use crate::Promise; +use crate::PromiseResolver; use crate::ToLocal; use crate::Value; @@ -62,10 +63,6 @@ pub enum PromiseState { Rejected, } -/// An instance of the built-in Promise constructor (ES6 draft). -#[repr(C)] -pub struct Promise(Opaque); - impl Promise { /// Returns the value of the [[PromiseState]] field. pub fn state(&mut self) -> PromiseState { @@ -142,9 +139,6 @@ impl Promise { } } -#[repr(C)] -pub struct PromiseResolver(Opaque); - impl PromiseResolver { /// Create a new resolver, along with an associated promise in pending state. pub fn new<'sc>( diff --git a/src/shared_array_buffer.rs b/src/shared_array_buffer.rs index dd8464cb..fc4d70e4 100644 --- a/src/shared_array_buffer.rs +++ b/src/shared_array_buffer.rs @@ -1,10 +1,10 @@ use std::ops::Deref; -use crate::support::Opaque; use crate::support::SharedRef; use crate::BackingStore; use crate::Isolate; use crate::Local; +use crate::SharedArrayBuffer; use crate::ToLocal; use crate::Value; @@ -21,11 +21,6 @@ extern "C" { ) -> SharedRef; } -/// An instance of the built-in SharedArrayBuffer constructor. -/// This API is experimental and may change significantly. -#[repr(C)] -pub struct SharedArrayBuffer(Opaque); - impl SharedArrayBuffer { /// Create a new SharedArrayBuffer. Allocate |byte_length| bytes. /// Allocated memory will be owned by a created SharedArrayBuffer and diff --git a/src/string.rs b/src/string.rs index 24b083cd..bfa9968a 100644 --- a/src/string.rs +++ b/src/string.rs @@ -6,10 +6,10 @@ use std::slice; use crate::support::char; use crate::support::int; -use crate::support::Opaque; use crate::InIsolate; use crate::Isolate; use crate::Local; +use crate::String; use crate::ToLocal; 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 { pub fn new_from_utf8<'sc>( scope: &mut impl ToLocal<'sc>, diff --git a/src/uint8_array.rs b/src/uint8_array.rs index 7f83910e..90b955a2 100644 --- a/src/uint8_array.rs +++ b/src/uint8_array.rs @@ -1,8 +1,8 @@ use std::ops::DerefMut; -use crate::support::Opaque; use crate::ArrayBuffer; use crate::Local; +use crate::Uint8Array; extern "C" { fn v8__Uint8Array__New( @@ -12,10 +12,6 @@ extern "C" { ) -> *mut Uint8Array; } -/// An instance of Uint8Array constructor (ES6 draft 15.13.6). -#[repr(C)] -pub struct Uint8Array(Opaque); - impl Uint8Array { pub fn new<'sc>( mut buf: Local, diff --git a/src/value.rs b/src/value.rs index 170eb338..54e08bfc 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,5 +1,5 @@ -use crate::support; use crate::Local; +use crate::Value; extern "C" { fn v8__Value__IsUndefined(this: &Value) -> bool; @@ -14,10 +14,6 @@ extern "C" { 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 { /// Returns true if this value is the undefined value. See ECMA-262 4.3.10. pub fn is_undefined(&self) -> bool { diff --git a/tests/test_api.rs b/tests/test_api.rs index 7a911348..b96e183f 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -5,6 +5,7 @@ extern crate lazy_static; use rusty_v8 as v8; use rusty_v8::{new_null, FunctionCallbackInfo, InIsolate, Local, ToLocal}; +use std::convert::Into; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Mutex; @@ -165,14 +166,12 @@ fn escapable_handle_scope() { let scope1 = hs.enter(); // After dropping EscapableHandleScope, we should be able to // read escaped values. - let number_val = { + let number = { let mut hs = v8::EscapableHandleScope::new(scope1); let escapable_scope = hs.enter(); - let number: Local = - cast(v8::Number::new(escapable_scope, 78.9)); + let number = v8::Number::new(escapable_scope, 78.9); escapable_scope.escape(number) }; - let number: Local = cast(number_val); assert_eq!(number.value(), 78.9); let string = { @@ -457,7 +456,7 @@ fn set_host_initialize_import_meta_object_callback() { let scope = hs.enter(); let key = v8::String::new(scope, "foo").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); @@ -475,7 +474,7 @@ fn set_host_initialize_import_meta_object_callback() { assert!(result.is_some()); let meta = module.evaluate(s, context).unwrap(); assert!(meta.is_object()); - let meta: Local = cast(meta); + let meta = unsafe { Local::::cast(meta) }; let key = v8::String::new(s, "foo").unwrap(); let expected = v8::String::new(s, "bar").unwrap(); let actual = meta.get(s, context, key.into()).unwrap(); @@ -698,12 +697,6 @@ fn json() { drop(locker); } -// TODO Safer casts https://github.com/denoland/rusty_v8/issues/51 -fn cast(local: v8::Local) -> v8::Local { - let cast_local: v8::Local = unsafe { std::mem::transmute_copy(&local) }; - cast_local -} - #[test] fn object() { setup(); @@ -719,8 +712,8 @@ fn object() { let null: v8::Local = new_null(scope).into(); let s1 = v8::String::new(scope, "a").unwrap(); let s2 = v8::String::new(scope, "b").unwrap(); - let name1: Local = cast(s1); - let name2: Local = cast(s2); + let name1 = s1.into(); + let name2 = s2.into(); let names = vec![name1, name2]; let v1: v8::Local = v8::Number::new(scope, 1.0).into(); let v2: v8::Local = v8::Number::new(scope, 2.0).into(); @@ -757,22 +750,22 @@ fn create_data_property() { .get(scope, context, key.into()) .unwrap(); assert!(obj.is_object()); - let obj: Local = cast(obj); + let obj = unsafe { Local::::cast(obj) }; let key = v8_str(scope, "foo"); let value = v8_str(scope, "bar"); assert_eq!( - obj.create_data_property(context, cast(key), cast(value)), + obj.create_data_property(context, key.into(), value.into()), 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)); let key2 = v8_str(scope, "foo2"); assert_eq!( - obj.set(context, cast(key2), cast(value)), + obj.set(context, key2.into(), value.into()), 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)); context.exit(); @@ -798,20 +791,18 @@ fn promise_resolved() { let mut promise = resolver.get_promise(scope); assert!(!promise.has_handler()); assert_eq!(promise.state(), v8::PromiseState::Pending); - let str = v8::String::new(scope, "test").unwrap(); - let value: Local = cast(str); - resolver.resolve(context, value); + let value = v8::String::new(scope, "test").unwrap(); + resolver.resolve(context, value.into()); assert_eq!(promise.state(), v8::PromiseState::Fulfilled); let result = promise.result(scope); - let result_str: v8::Local = cast(result); + let result_str = unsafe { Local::::cast(result) }; assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); // Resolve again with different value, since promise is already in `Fulfilled` state // it should be ignored. - let str = v8::String::new(scope, "test2").unwrap(); - let value: Local = cast(str); - resolver.resolve(context, value); + let value = v8::String::new(scope, "test2").unwrap(); + resolver.resolve(context, value.into()); let result = promise.result(scope); - let result_str: v8::Local = cast(result); + let result_str = unsafe { Local::::cast(result) }; assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); context.exit(); } @@ -836,21 +827,19 @@ fn promise_rejected() { let mut promise = resolver.get_promise(scope); assert!(!promise.has_handler()); assert_eq!(promise.state(), v8::PromiseState::Pending); - let str = v8::String::new(scope, "test").unwrap(); - let value: Local = cast(str); - let rejected = resolver.reject(context, value); + let value = v8::String::new(scope, "test").unwrap(); + let rejected = resolver.reject(context, value.into()); assert!(rejected.unwrap()); assert_eq!(promise.state(), v8::PromiseState::Rejected); let result = promise.result(scope); - let result_str: v8::Local = cast(result); + let result_str = unsafe { Local::::cast(result) }; assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); // Reject again with different value, since promise is already in `Rejected` state // it should be ignored. - let str = v8::String::new(scope, "test2").unwrap(); - let value: Local = cast(str); - resolver.reject(context, value); + let value = v8::String::new(scope, "test2").unwrap(); + resolver.reject(context, value.into()); let result = promise.result(scope); - let result_str: v8::Local = cast(result); + let result_str = unsafe { Local::::cast(result) }; assert_eq!(result_str.to_rust_string_lossy(scope), "test".to_string()); context.exit(); } @@ -904,7 +893,7 @@ fn function() { let maybe_value = v8::Function::call(&mut *function, scope, context, recv, 0, vec![]); let value = maybe_value.unwrap(); - let value_str: v8::Local = cast(value); + let value_str = unsafe { Local::::cast(value) }; let rust_str = value_str.to_rust_string_lossy(scope); assert_eq!(rust_str, "Hello callback!".to_string()); context.exit(); @@ -917,14 +906,14 @@ extern "C" fn promise_reject_callback(msg: v8::PromiseRejectMessage) { assert_eq!(event, v8::PromiseRejectEvent::PromiseRejectWithNoHandler); let mut promise = msg.get_promise(); assert_eq!(promise.state(), v8::PromiseState::Rejected); - let mut promise_obj: v8::Local = cast(promise); + let mut promise_obj: Local = promise.into(); let isolate = promise_obj.get_isolate(); let value = msg.get_value(); let mut locker = v8::Locker::new(isolate); { let mut hs = v8::HandleScope::new(&mut locker); let scope = hs.enter(); - let value_str: v8::Local = cast(value); + let value_str = unsafe { Local::::cast(value) }; let rust_str = value_str.to_rust_string_lossy(scope); assert_eq!(rust_str, "promise rejected".to_string()); } @@ -946,9 +935,8 @@ fn set_promise_reject_callback() { let mut context = v8::Context::new(scope); context.enter(); let mut resolver = v8::PromiseResolver::new(scope, context).unwrap(); - let str_ = v8::String::new(scope, "promise rejected").unwrap(); - let value: Local = cast(str_); - resolver.reject(context, value); + let value = v8::String::new(scope, "promise rejected").unwrap(); + resolver.reject(context, value.into()); context.exit(); } drop(locker); @@ -1109,7 +1097,7 @@ fn compile_specifier_as_module_resolve_callback( let source = v8::script_compiler::Source::new(specifier, &origin); let module = v8::script_compiler::compile_module(scope.isolate(), source).unwrap(); - &mut *cast(scope.escape(module)) + &mut *scope.escape(module) } #[test] @@ -1185,12 +1173,12 @@ fn primitive_array() { } 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, 1).is_string()); 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, 1).is_string()); assert!(array.get(scope, 2).is_number()); @@ -1257,8 +1245,7 @@ fn array_buffer_view() { source.to_rust_string_lossy(s); let result = script.run(s, context).unwrap(); // TODO: safer casts. - let result: v8::Local = - cast(result); + let result = unsafe { Local::::cast(result) }; assert_eq!(result.byte_length(), 4); assert_eq!(result.byte_offset(), 0); let mut dest = [0; 4]; @@ -1323,7 +1310,7 @@ fn snapshot_creator() { let mut script = v8::Script::compile(scope, context, source, None).unwrap(); let result = script.run(scope, context).unwrap(); - let true_val: Local = cast(v8::new_true(scope)); + let true_val = v8::new_true(scope).into(); assert!(result.same_value(true_val)); context.exit(); } @@ -1363,7 +1350,7 @@ fn external_references() { .expect("Unable to create function"); 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); @@ -1426,8 +1413,7 @@ fn uint8_array() { source.to_rust_string_lossy(s); let result = script.run(s, context).unwrap(); // TODO: safer casts. - let result: v8::Local = - cast(result); + let result = unsafe { Local::::cast(result) }; assert_eq!(result.byte_length(), 4); assert_eq!(result.byte_offset(), 0); let mut dest = [0; 4]; @@ -1520,8 +1506,8 @@ fn shared_array_buffer() { assert_eq!( global.create_data_property( context, - cast(v8_str(s, "shared")), - cast(sab) + v8_str(s, "shared").into(), + sab.into() ), v8::MaybeBool::JustTrue ); @@ -1534,7 +1520,7 @@ fn shared_array_buffer() { source.to_rust_string_lossy(s); let result = script.run(s, context).unwrap(); // TODO: safer casts. - let result: v8::Local = cast(result); + let result = unsafe { Local::::cast(result) }; assert_eq!(result.value(), 64); assert_eq!(shared_buf[2], 16); assert_eq!(shared_buf[14], 62);