summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/ffi/00_ffi.js9
-rw-r--r--ext/ffi/lib.rs45
-rw-r--r--test_ffi/src/lib.rs2
-rw-r--r--test_ffi/tests/integration_tests.rs5
-rw-r--r--test_ffi/tests/test.js13
5 files changed, 68 insertions, 6 deletions
diff --git a/ext/ffi/00_ffi.js b/ext/ffi/00_ffi.js
index cdaf69e0d..ac8dda317 100644
--- a/ext/ffi/00_ffi.js
+++ b/ext/ffi/00_ffi.js
@@ -10,7 +10,6 @@
ObjectPrototypeIsPrototypeOf,
PromisePrototypeThen,
TypeError,
- Uint8Array,
} = window.__bootstrap.primordials;
function unpackU64([hi, lo]) {
@@ -107,9 +106,11 @@
}
getArrayBuffer(byteLength, offset = 0) {
- const uint8array = new Uint8Array(byteLength);
- this.copyInto(uint8array, offset);
- return uint8array.buffer;
+ return core.opSync(
+ "op_ffi_get_buf",
+ offset ? this.pointer + BigInt(offset) : this.pointer,
+ byteLength,
+ );
}
copyInto(destination, offset = 0) {
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index 05dcba362..396affdb3 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -165,6 +165,7 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
op_ffi_call_ptr::decl::<P>(),
op_ffi_call_ptr_nonblocking::decl::<P>(),
op_ffi_ptr_of::decl::<P>(),
+ op_ffi_get_buf::decl::<P>(),
op_ffi_buf_copy_into::decl::<P>(),
op_ffi_cstr_read::decl::<P>(),
op_ffi_read_u8::decl::<P>(),
@@ -1912,6 +1913,50 @@ where
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]
fn op_ffi_buf_copy_into<FP>(
state: &mut deno_core::OpState,
diff --git a/test_ffi/src/lib.rs b/test_ffi/src/lib.rs
index cde914c22..95b7d900c 100644
--- a/test_ffi/src/lib.rs
+++ b/test_ffi/src/lib.rs
@@ -393,4 +393,4 @@ pub struct Structure {
}
#[no_mangle]
-pub static static_ptr: Structure = Structure { _data: 42 };
+pub static mut static_ptr: Structure = Structure { _data: 42 };
diff --git a/test_ffi/tests/integration_tests.rs b/test_ffi/tests/integration_tests.rs
index 26de8ce0d..4a910a836 100644
--- a/test_ffi/tests/integration_tests.rs
+++ b/test_ffi/tests/integration_tests.rs
@@ -101,6 +101,11 @@ fn basic() {
Static i64: -1242464576485n\n\
Static ptr: true\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";
assert_eq!(stdout, expected);
assert_eq!(stderr, "");
diff --git a/test_ffi/tests/test.js b/test_ffi/tests/test.js
index ff81f302e..516182f6f 100644
--- a/test_ffi/tests/test.js
+++ b/test_ffi/tests/test.js
@@ -3,7 +3,9 @@
// 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 [libPrefix, libSuffix] = {
@@ -442,6 +444,15 @@ console.log(
const view = new Deno.UnsafePointerView(dylib.symbols.static_ptr);
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() {
dylib.close();
throwCallback.close();