mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-26 00:59:28 -05:00
fix: better fix for empty Uint8Array (#1329)
This commit is contained in:
parent
97fab5ce0f
commit
bb5dadb418
2 changed files with 64 additions and 6 deletions
|
@ -267,13 +267,13 @@ impl<T: Default> FastApiTypedArray<T> {
|
|||
/// Returns a slice pointing to the underlying data if safe to do so.
|
||||
#[inline(always)]
|
||||
pub fn get_storage_if_aligned(&self) -> Option<&mut [T]> {
|
||||
// Ensure that we never create a null-ptr slice (even a zero-length null-ptr slice
|
||||
// is invalid because of Rust's niche packing).
|
||||
if self.data.is_null() {
|
||||
// V8 may provide an invalid or null pointer when length is zero, so we just
|
||||
// ignore that value completely and create an empty slice in this case.
|
||||
if self.length == 0 {
|
||||
return Some(&mut []);
|
||||
}
|
||||
// Ensure that we never return an unaligned buffer
|
||||
if (self.data as usize) % align_of::<T>() != 0 {
|
||||
// Ensure that we never return an unaligned or null buffer
|
||||
if self.data.is_null() || (self.data as usize) % align_of::<T>() != 0 {
|
||||
return None;
|
||||
}
|
||||
Some(unsafe { std::slice::from_raw_parts_mut(self.data, self.length) })
|
||||
|
|
|
@ -15,8 +15,8 @@ use std::ptr::{addr_of, NonNull};
|
|||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use v8::fast_api::CType;
|
||||
use v8::fast_api::Type::*;
|
||||
use v8::fast_api::{CType, FastApiTypedArray};
|
||||
use v8::inspector::ChannelBase;
|
||||
use v8::{fast_api, AccessorConfiguration};
|
||||
|
||||
|
@ -9566,6 +9566,64 @@ fn test_fast_calls() {
|
|||
assert_eq!("fast", unsafe { WHO });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fast_calls_empty_buffer() {
|
||||
static mut WHO: &str = "none";
|
||||
unsafe fn fast_fn(
|
||||
_recv: v8::Local<v8::Object>,
|
||||
buffer: *mut FastApiTypedArray<u8>,
|
||||
) {
|
||||
assert_eq!(WHO, "slow");
|
||||
WHO = "fast";
|
||||
assert_eq!(
|
||||
0,
|
||||
FastApiTypedArray::get_storage_from_pointer_if_aligned(buffer)
|
||||
.unwrap()
|
||||
.len()
|
||||
);
|
||||
}
|
||||
|
||||
fn slow_fn(
|
||||
_scope: &mut v8::HandleScope,
|
||||
_args: v8::FunctionCallbackArguments,
|
||||
_rv: v8::ReturnValue,
|
||||
) {
|
||||
unsafe {
|
||||
WHO = "slow";
|
||||
}
|
||||
}
|
||||
|
||||
const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new(
|
||||
&[V8Value, TypedArray(CType::Uint8)],
|
||||
fast_api::CType::Void,
|
||||
fast_fn as _,
|
||||
);
|
||||
|
||||
let _setup_guard = setup::parallel_test();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
let global = context.global(scope);
|
||||
|
||||
let template = v8::FunctionTemplate::builder(slow_fn)
|
||||
.build_fast(scope, &FAST_TEST, None, None, None);
|
||||
|
||||
let name = v8::String::new(scope, "func").unwrap();
|
||||
let value = template.get_function(scope).unwrap();
|
||||
global.set(scope, name.into(), value.into()).unwrap();
|
||||
let source = r#"
|
||||
function f(arr) { func(arr); }
|
||||
%PrepareFunctionForOptimization(f);
|
||||
f(new Uint8Array(0));
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
f(new Uint8Array(0));
|
||||
"#;
|
||||
eval(scope, source).unwrap();
|
||||
assert_eq!(unsafe { WHO }, "fast");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fast_calls_sequence() {
|
||||
static mut WHO: &str = "none";
|
||||
|
|
Loading…
Reference in a new issue