Rolling to V8 12.0.267.1 (#1361)

Co-authored-by: Luca Casonato <hello@lcas.dev>
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
denobot 2023-10-31 20:26:06 -04:00 committed by GitHub
parent 7072da4199
commit 92f7d41a4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 246 additions and 99 deletions

View File

@ -1,6 +1,6 @@
# Rusty V8 Binding
V8 Version: 11.8.172.13
V8 Version: 12.0.267.1
[![ci](https://github.com/denoland/rusty_v8/workflows/ci/badge.svg?branch=main)](https://github.com/denoland/rusty_v8/actions)
[![crates](https://img.shields.io/crates/v/v8.svg)](https://crates.io/crates/v8)

View File

@ -883,6 +883,6 @@ edge [fontsize=10]
fn test_static_lib_size() {
let static_lib_size = std::fs::metadata(static_lib_path()).unwrap().len();
eprintln!("static lib size {}", static_lib_size);
assert!(static_lib_size <= 270u64 << 20); // No more than 270 MiB.
assert!(static_lib_size <= 300u64 << 20); // No more than 300 MiB.
}
}

View File

@ -485,7 +485,7 @@ uint32_t v8__ScriptCompiler__CachedDataVersionTag() {
size_t v8__TypedArray__Length(const v8::TypedArray* self) {
return ptr_to_local(self)->Length();
}
size_t v8__TypedArray__kMaxLength() { return v8::TypedArray::kMaxLength; }
size_t v8__TypedArray__kMaxByteLength() { return v8::TypedArray::kMaxByteLength; }
bool v8__Data__EQ(const v8::Data& self, const v8::Data& other) {
return ptr_to_local(&self) == ptr_to_local(&other);
@ -1430,7 +1430,7 @@ int v8__Object__InternalFieldCount(const v8::Object& self) {
return ptr_to_local(&self)->InternalFieldCount();
}
const v8::Value* v8__Object__GetInternalField(const v8::Object& self,
const v8::Data* v8__Object__GetInternalField(const v8::Object& self,
int index) {
return local_to_ptr(ptr_to_local(&self)->GetInternalField(index));
}
@ -1448,8 +1448,8 @@ MaybeBool v8__Object__SetIntegrityLevel(const v8::Object& self,
}
void v8__Object__SetInternalField(const v8::Object& self, int index,
const v8::Value& value) {
ptr_to_local(&self)->SetInternalField(index, ptr_to_local(&value));
const v8::Data& data) {
ptr_to_local(&self)->SetInternalField(index, ptr_to_local(&data));
}
const v8::Value* v8__Object__GetPrivate(const v8::Object& self,
@ -2308,8 +2308,12 @@ void v8__AllowJavascriptExecutionScope__DESTRUCT(
size_t byte_offset, size_t length) { \
return local_to_ptr( \
v8::NAME::New(ptr_to_local(&buf_ptr), byte_offset, length)); \
} \
size_t v8__##NAME##__kMaxLength() { \
return v8::NAME::kMaxLength; \
}
V(Uint8Array)
V(Uint8ClampedArray)
V(Int8Array)
@ -3003,10 +3007,11 @@ const v8::Module* v8__Module__CreateSyntheticModule(
v8::Isolate* isolate, const v8::String* module_name,
size_t export_names_len, const v8::String* export_names_raw[],
v8::Module::SyntheticModuleEvaluationSteps evaluation_steps) {
std::vector<v8::Local<v8::String>> export_names{};
std::vector<v8::Local<v8::String>> export_names_vec{};
for (size_t i = 0; i < export_names_len; i += 1) {
export_names.push_back(ptr_to_local(export_names_raw[i]));
export_names_vec.push_back(ptr_to_local(export_names_raw[i]));
}
auto export_names = v8::MemorySpan<const v8::Local<v8::String>>{export_names_vec.data(), export_names_len};
return local_to_ptr(v8::Module::CreateSyntheticModule(
isolate, ptr_to_local(module_name), export_names, evaluation_steps));
}
@ -3134,7 +3139,7 @@ void v8__HeapProfiler__TakeHeapSnapshot(v8::Isolate* isolate,
v8::Isolate* v8__internal__GetIsolateFromHeapObject(const v8::Data& data) {
namespace i = v8::internal;
i::Object object(reinterpret_cast<const i::Address&>(data));
i::Tagged<i::Object> object(reinterpret_cast<const i::Address&>(data));
i::Isolate* isolate;
return IsHeapObject(object) &&
i::GetIsolateFromHeapObject(object.GetHeapObject(), &isolate)
@ -3144,7 +3149,7 @@ v8::Isolate* v8__internal__GetIsolateFromHeapObject(const v8::Data& data) {
int v8__Value__GetHash(const v8::Value& data) {
namespace i = v8::internal;
i::Object object(reinterpret_cast<const i::Address&>(data));
i::Tagged<i::Object> object(reinterpret_cast<const i::Address&>(data));
i::Isolate* isolate;
int hash = IsHeapObject(object) && i::GetIsolateFromHeapObject(
object.GetHeapObject(), &isolate)

View File

@ -8,6 +8,7 @@ use crate::AccessorNameGetterCallback;
use crate::AccessorNameSetterCallback;
use crate::Array;
use crate::Context;
use crate::Data;
use crate::GetPropertyNamesArgs;
use crate::HandleScope;
use crate::IndexFilter;
@ -141,7 +142,7 @@ extern "C" {
fn v8__Object__GetInternalField(
this: *const Object,
index: int,
) -> *const Value;
) -> *const Data;
fn v8__Object__GetAlignedPointerFromInternalField(
this: *const Object,
index: int,
@ -159,7 +160,7 @@ extern "C" {
fn v8__Object__SetInternalField(
this: *const Object,
index: int,
value: *const Value,
data: *const Data,
);
fn v8__Object__GetPrivate(
this: *const Object,
@ -623,13 +624,13 @@ impl Object {
usize::try_from(count).expect("bad internal field count") // Can't happen.
}
/// Gets the value from an internal field.
/// Gets the data from an internal field.
#[inline(always)]
pub fn get_internal_field<'s>(
&self,
scope: &mut HandleScope<'s>,
index: usize,
) -> Option<Local<'s, Value>> {
) -> Option<Local<'s, Data>> {
// Trying to access out-of-bounds internal fields makes V8 abort
// in debug mode and access out-of-bounds memory in release mode.
// The C++ API takes an i32 but doesn't check for indexes < 0, which
@ -681,17 +682,17 @@ impl Object {
.into()
}
/// Sets the value in an internal field. Returns false when the index
/// Sets the data in an internal field. Returns false when the index
/// is out of bounds, true otherwise.
#[inline(always)]
pub fn set_internal_field(&self, index: usize, value: Local<Value>) -> bool {
pub fn set_internal_field(&self, index: usize, data: Local<Data>) -> bool {
// Trying to access out-of-bounds internal fields makes V8 abort
// in debug mode and access out-of-bounds memory in release mode.
// The C++ API takes an i32 but doesn't check for indexes < 0, which
// results in an out-of-bounds access in both debug and release mode.
if index < self.internal_field_count() {
if let Ok(index) = int::try_from(index) {
unsafe { v8__Object__SetInternalField(self, index, &*value) };
unsafe { v8__Object__SetInternalField(self, index, &*data) };
return true;
}
}

View File

@ -6,17 +6,16 @@ use crate::Local;
use crate::TypedArray;
extern "C" {
fn v8__TypedArray__kMaxLength() -> size_t;
fn v8__TypedArray__kMaxByteLength() -> size_t;
fn v8__TypedArray__Length(this: *const TypedArray) -> size_t;
}
impl TypedArray {
/// The maximum length (in bytes) of the buffer backing a v8::TypedArray
/// instance. Attempting to create a v8::ArrayBuffer from a larger buffer will
/// result in a fatal error.
/// The largest supported typed array byte size. Each subclass defines a
/// type-specific max_length for the maximum length that can be passed to new.
#[inline(always)]
pub fn max_length() -> usize {
unsafe { v8__TypedArray__kMaxLength() }
pub fn max_byte_length() -> usize {
unsafe { v8__TypedArray__kMaxByteLength() }
}
/// Number of elements in this typed array
@ -28,7 +27,7 @@ impl TypedArray {
}
macro_rules! typed_array {
($name:ident, $func:ident) => {
($name:ident, $new_func:ident, $max_length_func:ident) => {
use crate::$name;
impl $name {
#[inline(always)]
@ -39,26 +38,64 @@ macro_rules! typed_array {
length: usize,
) -> Option<Local<'s, $name>> {
extern "C" {
fn $func(
fn $new_func(
buf_ptr: *const ArrayBuffer,
byte_offset: usize,
length: usize,
) -> *const $name;
}
unsafe { scope.cast_local(|_| $func(&*buf, byte_offset, length)) }
unsafe { scope.cast_local(|_| $new_func(&*buf, byte_offset, length)) }
}
#[doc = concat!("The largest ", stringify!($name), " size that can be constructed using `new`.")]
#[inline(always)]
pub fn max_length() -> usize {
extern "C" {
fn $max_length_func() -> usize;
}
unsafe { $max_length_func() }
}
}
};
}
typed_array!(Uint8Array, v8__Uint8Array__New);
typed_array!(Uint8ClampedArray, v8__Uint8ClampedArray__New);
typed_array!(Int8Array, v8__Int8Array__New);
typed_array!(Uint16Array, v8__Uint16Array__New);
typed_array!(Int16Array, v8__Int16Array__New);
typed_array!(Uint32Array, v8__Uint32Array__New);
typed_array!(Int32Array, v8__Int32Array__New);
typed_array!(Float32Array, v8__Float32Array__New);
typed_array!(Float64Array, v8__Float64Array__New);
typed_array!(BigUint64Array, v8__BigUint64Array__New);
typed_array!(BigInt64Array, v8__BigInt64Array__New);
typed_array!(Uint8Array, v8__Uint8Array__New, v8__Uint8Array__kMaxLength);
typed_array!(
Uint8ClampedArray,
v8__Uint8ClampedArray__New,
v8__Uint8ClampedArray__kMaxLength
);
typed_array!(Int8Array, v8__Int8Array__New, v8__Int8Array__kMaxLength);
typed_array!(
Uint16Array,
v8__Uint16Array__New,
v8__Uint16Array__kMaxLength
);
typed_array!(Int16Array, v8__Int16Array__New, v8__Int16Array__kMaxLength);
typed_array!(
Uint32Array,
v8__Uint32Array__New,
v8__Uint32Array__kMaxLength
);
typed_array!(Int32Array, v8__Int32Array__New, v8__Int32Array__kMaxLength);
typed_array!(
Float32Array,
v8__Float32Array__New,
v8__Float32Array__kMaxLength
);
typed_array!(
Float64Array,
v8__Float64Array__New,
v8__Float64Array__kMaxLength
);
typed_array!(
BigUint64Array,
v8__BigUint64Array__New,
v8__BigUint64Array__kMaxLength
);
typed_array!(
BigInt64Array,
v8__BigInt64Array__New,
v8__BigInt64Array__kMaxLength
);

View File

@ -1628,12 +1628,16 @@ fn object_template() {
assert!(!object.is_null_or_undefined());
assert_eq!(1, object.internal_field_count());
let value = object.get_internal_field(scope, 0).unwrap();
let data = object.get_internal_field(scope, 0).unwrap();
assert!(data.is_value());
let value: v8::Local<v8::Value> = data.try_into().unwrap();
assert!(value.is_undefined());
let fortytwo = v8::Integer::new(scope, 42).into();
assert!(object.set_internal_field(0, fortytwo));
let value = object.get_internal_field(scope, 0).unwrap();
let fortytwo: v8::Local<'_, v8::Value> = v8::Integer::new(scope, 42).into();
assert!(object.set_internal_field(0, fortytwo.into()));
let data = object.get_internal_field(scope, 0).unwrap();
assert!(data.is_value());
let value: v8::Local<v8::Value> = data.try_into().unwrap();
assert!(value.same_value(fortytwo));
let name = v8::String::new(scope, "g").unwrap();
@ -1861,12 +1865,13 @@ fn instance_template_with_internal_field() {
context.global(scope).set(scope, name.into(), val.into());
let new_instance = eval(scope, "new WithInternalField()").unwrap();
let internal_field = new_instance
let internal_field_data = new_instance
.to_object(scope)
.unwrap()
.get_internal_field(scope, 0)
.unwrap();
let internal_field: v8::Local<v8::Value> =
internal_field_data.try_into().unwrap();
assert_eq!(internal_field.integer_value(scope).unwrap(), 42);
}
@ -1892,7 +1897,12 @@ fn object_template_set_accessor() {
let expected_key = v8::String::new(scope, "key").unwrap();
assert!(key.strict_equals(expected_key.into()));
rv.set(this.get_internal_field(scope, 0).unwrap());
let internal_field = this
.get_internal_field(scope, 0)
.unwrap()
.try_into()
.unwrap();
rv.set(internal_field);
};
let setter = |scope: &mut v8::HandleScope,
@ -1910,7 +1920,7 @@ fn object_template_set_accessor() {
assert!(key.strict_equals(expected_key.into()));
assert!(value.is_int32());
assert!(this.set_internal_field(0, value));
assert!(this.set_internal_field(0, value.into()));
};
let getter_with_data =
@ -1928,7 +1938,12 @@ fn object_template_set_accessor() {
let expected_key = v8::String::new(scope, "key").unwrap();
assert!(key.strict_equals(expected_key.into()));
rv.set(this.get_internal_field(scope, 0).unwrap());
let internal_field = this
.get_internal_field(scope, 0)
.unwrap()
.try_into()
.unwrap();
rv.set(internal_field);
};
let setter_with_data = |scope: &mut v8::HandleScope,
@ -1947,7 +1962,7 @@ fn object_template_set_accessor() {
assert!(key.strict_equals(expected_key.into()));
assert!(value.is_int32());
assert!(this.set_internal_field(0, value));
assert!(this.set_internal_field(0, value.into()));
};
let key = v8::String::new(scope, "key").unwrap();
@ -1982,10 +1997,12 @@ fn object_template_set_accessor() {
);
let new_int = v8::Integer::new(scope, 9);
eval(scope, "obj.key = 9");
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(new_int.into()));
// Falls back on standard setter
assert!(eval(scope, "obj.key2 = null; obj.key2").unwrap().is_null());
@ -2010,10 +2027,12 @@ fn object_template_set_accessor() {
);
let new_int = v8::Integer::new(scope, 9);
eval(scope, "obj.key = 9");
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(new_int.into()));
// Falls back on standard setter
assert!(eval(scope, "obj.key2 = null; obj.key2").unwrap().is_null());
@ -2098,7 +2117,12 @@ fn object_template_set_named_property_handler() {
let expected_key = v8::String::new(scope, "key").unwrap();
assert!(key.strict_equals(expected_key.into()));
rv.set(this.get_internal_field(scope, 0).unwrap());
let internal_field = this
.get_internal_field(scope, 0)
.unwrap()
.try_into()
.unwrap();
rv.set(internal_field);
};
let setter = |scope: &mut v8::HandleScope,
@ -2126,7 +2150,7 @@ fn object_template_set_named_property_handler() {
assert!(key.strict_equals(expected_key.into()));
assert!(value.is_int32());
assert!(this.set_internal_field(0, value));
assert!(this.set_internal_field(0, value.into()));
rv.set_undefined();
};
@ -2156,10 +2180,12 @@ fn object_template_set_named_property_handler() {
// PropertyAttribute::READ_ONLY
rv.set_int32(1);
let expected_value = v8::Integer::new(scope, 42);
assert!(this
let internal_field: v8::Local<v8::Value> = this
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(expected_value.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(expected_value.into()));
};
let deleter = |scope: &mut v8::HandleScope,
@ -2192,10 +2218,12 @@ fn object_template_set_named_property_handler() {
// Validate is the current object.
let expected_value = v8::Integer::new(scope, 42);
assert!(this
let internal_field: v8::Local<v8::Value> = this
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(expected_value.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(expected_value.into()));
let key: v8::Local<v8::Name> =
v8::String::new(scope, "key").unwrap().into();
@ -2232,7 +2260,7 @@ fn object_template_set_named_property_handler() {
let value = desc.value();
assert!(value.is_int32());
assert!(this.set_internal_field(0, value));
assert!(this.set_internal_field(0, value.into()));
rv.set_undefined();
};
@ -2253,7 +2281,8 @@ fn object_template_set_named_property_handler() {
let descriptor = v8::Object::new(scope);
let value_key = v8::String::new(scope, "value").unwrap();
let value = this.get_internal_field(scope, 0).unwrap();
let data = this.get_internal_field(scope, 0).unwrap();
let value = data.try_into().unwrap();
descriptor.set(scope, value_key.into(), value);
let enumerable_key = v8::String::new(scope, "enumerable").unwrap();
let enumerable = v8::Boolean::new(scope, true);
@ -2290,10 +2319,12 @@ fn object_template_set_named_property_handler() {
assert!(eval(scope, "obj.fallthrough = 'a'; obj.fallthrough")
.unwrap()
.is_string());
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(int.into()));
// Getter + setter + deleter
let templ = v8::ObjectTemplate::new(scope);
@ -2314,18 +2345,30 @@ fn object_template_set_named_property_handler() {
);
let new_int = v8::Integer::new(scope, 9);
eval(scope, "obj.key = 9");
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(new_int.into()));
assert!(eval(scope, "delete obj.key").unwrap().boolean_value(scope));
assert!(obj.get_internal_field(scope, 0).unwrap().is_undefined());
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.try_into()
.unwrap();
assert!(internal_field.is_undefined());
assert!(eval(scope, "delete obj.key").unwrap().boolean_value(scope));
assert!(eval(scope, "obj.fallthrough = 'a'; obj.fallthrough")
.unwrap()
.is_string());
assert!(obj.get_internal_field(scope, 0).unwrap().is_undefined());
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.try_into()
.unwrap();
assert!(internal_field.is_undefined());
assert!(eval(scope, "delete obj.fallthrough")
.unwrap()
.boolean_value(scope));
@ -2403,10 +2446,12 @@ fn object_template_set_named_property_handler() {
"Object.defineProperty(obj, 'key', { value: 9, enumerable: true, configurable: true, writable: true })",
)
.unwrap();
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(new_int.into()));
assert!(eval(
scope,
"Object.defineProperty(obj, 'fallthrough', { value: 'a' }); obj.fallthrough"
@ -2535,7 +2580,12 @@ fn object_template_set_indexed_property_handler() {
let expected_index = 37;
assert!(index.eq(&expected_index));
rv.set(this.get_internal_field(scope, 0).unwrap());
let internal_field = this
.get_internal_field(scope, 0)
.unwrap()
.try_into()
.unwrap();
rv.set(internal_field);
};
let setter = |_scope: &mut v8::HandleScope,
@ -2552,7 +2602,7 @@ fn object_template_set_indexed_property_handler() {
assert_eq!(index, 37);
assert!(value.is_int32());
assert!(this.set_internal_field(0, value));
assert!(this.set_internal_field(0, value.into()));
rv.set_undefined();
};
@ -2591,10 +2641,12 @@ fn object_template_set_indexed_property_handler() {
// Validate is the current object.
let expected_value = v8::Integer::new(scope, 42);
assert!(this
let internal_field: v8::Local<v8::Value> = this
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(expected_value.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(expected_value.into()));
let key = v8::Integer::new(scope, 37);
let result = v8::Array::new_with_elements(scope, &[key.into()]);
@ -2618,7 +2670,7 @@ fn object_template_set_indexed_property_handler() {
assert!(!desc.has_set());
let value = desc.value();
this.set_internal_field(0, value);
this.set_internal_field(0, value.into());
rv.set_undefined();
};
@ -2633,7 +2685,8 @@ fn object_template_set_indexed_property_handler() {
let descriptor = v8::Object::new(scope);
let value_key = v8::String::new(scope, "value").unwrap();
let value = this.get_internal_field(scope, 0).unwrap();
let data = this.get_internal_field(scope, 0).unwrap();
let value = data.try_into().unwrap();
descriptor.set(scope, value_key.into(), value);
let enumerable_key = v8::String::new(scope, "enumerable").unwrap();
let enumerable = v8::Boolean::new(scope, true);
@ -2684,10 +2737,12 @@ fn object_template_set_indexed_property_handler() {
.set(scope, name.into(), obj.into());
let new_int = v8::Integer::new(scope, 9);
eval(scope, "obj[37] = 9");
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(new_int.into()));
assert!(!eval(scope, "delete obj[37]").unwrap().boolean_value(scope));
@ -2749,10 +2804,12 @@ fn object_template_set_indexed_property_handler() {
.global(scope)
.set(scope, name.into(), obj.into());
eval(scope, "Object.defineProperty(obj, 37, { value: 9 })").unwrap();
assert!(obj
let internal_field: v8::Local<v8::Value> = obj
.get_internal_field(scope, 0)
.unwrap()
.strict_equals(new_int.into()));
.try_into()
.unwrap();
assert!(internal_field.strict_equals(new_int.into()));
// Descriptor
let templ = v8::ObjectTemplate::new(scope);
@ -4197,12 +4254,13 @@ fn context_get_extras_binding_object() {
let extras_binding = context.get_extras_binding_object(scope);
assert!(extras_binding.is_object());
// Verify that Deno specific APIs are available on the extras object.
for builtin_name in &["fromUtf8", "toUtf8", "isOneByte"] {
let name = v8::String::new(scope, builtin_name).unwrap();
let value = extras_binding.get(scope, name.into()).unwrap();
assert!(value.is_function());
}
// Disabled for now because patch doesn't apply cleanly on v8 12.0
// // Verify that Deno specific APIs are available on the extras object.
// for builtin_name in &["fromUtf8", "toUtf8", "isOneByte"] {
// let name = v8::String::new(scope, builtin_name).unwrap();
// let value = extras_binding.get(scope, name.into()).unwrap();
// assert!(value.is_function());
// }
}
}
@ -5524,71 +5582,117 @@ fn typed_array_constructors() {
assert!(t.is_uint8_array());
assert_eq!(t.length(), 0);
// Uint8Array::max_length() ought to be 1 << 53 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 53) - 1, v8::Uint8Array::max_length());
let t = v8::Uint8ClampedArray::new(scope, ab, 0, 0).unwrap();
assert!(t.is_uint8_clamped_array());
assert_eq!(t.length(), 0);
// Uint8ClampedArray::max_length() ought to be 1 << 53 - 1 on 64 bits when
// heap sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 53) - 1, v8::Uint8ClampedArray::max_length());
let t = v8::Int8Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_int8_array());
assert_eq!(t.length(), 0);
// Int8Array::max_length() ought to be 1 << 53 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 53) - 1, v8::Int8Array::max_length());
let t = v8::Uint16Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_uint16_array());
assert_eq!(t.length(), 0);
// Uint16Array::max_length() ought to be 1 << 52 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 52) - 1, v8::Uint16Array::max_length());
let t = v8::Int16Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_int16_array());
assert_eq!(t.length(), 0);
// Int16Array::max_length() ought to be 1 << 52 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 52) - 1, v8::Int16Array::max_length());
let t = v8::Uint32Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_uint32_array());
assert_eq!(t.length(), 0);
// Uint32Array::max_length() ought to be 1 << 51 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 51) - 1, v8::Uint32Array::max_length());
let t = v8::Int32Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_int32_array());
assert_eq!(t.length(), 0);
// Int32Array::max_length() ought to be 1 << 51 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 51) - 1, v8::Int32Array::max_length());
let t = v8::Float32Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_float32_array());
assert_eq!(t.length(), 0);
// Float32Array::max_length() ought to be 1 << 51 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 51) - 1, v8::Float32Array::max_length());
let t = v8::Float64Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_float64_array());
assert_eq!(t.length(), 0);
// Float64Array::max_length() ought to be 1 << 50 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 50) - 1, v8::Float64Array::max_length());
let t = v8::BigUint64Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_big_uint64_array());
assert_eq!(t.length(), 0);
// BigUint64Array::max_length() ought to be 1 << 50 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 50) - 1, v8::BigUint64Array::max_length());
let t = v8::BigInt64Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_big_int64_array());
assert_eq!(t.length(), 0);
// TypedArray::max_length() ought to be >= 2^30 < 2^32 in 64 bits
// BigInt64Array::max_length() ought to be 1 << 50 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert!(((2 << 30)..(2 << 32)).contains(&v8::TypedArray::max_length()));
assert_eq!((1 << 50) - 1, v8::BigInt64Array::max_length());
// TypedArray::max_length() ought to be >= 2^28 < 2^30 in 32 bits
// TypedArray::max_byte_length() ought to be 1 << 53 - 1 on 64 bits when heap
// sandbox is disabled.
#[cfg(target_pointer_width = "64")]
assert_eq!((1 << 53) - 1, v8::TypedArray::max_byte_length());
// TypedArray::max_byte_length() ought to be >= 2^28 < 2^30 in 32 bits
#[cfg(target_pointer_width = "32")]
assert!(((2 << 28)..(2 << 30)).contains(&v8::TypedArray::max_length()));
assert!(((2 << 28)..(2 << 30)).contains(&v8::TypedArray::max_byte_length()));
// v8::ArrayBuffer::new raises a fatal if the length is > kMaxLength, so we test this behavior
// through the JS side of things, where a non-fatal RangeError is thrown in such cases.
{
let scope = &mut v8::TryCatch::new(scope);
let _ = eval(
scope,
&format!("new Uint8Array({})", v8::TypedArray::max_length()),
)
.unwrap();
assert!(!scope.has_caught());
}
{
let scope = &mut v8::TryCatch::new(scope);
eval(
scope,
&format!("new Uint8Array({})", v8::TypedArray::max_length() + 1),
&format!("new Uint8Array({})", v8::Uint8Array::max_length() + 1),
);
// Array is too big (> max_length) - expecting this threw a RangeError
assert!(scope.has_caught());

2
v8

@ -1 +1 @@
Subproject commit 39650ed07cb96533a601a8a9563d8e551be3bf06
Subproject commit b287115fa7c9f0323c43724eff14a173c41dc9e4