summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/ffi/00_ffi.js24
-rw-r--r--ext/ffi/lib.rs49
-rw-r--r--test_ffi/tests/bench.js14
3 files changed, 66 insertions, 21 deletions
diff --git a/ext/ffi/00_ffi.js b/ext/ffi/00_ffi.js
index 22e442e51..cdaf69e0d 100644
--- a/ext/ffi/00_ffi.js
+++ b/ext/ffi/00_ffi.js
@@ -32,77 +32,77 @@
getUint8(offset = 0) {
return core.opSync(
"op_ffi_read_u8",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getInt8(offset = 0) {
return core.opSync(
"op_ffi_read_i8",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getUint16(offset = 0) {
return core.opSync(
"op_ffi_read_u16",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getInt16(offset = 0) {
return core.opSync(
"op_ffi_read_i16",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getUint32(offset = 0) {
return core.opSync(
"op_ffi_read_u32",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getInt32(offset = 0) {
return core.opSync(
"op_ffi_read_i32",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getBigUint64(offset = 0) {
return core.opSync(
"op_ffi_read_u64",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getBigInt64(offset = 0) {
return core.opSync(
"op_ffi_read_u64",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getFloat32(offset = 0) {
return core.opSync(
"op_ffi_read_f32",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getFloat64(offset = 0) {
return core.opSync(
"op_ffi_read_f64",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
getCString(offset = 0) {
return core.opSync(
"op_ffi_cstr_read",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
);
}
@@ -115,7 +115,7 @@
copyInto(destination, offset = 0) {
core.opSync(
"op_ffi_buf_copy_into",
- this.pointer + BigInt(offset),
+ offset ? this.pointer + BigInt(offset) : this.pointer,
destination,
destination.byteLength,
);
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index 926d88ac7..05dcba362 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -1873,7 +1873,7 @@ fn op_ffi_call_nonblocking<'scope>(
fn op_ffi_ptr_of<FP, 'scope>(
scope: &mut v8::HandleScope<'scope>,
state: &mut deno_core::OpState,
- buf: ZeroCopyBuf,
+ buf: serde_v8::Value<'scope>,
) -> Result<serde_v8::Value<'scope>, AnyError>
where
FP: FfiPermissions + 'static,
@@ -1882,8 +1882,33 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ let pointer = if let Ok(value) =
+ v8::Local::<v8::ArrayBufferView>::try_from(buf.v8_value)
+ {
+ let backing_store = value
+ .buffer(scope)
+ .ok_or_else(|| {
+ type_error("Invalid FFI ArrayBufferView, expected data in the buffer")
+ })?
+ .get_backing_store();
+ let byte_offset = value.byte_offset();
+ if byte_offset > 0 {
+ &backing_store[byte_offset..] as *const _ as *const u8
+ } else {
+ &backing_store[..] as *const _ as *const u8
+ }
+ } else if let Ok(value) = v8::Local::<v8::ArrayBuffer>::try_from(buf.v8_value)
+ {
+ let backing_store = value.get_backing_store();
+ &backing_store[..] as *const _ as *const u8
+ } else {
+ return Err(type_error(
+ "Invalid FFI buffer, expected ArrayBuffer, or ArrayBufferView",
+ ));
+ };
+
let big_int: v8::Local<v8::Value> =
- v8::BigInt::new_from_u64(scope, buf.as_ptr() as u64).into();
+ v8::BigInt::new_from_u64(scope, pointer as u64).into();
Ok(big_int.into())
}
@@ -1915,11 +1940,12 @@ where
}
}
-#[op]
-fn op_ffi_cstr_read<FP>(
+#[op(v8)]
+fn op_ffi_cstr_read<FP, 'scope>(
+ scope: &mut v8::HandleScope<'scope>,
state: &mut deno_core::OpState,
ptr: u64,
-) -> Result<String, AnyError>
+) -> Result<serde_v8::Value<'scope>, AnyError>
where
FP: FfiPermissions + 'static,
{
@@ -1928,10 +1954,15 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
- let ptr = ptr as *const c_char;
- // SAFETY: ptr is user provided
- // lifetime validity is not an issue because we allocate a new string.
- Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string())
+ // SAFETY: Pointer is user provided.
+ let cstr = unsafe { CStr::from_ptr(ptr as *const c_char) }.to_bytes();
+ let value: v8::Local<v8::Value> =
+ v8::String::new_from_utf8(scope, cstr, v8::NewStringType::Normal)
+ .ok_or_else(|| {
+ type_error("Invalid CString pointer, string exceeds max length")
+ })?
+ .into();
+ Ok(value.into())
}
#[op]
diff --git a/test_ffi/tests/bench.js b/test_ffi/tests/bench.js
index 54a9e0acc..165b395e2 100644
--- a/test_ffi/tests/bench.js
+++ b/test_ffi/tests/bench.js
@@ -571,3 +571,17 @@ Deno.bench("nop_many_parameters_nonblocking()", () => {
buffer2,
);
});
+
+Deno.bench("Deno.UnsafePointer.of", () => {
+ Deno.UnsafePointer.of(buffer);
+});
+
+const cstringBuffer = new TextEncoder().encode("Best believe it!\0");
+// Make sure the buffer does not get collected
+globalThis.cstringBuffer = cstringBuffer;
+const cstringPointerView = new Deno.UnsafePointerView(
+ Deno.UnsafePointer.of(cstringBuffer),
+);
+Deno.bench("Deno.UnsafePointerView#getCString", () => {
+ cstringPointerView.getCString();
+});