Skip to content

Commit

Permalink
feat: implement ToV8 for all TypedArray types (#1032)
Browse files Browse the repository at this point in the history
allows returning any Vec/Box type which corresponds to a TypedArray
  • Loading branch information
devsnek authored Jan 7, 2025
1 parent 8d7bfea commit 7d5a499
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 24 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ serde_v8 = { version = "0.237.0", path = "./serde_v8" }
deno_ast = { version = "=0.40.0", features = ["transpiling"] }
deno_core_icudata = "0.74.0"
deno_unsync = "0.4.1"
v8 = { version = "130.0.5", default-features = false }
v8 = { version = "130.0.6", default-features = false }

anyhow = "1"
bencher = "0.1"
Expand All @@ -45,6 +45,7 @@ libc = "0.2.126"
memoffset = ">=0.9"
num-bigint = { version = "0.4", features = ["rand"] }
parking_lot = "0.12.0"
paste = "1.0"
percent-encoding = "2.3.0"
pin-project = "1"
pretty_assertions = "1.3.0"
Expand Down
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ bencher.workspace = true
criterion.workspace = true
deno_ast.workspace = true
fastrand.workspace = true
paste.workspace = true
pretty_assertions.workspace = true
rstest.workspace = true
twox-hash.workspace = true
Expand Down
58 changes: 58 additions & 0 deletions core/runtime/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,15 @@ mod tests {
op_smi_to_from_v8,
op_number_to_from_v8,
op_bool_to_from_v8,

op_create_buf_u8,
op_create_buf_u16,
op_create_buf_u32,
op_create_buf_u64,
op_create_buf_i8,
op_create_buf_i16,
op_create_buf_i32,
op_create_buf_i64,
],
state = |state| {
state.put(1234u32);
Expand Down Expand Up @@ -2499,4 +2508,53 @@ mod tests {
);
Ok(())
}

macro_rules! op_create_buf {
($size:ident) => {
paste::paste! {
#[op2]
#[buffer]
fn [< op_create_buf_ $size >] () -> Vec<$size> {
vec![1, 2, 3, 4]
}
}
};
}
op_create_buf!(u8);
op_create_buf!(u16);
op_create_buf!(u32);
op_create_buf!(u64);
op_create_buf!(i8);
op_create_buf!(i16);
op_create_buf!(i32);
op_create_buf!(i64);

#[test]
fn return_buffers() -> Result<(), Box<dyn std::error::Error>> {
fn test(size: &str) -> Result<(), Box<dyn std::error::Error>> {
run_test2(
1,
&format!("op_create_buf_{size}"),
&format!(
r"
let buf = op_create_buf_{size}();
assert(Number(buf[0]) === 1);
assert(Number(buf[1]) === 2);
assert(Number(buf[2]) === 3);
assert(Number(buf[3]) === 4);
"
),
)?;
Ok(())
}
test("u8")?;
test("u16")?;
test("u32")?;
test("u64")?;
test("i8")?;
test("i16")?;
test("i32")?;
test("i64")?;
Ok(())
}
}
56 changes: 36 additions & 20 deletions core/runtime/ops_rust_to_v8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,26 +347,6 @@ to_v8!(RustToV8Marker<ArrayBufferMarker, serde_v8::JsBuffer>: |value, scope| {
to_v8_fallible!(serde_v8::JsBuffer: |value, scope| {
value.into_parts().to_v8_fallible(scope)
});
to_v8!(RustToV8Marker<ArrayBufferMarker, Box<[u8]>>: |buf, scope| {
let buf = buf.0;
if buf.is_empty() {
v8::ArrayBuffer::new(scope, 0)
} else {
let backing_store =
v8::ArrayBuffer::new_backing_store_from_boxed_slice(buf);
let backing_store_shared = backing_store.make_shared();
v8::ArrayBuffer::with_backing_store(scope, &backing_store_shared)
}
});
to_v8_fallible!(Box<[u8]>: |buf, scope| {
let len = buf.len();
let ab = unsafe { v8::Local::cast_unchecked(RustToV8Marker::<ArrayBufferMarker, _>::from(buf).to_v8(scope)) };
v8::Uint8Array::new(scope, ab, 0, len).ok_or_else(|| serde_v8::Error::Message("failed to allocate array".into()))
});
to_v8!(RustToV8Marker<ArrayBufferMarker, Vec<u8>>: |value, scope| {
RustToV8Marker::<ArrayBufferMarker, _>::from(value.0.into_boxed_slice()).to_v8(scope)
});
to_v8_fallible!(Vec<u8>: |value, scope| value.into_boxed_slice().to_v8_fallible(scope));
to_v8!(RustToV8Marker<ArrayBufferMarker, BytesMut>: |value, scope| {
let value = value.0;
let ptr = value.as_ptr();
Expand All @@ -393,6 +373,42 @@ to_v8_fallible!(BytesMut: |buf, scope| {
v8::Uint8Array::new(scope, ab, 0, len).ok_or_else(|| serde_v8::Error::Message("failed to allocate array".into()))
});

macro_rules! typedarray {
($rty:ty, $v8ty:ident) => {
to_v8!(RustToV8Marker<ArrayBufferMarker, Box<[$rty]>>: |buf, scope| {
let buf = buf.0;
if buf.is_empty() {
v8::ArrayBuffer::new(scope, 0)
} else {
let backing_store =
v8::ArrayBuffer::new_backing_store_from_bytes(buf);
let backing_store_shared = backing_store.make_shared();
v8::ArrayBuffer::with_backing_store(scope, &backing_store_shared)
}
});
to_v8_fallible!(Box<[$rty]>: |buf, scope| {
let len = buf.len();
let ab = unsafe {
v8::Local::cast_unchecked(RustToV8Marker::<ArrayBufferMarker, _>::from(buf).to_v8(scope))
};
v8::$v8ty::new(scope, ab, 0, len).ok_or_else(|| serde_v8::Error::Message("failed to allocate array".into()))
});
to_v8!(RustToV8Marker<ArrayBufferMarker, Vec<$rty>>: |value, scope| {
RustToV8Marker::<ArrayBufferMarker, _>::from(value.0.into_boxed_slice()).to_v8(scope)
});
to_v8_fallible!(Vec<$rty>: |value, scope| value.into_boxed_slice().to_v8_fallible(scope));
}
}

typedarray!(u8, Uint8Array);
typedarray!(u16, Uint16Array);
typedarray!(u32, Uint32Array);
typedarray!(u64, BigUint64Array);
typedarray!(i8, Int8Array);
typedarray!(i16, Int16Array);
typedarray!(i32, Int32Array);
typedarray!(i64, BigInt64Array);

//
// Serde
//
Expand Down
2 changes: 1 addition & 1 deletion core/runtime/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn v8_init(
v8::V8::initialize_platform(v8_platform.clone());
v8::V8::initialize();

v8::cppgc::initalize_process(v8_platform);
v8::cppgc::initialize_process(v8_platform);
}

pub fn init_v8(
Expand Down

0 comments on commit 7d5a499

Please sign in to comment.