feat: add bindings for String::kMaxLength and TypedArray::kMaxLength (#904)

This commit is contained in:
Romain Marcadier 2022-02-23 06:23:28 +01:00 committed by GitHub
parent fe447c88df
commit 2404d208f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 0 deletions

View File

@ -457,6 +457,8 @@ bool v8__Data__IsFunctionTemplate(const v8::Data& self) {
return self.IsFunctionTemplate(); return self.IsFunctionTemplate();
} }
size_t v8__TypedArray__kMaxLength() { return v8::TypedArray::kMaxLength; }
bool v8__Value__IsUndefined(const v8::Value& self) { bool v8__Value__IsUndefined(const v8::Value& self) {
return self.IsUndefined(); return self.IsUndefined();
} }
@ -849,6 +851,8 @@ int v8__Name__GetIdentityHash(const v8::Name& self) {
return ptr_to_local(&self)->GetIdentityHash(); return ptr_to_local(&self)->GetIdentityHash();
} }
size_t v8__String__kMaxLength() { return v8::String::kMaxLength; }
const v8::String* v8__String__Empty(v8::Isolate* isolate) { const v8::String* v8__String__Empty(v8::Isolate* isolate) {
return local_to_ptr(v8::String::Empty(isolate)); return local_to_ptr(v8::String::Empty(isolate));
} }

View File

@ -11,6 +11,8 @@ use crate::Local;
use crate::String; use crate::String;
extern "C" { extern "C" {
fn v8__String__kMaxLength() -> libc::size_t;
fn v8__String__Empty(isolate: *mut Isolate) -> *const String; fn v8__String__Empty(isolate: *mut Isolate) -> *const String;
fn v8__String__NewFromUtf8( fn v8__String__NewFromUtf8(
@ -115,6 +117,13 @@ bitflags! {
} }
impl String { impl String {
/// The maximum length (in bytes) of a buffer that a v8::String can be built
/// from. Attempting to create a v8::String from a larger buffer will result
/// in None being returned.
pub fn max_length() -> usize {
unsafe { v8__String__kMaxLength() }
}
pub fn empty<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, String> { pub fn empty<'s>(scope: &mut HandleScope<'s, ()>) -> Local<'s, String> {
// FIXME(bnoordhuis) v8__String__Empty() is infallible so there // FIXME(bnoordhuis) v8__String__Empty() is infallible so there
// is no need to box up the result, only to unwrap it again. // is no need to box up the result, only to unwrap it again.

View File

@ -2,6 +2,20 @@
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::HandleScope; use crate::HandleScope;
use crate::Local; use crate::Local;
use crate::TypedArray;
extern "C" {
fn v8__TypedArray__kMaxLength() -> libc::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.
pub fn max_length() -> usize {
unsafe { v8__TypedArray__kMaxLength() }
}
}
macro_rules! typed_array { macro_rules! typed_array {
($name:ident, $func:ident) => { ($name:ident, $func:ident) => {

View File

@ -236,6 +236,31 @@ fn test_string() {
assert_eq!(4, local.utf8_length(scope)); assert_eq!(4, local.utf8_length(scope));
assert_eq!("🦕", local.to_rust_string_lossy(scope)); assert_eq!("🦕", local.to_rust_string_lossy(scope));
} }
{
let scope = &mut v8::HandleScope::new(isolate);
let buffer = (0..v8::String::max_length() / 4)
.map(|_| '\u{10348}') // UTF8: 0xF0 0x90 0x8D 0x88
.collect::<String>();
let local = v8::String::new_from_utf8(
scope,
buffer.as_bytes(),
v8::NewStringType::Normal,
)
.unwrap();
// U+10348 is 2 UTF-16 code units, which is the unit of v8::String.length().
assert_eq!(v8::String::max_length() / 2, local.length());
assert_eq!(buffer, local.to_rust_string_lossy(scope));
let too_long = (0..(v8::String::max_length() / 4) + 1)
.map(|_| '\u{10348}') // UTF8: 0xF0 0x90 0x8D 0x88
.collect::<String>();
let none = v8::String::new_from_utf8(
scope,
too_long.as_bytes(),
v8::NewStringType::Normal,
);
assert!(none.is_none());
}
} }
#[test] #[test]
@ -3113,6 +3138,31 @@ fn typed_array_constructors() {
let t = v8::BigInt64Array::new(scope, ab, 0, 0).unwrap(); let t = v8::BigInt64Array::new(scope, ab, 0, 0).unwrap();
assert!(t.is_big_int64_array()); assert!(t.is_big_int64_array());
// TypedArray::max_length() ought to be >= 2^30 < 2^32
assert!(((2 << 30)..(2 << 32)).contains(&v8::TypedArray::max_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),
);
// Array is too big (> max_length) - expecting this threw a RangeError
assert!(scope.has_caught());
}
} }
#[test] #[test]