mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
feat(ext/ffi): Add support to get ArrayBuffers from UnsafePointerView (#15143)
This commit is contained in:
parent
2843160fc7
commit
e1cbd2364f
5 changed files with 68 additions and 6 deletions
|
@ -10,7 +10,6 @@
|
||||||
ObjectPrototypeIsPrototypeOf,
|
ObjectPrototypeIsPrototypeOf,
|
||||||
PromisePrototypeThen,
|
PromisePrototypeThen,
|
||||||
TypeError,
|
TypeError,
|
||||||
Uint8Array,
|
|
||||||
} = window.__bootstrap.primordials;
|
} = window.__bootstrap.primordials;
|
||||||
|
|
||||||
function unpackU64([hi, lo]) {
|
function unpackU64([hi, lo]) {
|
||||||
|
@ -107,9 +106,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
getArrayBuffer(byteLength, offset = 0) {
|
getArrayBuffer(byteLength, offset = 0) {
|
||||||
const uint8array = new Uint8Array(byteLength);
|
return core.opSync(
|
||||||
this.copyInto(uint8array, offset);
|
"op_ffi_get_buf",
|
||||||
return uint8array.buffer;
|
offset ? this.pointer + BigInt(offset) : this.pointer,
|
||||||
|
byteLength,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
copyInto(destination, offset = 0) {
|
copyInto(destination, offset = 0) {
|
||||||
|
|
|
@ -165,6 +165,7 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
|
||||||
op_ffi_call_ptr::decl::<P>(),
|
op_ffi_call_ptr::decl::<P>(),
|
||||||
op_ffi_call_ptr_nonblocking::decl::<P>(),
|
op_ffi_call_ptr_nonblocking::decl::<P>(),
|
||||||
op_ffi_ptr_of::decl::<P>(),
|
op_ffi_ptr_of::decl::<P>(),
|
||||||
|
op_ffi_get_buf::decl::<P>(),
|
||||||
op_ffi_buf_copy_into::decl::<P>(),
|
op_ffi_buf_copy_into::decl::<P>(),
|
||||||
op_ffi_cstr_read::decl::<P>(),
|
op_ffi_cstr_read::decl::<P>(),
|
||||||
op_ffi_read_u8::decl::<P>(),
|
op_ffi_read_u8::decl::<P>(),
|
||||||
|
@ -1912,6 +1913,50 @@ where
|
||||||
Ok(big_int.into())
|
Ok(big_int.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn noop_deleter_callback(
|
||||||
|
_data: *mut c_void,
|
||||||
|
_byte_length: usize,
|
||||||
|
_deleter_data: *mut c_void,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op(v8)]
|
||||||
|
fn op_ffi_get_buf<FP, 'scope>(
|
||||||
|
scope: &mut v8::HandleScope<'scope>,
|
||||||
|
state: &mut deno_core::OpState,
|
||||||
|
src: serde_v8::Value<'scope>,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<serde_v8::Value<'scope>, AnyError>
|
||||||
|
where
|
||||||
|
FP: FfiPermissions + 'static,
|
||||||
|
{
|
||||||
|
check_unstable(state, "Deno.UnsafePointerView#arrayBuffer");
|
||||||
|
|
||||||
|
let permissions = state.borrow_mut::<FP>();
|
||||||
|
permissions.check(None)?;
|
||||||
|
|
||||||
|
let value = v8::Local::<v8::BigInt>::try_from(src.v8_value)
|
||||||
|
.map_err(|_| type_error("Invalid FFI pointer value, expected BigInt"))?;
|
||||||
|
let ptr = value.u64_value().0 as usize as *mut c_void;
|
||||||
|
if std::ptr::eq(ptr, std::ptr::null()) {
|
||||||
|
return Err(type_error("Invalid FFI pointer value, got nullptr"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: Trust the user to have provided a real pointer, and a valid matching size to it. Since this is a foreign pointer, we should not do any deletion.
|
||||||
|
let backing_store = unsafe {
|
||||||
|
v8::ArrayBuffer::new_backing_store_from_ptr(
|
||||||
|
ptr,
|
||||||
|
len,
|
||||||
|
noop_deleter_callback,
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.make_shared();
|
||||||
|
let array_buffer: v8::Local<v8::Value> =
|
||||||
|
v8::ArrayBuffer::with_backing_store(scope, &backing_store).into();
|
||||||
|
Ok(array_buffer.into())
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_ffi_buf_copy_into<FP>(
|
fn op_ffi_buf_copy_into<FP>(
|
||||||
state: &mut deno_core::OpState,
|
state: &mut deno_core::OpState,
|
||||||
|
|
|
@ -393,4 +393,4 @@ pub struct Structure {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub static static_ptr: Structure = Structure { _data: 42 };
|
pub static mut static_ptr: Structure = Structure { _data: 42 };
|
||||||
|
|
|
@ -101,6 +101,11 @@ fn basic() {
|
||||||
Static i64: -1242464576485n\n\
|
Static i64: -1242464576485n\n\
|
||||||
Static ptr: true\n\
|
Static ptr: true\n\
|
||||||
Static ptr value: 42\n\
|
Static ptr value: 42\n\
|
||||||
|
arrayBuffer.byteLength: 4\n\
|
||||||
|
uint32Array.length: 1\n\
|
||||||
|
uint32Array[0]: 42\n\
|
||||||
|
uint32Array[0] after mutation: 55\n\
|
||||||
|
Static ptr value after mutation: 55\n\
|
||||||
Correct number of resources\n";
|
Correct number of resources\n";
|
||||||
assert_eq!(stdout, expected);
|
assert_eq!(stdout, expected);
|
||||||
assert_eq!(stderr, "");
|
assert_eq!(stderr, "");
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
// Run using cargo test or `--v8-options=--allow-natives-syntax`
|
// Run using cargo test or `--v8-options=--allow-natives-syntax`
|
||||||
|
|
||||||
import { assertThrows } from "../../test_util/std/testing/asserts.ts";
|
import {
|
||||||
|
assertThrows,
|
||||||
|
} from "../../test_util/std/testing/asserts.ts";
|
||||||
|
|
||||||
const targetDir = Deno.execPath().replace(/[^\/\\]+$/, "");
|
const targetDir = Deno.execPath().replace(/[^\/\\]+$/, "");
|
||||||
const [libPrefix, libSuffix] = {
|
const [libPrefix, libSuffix] = {
|
||||||
|
@ -442,6 +444,15 @@ console.log(
|
||||||
const view = new Deno.UnsafePointerView(dylib.symbols.static_ptr);
|
const view = new Deno.UnsafePointerView(dylib.symbols.static_ptr);
|
||||||
console.log("Static ptr value:", view.getUint32());
|
console.log("Static ptr value:", view.getUint32());
|
||||||
|
|
||||||
|
const arrayBuffer = view.getArrayBuffer(4);
|
||||||
|
const uint32Array = new Uint32Array(arrayBuffer);
|
||||||
|
console.log("arrayBuffer.byteLength:", arrayBuffer.byteLength);
|
||||||
|
console.log("uint32Array.length:", uint32Array.length);
|
||||||
|
console.log("uint32Array[0]:", uint32Array[0]);
|
||||||
|
uint32Array[0] = 55; // MUTATES!
|
||||||
|
console.log("uint32Array[0] after mutation:", uint32Array[0]);
|
||||||
|
console.log("Static ptr value after mutation:", view.getUint32());
|
||||||
|
|
||||||
(function cleanup() {
|
(function cleanup() {
|
||||||
dylib.close();
|
dylib.close();
|
||||||
throwCallback.close();
|
throwCallback.close();
|
||||||
|
|
Loading…
Add table
Reference in a new issue