mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-11 08:34:01 -05:00
Add APIs to store/retrieve embedder data in a Context or Isolate snapshot (#449)
Co-authored-by: Bert Belder <bertbelder@gmail.com>
This commit is contained in:
parent
888e5deea1
commit
405a5a5158
6 changed files with 264 additions and 109 deletions
|
@ -153,6 +153,11 @@ uint32_t v8__Isolate__GetNumberOfDataSlots(v8::Isolate* isolate) {
|
|||
return SLOT_NUM_EXTERNAL(isolate);
|
||||
}
|
||||
|
||||
const v8::Data* v8__Isolate__GetDataFromSnapshotOnce(v8::Isolate* isolate,
|
||||
size_t index) {
|
||||
return maybe_local_to_ptr(isolate->GetDataFromSnapshotOnce<v8::Data>(index));
|
||||
}
|
||||
|
||||
v8::MicrotasksPolicy v8__Isolate__GetMicrotasksPolicy(
|
||||
const v8::Isolate* isolate) {
|
||||
return isolate->GetMicrotasksPolicy();
|
||||
|
@ -296,11 +301,7 @@ const v8::Module* v8__ScriptCompiler__CompileModule(
|
|||
v8::ScriptCompiler::NoCacheReason no_cache_reason) {
|
||||
v8::MaybeLocal<v8::Module> maybe_local = v8::ScriptCompiler::CompileModule(
|
||||
isolate, source, options, no_cache_reason);
|
||||
if (maybe_local.IsEmpty()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return local_to_ptr(maybe_local.ToLocalChecked());
|
||||
}
|
||||
return maybe_local_to_ptr(maybe_local);
|
||||
}
|
||||
|
||||
bool v8__Data__EQ(const v8::Data& self, const v8::Data& other) {
|
||||
|
@ -1012,6 +1013,12 @@ const v8::Object* v8__Context__Global(const v8::Context& self) {
|
|||
return local_to_ptr(ptr_to_local(&self)->Global());
|
||||
}
|
||||
|
||||
const v8::Data* v8__Context__GetDataFromSnapshotOnce(v8::Context& self,
|
||||
size_t index) {
|
||||
return maybe_local_to_ptr(
|
||||
ptr_to_local(&self)->GetDataFromSnapshotOnce<v8::Data>(index));
|
||||
}
|
||||
|
||||
const v8::String* v8__Message__Get(const v8::Message& self) {
|
||||
return local_to_ptr(self.Get());
|
||||
}
|
||||
|
@ -1519,6 +1526,17 @@ void v8__SnapshotCreator__SetDefaultContext(v8::SnapshotCreator* self,
|
|||
self->SetDefaultContext(ptr_to_local(&context), SerializeInternalFields);
|
||||
}
|
||||
|
||||
size_t v8__SnapshotCreator__AddData_to_isolate(v8::SnapshotCreator* self,
|
||||
const v8::Data& data) {
|
||||
return self->AddData(ptr_to_local(&data));
|
||||
}
|
||||
|
||||
size_t v8__SnapshotCreator__AddData_to_context(v8::SnapshotCreator* self,
|
||||
const v8::Context& context,
|
||||
const v8::Data& data) {
|
||||
return self->AddData(ptr_to_local(&context), ptr_to_local(&data));
|
||||
}
|
||||
|
||||
v8::StartupData v8__SnapshotCreator__CreateBlob(
|
||||
v8::SnapshotCreator* self,
|
||||
v8::SnapshotCreator::FunctionCodeHandling function_code_handling) {
|
||||
|
|
48
src/data.rs
48
src/data.rs
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::any::type_name;
|
||||
use std::convert::From;
|
||||
use std::convert::TryFrom;
|
||||
use std::error::Error;
|
||||
|
@ -89,11 +90,11 @@ macro_rules! impl_from {
|
|||
macro_rules! impl_try_from {
|
||||
{ $source:ident for $target:ident if $value:pat => $check:expr } => {
|
||||
impl<'s> TryFrom<Local<'s, $source>> for Local<'s, $target> {
|
||||
type Error = TryFromTypeError;
|
||||
type Error = DataError;
|
||||
fn try_from(l: Local<'s, $source>) -> Result<Self, Self::Error> {
|
||||
match l {
|
||||
$value if $check => Ok(unsafe { transmute(l) }),
|
||||
_ => Err(TryFromTypeError::new(stringify!($target)))
|
||||
_ => Err(DataError::bad_type::<$target, $source>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,23 +153,45 @@ macro_rules! impl_partial_eq {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct TryFromTypeError {
|
||||
expected_type: &'static str,
|
||||
pub enum DataError {
|
||||
BadType {
|
||||
actual: &'static str,
|
||||
expected: &'static str,
|
||||
},
|
||||
NoData {
|
||||
expected: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
impl TryFromTypeError {
|
||||
fn new(expected_type: &'static str) -> Self {
|
||||
Self { expected_type }
|
||||
impl DataError {
|
||||
pub(crate) fn bad_type<E: 'static, A: 'static>() -> Self {
|
||||
Self::BadType {
|
||||
expected: type_name::<E>(),
|
||||
actual: type_name::<A>(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn no_data<E: 'static>() -> Self {
|
||||
Self::NoData {
|
||||
expected: type_name::<E>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TryFromTypeError {
|
||||
impl Display for DataError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{} expected", self.expected_type)
|
||||
match self {
|
||||
Self::BadType { expected, actual } => {
|
||||
write!(f, "expected type `{}`, got `{}`", expected, actual)
|
||||
}
|
||||
Self::NoData { expected } => {
|
||||
write!(f, "expected `Some({})`, found `None`", expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for TryFromTypeError {}
|
||||
impl Error for DataError {}
|
||||
|
||||
/// The superclass of objects that can reside on V8's heap.
|
||||
#[repr(C)]
|
||||
|
@ -587,6 +610,11 @@ impl_partial_eq! { UnboundScript for UnboundScript use identity }
|
|||
pub struct Value(Opaque);
|
||||
|
||||
impl_deref! { Data for Value }
|
||||
// TODO: Also implement `TryFrom<Data>` for all subtypes of `Value`,
|
||||
// so a `Local<Data>` can be directly cast to any `Local` with a JavaScript
|
||||
// value type in it. We need this to make certain APIs work, such as
|
||||
// `scope.get_context_data_from_snapshot_once::<v8::Number>()` and
|
||||
// `scope.get_isolate_data_from_snapshot_once::<v8::Number>()`.
|
||||
impl_try_from! { Data for Value if d => d.is_value() }
|
||||
impl_from! { External for Value }
|
||||
impl_from! { Object for Value }
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::scope::CallbackScope;
|
||||
use crate::support::MapFnFrom;
|
||||
use crate::support::MapFnTo;
|
||||
use crate::support::ToCFn;
|
||||
use crate::support::UnitType;
|
||||
use crate::support::{int, Opaque};
|
||||
use crate::CallbackScope;
|
||||
use crate::Context;
|
||||
use crate::Function;
|
||||
use crate::HandleScope;
|
||||
|
|
70
src/scope.rs
70
src/scope.rs
|
@ -81,6 +81,8 @@ use std::alloc::alloc;
|
|||
use std::alloc::Layout;
|
||||
use std::any::type_name;
|
||||
use std::cell::Cell;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::num::NonZeroUsize;
|
||||
|
@ -93,6 +95,7 @@ use crate::function::FunctionCallbackInfo;
|
|||
use crate::function::PropertyCallbackInfo;
|
||||
use crate::Context;
|
||||
use crate::Data;
|
||||
use crate::DataError;
|
||||
use crate::Handle;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
|
@ -224,6 +227,61 @@ impl<'s> HandleScope<'s, ()> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'s> HandleScope<'s> {
|
||||
/// Return data that was previously attached to the isolate snapshot via
|
||||
/// SnapshotCreator, and removes the reference to it. If called again with
|
||||
/// same `index` argument, this function returns `DataError::NoData`.
|
||||
///
|
||||
/// The value that was stored in the snapshot must either match or be
|
||||
/// convertible to type parameter `T`, otherwise `DataError::BadType` is
|
||||
/// returned.
|
||||
pub fn get_isolate_data_from_snapshot_once<T>(
|
||||
&mut self,
|
||||
index: usize,
|
||||
) -> Result<Local<'s, T>, DataError>
|
||||
where
|
||||
T: 'static,
|
||||
for<'l> Local<'l, Data>: TryInto<Local<'l, T>, Error = DataError>,
|
||||
{
|
||||
unsafe {
|
||||
self
|
||||
.cast_local(|sd| {
|
||||
raw::v8__Isolate__GetDataFromSnapshotOnce(sd.get_isolate_ptr(), index)
|
||||
})
|
||||
.ok_or_else(DataError::no_data::<T>)
|
||||
.and_then(|data| data.try_into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Return data that was previously attached to the context snapshot via
|
||||
/// SnapshotCreator, and removes the reference to it. If called again with
|
||||
/// same `index` argument, this function returns `DataError::NoData`.
|
||||
///
|
||||
/// The value that was stored in the snapshot must either match or be
|
||||
/// convertible to type parameter `T`, otherwise `DataError::BadType` is
|
||||
/// returned.
|
||||
pub fn get_context_data_from_snapshot_once<T>(
|
||||
&mut self,
|
||||
index: usize,
|
||||
) -> Result<Local<'s, T>, DataError>
|
||||
where
|
||||
T: 'static,
|
||||
for<'l> Local<'l, Data>: TryInto<Local<'l, T>, Error = DataError>,
|
||||
{
|
||||
unsafe {
|
||||
self
|
||||
.cast_local(|sd| {
|
||||
raw::v8__Context__GetDataFromSnapshotOnce(
|
||||
sd.get_current_context(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.ok_or_else(DataError::no_data::<T>)
|
||||
.and_then(|data| data.try_into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A HandleScope which first allocates a handle in the current scope
|
||||
/// which will be later filled with the escape value.
|
||||
// TODO(piscisaureus): type parameter `C` is not very useful in practice; being
|
||||
|
@ -608,8 +666,8 @@ impl<T: Scope> ScopeCast for T {
|
|||
///
|
||||
/// For example: a `ContextScope` created inside `HandleScope<'a, ()>` does not
|
||||
/// produce a `ContextScope`, but rather a `HandleScope<'a, Context>`, which
|
||||
/// describes a scope that is both a `HandleScope` _and_ a `ContextScope`.
|
||||
///
|
||||
/// describes a scope that is both a `HandleScope` _and_ a `ContextScope`.
|
||||
///
|
||||
/// The Traits in the (private) `param` module define which types can be passed
|
||||
/// as a parameter to the `«Some»Scope::new()` constructor, and what the
|
||||
/// actual, merged scope type will be that `new()` returns for a specific
|
||||
|
@ -1560,6 +1618,10 @@ mod raw {
|
|||
isolate: *mut Isolate,
|
||||
exception: *const Value,
|
||||
) -> *const Value;
|
||||
pub(super) fn v8__Isolate__GetDataFromSnapshotOnce(
|
||||
this: *mut Isolate,
|
||||
index: usize,
|
||||
) -> *const Data;
|
||||
|
||||
pub(super) fn v8__Context__EQ(
|
||||
this: *const Context,
|
||||
|
@ -1569,6 +1631,10 @@ mod raw {
|
|||
pub(super) fn v8__Context__Exit(this: *const Context);
|
||||
pub(super) fn v8__Context__GetIsolate(this: *const Context)
|
||||
-> *mut Isolate;
|
||||
pub(super) fn v8__Context__GetDataFromSnapshotOnce(
|
||||
this: *const Context,
|
||||
index: usize,
|
||||
) -> *const Data;
|
||||
|
||||
pub(super) fn v8__HandleScope__CONSTRUCT(
|
||||
buf: *mut MaybeUninit<HandleScope>,
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::support::char;
|
|||
use crate::support::int;
|
||||
use crate::support::intptr_t;
|
||||
use crate::Context;
|
||||
use crate::Data;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::OwnedIsolate;
|
||||
|
@ -30,6 +31,15 @@ extern "C" {
|
|||
this: *mut SnapshotCreator,
|
||||
context: *const Context,
|
||||
);
|
||||
fn v8__SnapshotCreator__AddData_to_isolate(
|
||||
this: *mut SnapshotCreator,
|
||||
data: *const Data,
|
||||
) -> usize;
|
||||
fn v8__SnapshotCreator__AddData_to_context(
|
||||
this: *mut SnapshotCreator,
|
||||
context: *const Context,
|
||||
data: *const Data,
|
||||
) -> usize;
|
||||
fn v8__StartupData__DESTRUCT(this: *mut StartupData);
|
||||
}
|
||||
|
||||
|
@ -112,6 +122,34 @@ impl SnapshotCreator {
|
|||
unsafe { v8__SnapshotCreator__SetDefaultContext(self, &*context) };
|
||||
}
|
||||
|
||||
/// Attach arbitrary `v8::Data` to the isolate snapshot, which can be
|
||||
/// retrieved via `HandleScope::get_context_data_from_snapshot_once()` after
|
||||
/// deserialization. This data does not survive when a new snapshot is created
|
||||
/// from an existing snapshot.
|
||||
pub fn add_isolate_data<T>(&mut self, data: Local<T>) -> usize
|
||||
where
|
||||
for<'l> Local<'l, T>: Into<Local<'l, Data>>,
|
||||
{
|
||||
unsafe { v8__SnapshotCreator__AddData_to_isolate(self, &*data.into()) }
|
||||
}
|
||||
|
||||
/// Attach arbitrary `v8::Data` to the context snapshot, which can be
|
||||
/// retrieved via `HandleScope::get_context_data_from_snapshot_once()` after
|
||||
/// deserialization. This data does not survive when a new snapshot is
|
||||
/// created from an existing snapshot.
|
||||
pub fn add_context_data<T>(
|
||||
&mut self,
|
||||
context: Local<Context>,
|
||||
data: Local<T>,
|
||||
) -> usize
|
||||
where
|
||||
for<'l> Local<'l, T>: Into<Local<'l, Data>>,
|
||||
{
|
||||
unsafe {
|
||||
v8__SnapshotCreator__AddData_to_context(self, &*context, &*data.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a snapshot data blob.
|
||||
/// This must not be called from within a handle scope.
|
||||
pub fn create_blob(
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::any::type_name;
|
||||
use std::convert::{Into, TryFrom, TryInto};
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
@ -2101,6 +2102,9 @@ fn snapshot_creator() {
|
|||
let _setup_guard = setup();
|
||||
// First we create the snapshot, there is a single global variable 'a' set to
|
||||
// the value 3.
|
||||
let isolate_data_index;
|
||||
let context_data_index;
|
||||
let context_data_index_2;
|
||||
let startup_data = {
|
||||
let mut snapshot_creator = v8::SnapshotCreator::new(None);
|
||||
// TODO(ry) this shouldn't be necessary. workaround unfinished business in
|
||||
|
@ -2119,6 +2123,13 @@ fn snapshot_creator() {
|
|||
script.run(scope).unwrap();
|
||||
|
||||
snapshot_creator.set_default_context(context);
|
||||
|
||||
isolate_data_index =
|
||||
snapshot_creator.add_isolate_data(v8::Number::new(scope, 1.0));
|
||||
context_data_index =
|
||||
snapshot_creator.add_context_data(context, v8::Number::new(scope, 2.0));
|
||||
context_data_index_2 =
|
||||
snapshot_creator.add_context_data(context, v8::Number::new(scope, 3.0));
|
||||
}
|
||||
std::mem::forget(isolate); // TODO(ry) this shouldn't be necessary.
|
||||
snapshot_creator
|
||||
|
@ -2140,6 +2151,26 @@ fn snapshot_creator() {
|
|||
let result = script.run(scope).unwrap();
|
||||
let true_val = v8::Boolean::new(scope, true).into();
|
||||
assert!(result.same_value(true_val));
|
||||
|
||||
let isolate_data = scope
|
||||
.get_isolate_data_from_snapshot_once::<v8::Value>(isolate_data_index);
|
||||
assert!(isolate_data.unwrap() == v8::Number::new(scope, 1.0));
|
||||
let no_data_err = scope
|
||||
.get_isolate_data_from_snapshot_once::<v8::Value>(isolate_data_index);
|
||||
assert!(matches!(no_data_err, Err(v8::DataError::NoData { .. })));
|
||||
|
||||
let context_data = scope
|
||||
.get_context_data_from_snapshot_once::<v8::Value>(context_data_index);
|
||||
assert!(context_data.unwrap() == v8::Number::new(scope, 2.0));
|
||||
let no_data_err = scope
|
||||
.get_context_data_from_snapshot_once::<v8::Value>(context_data_index);
|
||||
assert!(matches!(no_data_err, Err(v8::DataError::NoData { .. })));
|
||||
|
||||
let bad_type_err = scope
|
||||
.get_context_data_from_snapshot_once::<v8::Private>(
|
||||
context_data_index_2,
|
||||
);
|
||||
assert!(matches!(bad_type_err, Err(v8::DataError::BadType { .. })));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2782,20 +2813,16 @@ fn try_from_value() {
|
|||
{
|
||||
let value: v8::Local<v8::Value> = v8::undefined(scope).into();
|
||||
let _primitive = v8::Local::<v8::Primitive>::try_from(value).unwrap();
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Object>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Object expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Int32>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Int32 expected"
|
||||
);
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Object>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Object>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Int32>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Int32>()
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2803,20 +2830,16 @@ fn try_from_value() {
|
|||
let primitive = v8::Local::<v8::Primitive>::try_from(value).unwrap();
|
||||
let _boolean = v8::Local::<v8::Boolean>::try_from(value).unwrap();
|
||||
let _boolean = v8::Local::<v8::Boolean>::try_from(primitive).unwrap();
|
||||
assert_eq!(
|
||||
v8::Local::<v8::String>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"String expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Number>::try_from(primitive)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Number expected"
|
||||
);
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::String>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::String>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Number>::try_from(primitive),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Number>()
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2831,27 +2854,21 @@ fn try_from_value() {
|
|||
let _int32 = v8::Local::<v8::Int32>::try_from(primitive).unwrap();
|
||||
let _int32 = v8::Local::<v8::Int32>::try_from(integer).unwrap();
|
||||
let _int32 = v8::Local::<v8::Int32>::try_from(number).unwrap();
|
||||
assert_eq!(
|
||||
v8::Local::<v8::String>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"String expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Boolean>::try_from(primitive)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Boolean expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Uint32>::try_from(integer)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Uint32 expected"
|
||||
);
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::String>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::String>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Boolean>::try_from(primitive),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Boolean>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Uint32>::try_from(integer),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Uint32>()
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2859,48 +2876,36 @@ fn try_from_value() {
|
|||
let object = v8::Local::<v8::Object>::try_from(value).unwrap();
|
||||
let _function = v8::Local::<v8::Function>::try_from(value).unwrap();
|
||||
let _function = v8::Local::<v8::Function>::try_from(object).unwrap();
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Primitive>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Primitive expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::BigInt>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"BigInt expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::NumberObject>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"NumberObject expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::NumberObject>::try_from(object)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"NumberObject expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Set>::try_from(value)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Set expected"
|
||||
);
|
||||
assert_eq!(
|
||||
v8::Local::<v8::Set>::try_from(object)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"Set expected"
|
||||
);
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Primitive>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Primitive>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::BigInt>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::BigInt>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::NumberObject>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::NumberObject>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::NumberObject>::try_from(object),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::NumberObject>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Set>::try_from(value),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Set>()
|
||||
));
|
||||
assert!(matches!(
|
||||
v8::Local::<v8::Set>::try_from(object),
|
||||
Err(v8::DataError::BadType { expected, .. })
|
||||
if expected == type_name::<v8::Set>()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue