napi-rs/examples/napi-compat-mode/src/arraybuffer.rs
nihohit 1cf32631bf
fix(napi): typed arrays ref shouldn't use offset. (#1376)
Notice from the n-api docs that the data returned from
`napi_get_typedarray_info` is already adjusted by the byte offset.
https://nodejs.org/api/n-api.html#napi_get_typedarray_info

This means that when `as_ref`/`as_mut` apply the byte offset, the
offset is in practice applied twice.
This wasn't caught in tests because no test tried to modify a typed
array with a byte offset, and the test didn't us the typed array
structs, only `JsTypedArray`. If you want, I can modify the rest of the
functions in examples/napi-compt-mode/src/arraybuffers.rs
and the matching tests, to test all typed arrays.

IMO the `byte_offset` field can be removed entirely from the struct,
but I wanted to submit a minimal PR.
2022-11-30 20:54:13 +08:00

74 lines
2.5 KiB
Rust

use std::f64::consts::PI;
use std::str;
use napi::{
bindgen_prelude::Uint8Array, CallContext, JsArrayBuffer, JsNumber, JsObject, JsTypedArray,
JsUndefined, Result,
};
#[js_function(1)]
pub fn get_arraybuffer_length(ctx: CallContext) -> Result<JsNumber> {
let buffer = ctx.get::<JsArrayBuffer>(0)?.into_value()?;
ctx.env.create_uint32(buffer.len() as u32)
}
#[js_function(1)]
pub fn mutate_uint8_array(ctx: CallContext) -> Result<JsUndefined> {
let mut buffer = ctx.get::<Uint8Array>(0)?;
let buffer_mut_ref: &mut [u8] = buffer.as_mut();
buffer_mut_ref[0] = 42;
ctx.env.get_undefined()
}
#[js_function(1)]
pub fn mutate_uint16_array(ctx: CallContext) -> Result<JsUndefined> {
let mut buffer = ctx.get::<JsTypedArray>(0)?.into_value()?;
let buffer_mut_ref: &mut [u16] = buffer.as_mut();
buffer_mut_ref[0] = 65535;
ctx.env.get_undefined()
}
#[js_function(1)]
pub fn mutate_int16_array(ctx: CallContext) -> Result<JsUndefined> {
let mut buffer = ctx.get::<JsTypedArray>(0)?.into_value()?;
let buffer_mut_ref: &mut [i16] = buffer.as_mut();
buffer_mut_ref[0] = 32767;
ctx.env.get_undefined()
}
#[js_function(1)]
pub fn mutate_float32_array(ctx: CallContext) -> Result<JsUndefined> {
let mut buffer = ctx.get::<JsTypedArray>(0)?.into_value()?;
let buffer_mut_ref: &mut [f32] = buffer.as_mut();
buffer_mut_ref[0] = 3.33;
ctx.env.get_undefined()
}
#[js_function(1)]
pub fn mutate_float64_array(ctx: CallContext) -> Result<JsUndefined> {
let mut buffer = ctx.get::<JsTypedArray>(0)?.into_value()?;
let buffer_mut_ref: &mut [f64] = buffer.as_mut();
buffer_mut_ref[0] = PI;
ctx.env.get_undefined()
}
#[js_function(1)]
#[cfg(feature = "latest")]
pub fn mutate_i64_array(ctx: CallContext) -> Result<JsUndefined> {
let mut buffer = ctx.get::<JsTypedArray>(0)?.into_value()?;
let buffer_mut_ref: &mut [i64] = buffer.as_mut();
buffer_mut_ref[0] = 9223372036854775807;
ctx.env.get_undefined()
}
pub fn register_js(exports: &mut JsObject) -> Result<()> {
exports.create_named_method("getArraybufferLength", get_arraybuffer_length)?;
exports.create_named_method("mutateUint8Array", mutate_uint8_array)?;
exports.create_named_method("mutateUint16Array", mutate_uint16_array)?;
exports.create_named_method("mutateInt16Array", mutate_int16_array)?;
exports.create_named_method("mutateFloat32Array", mutate_float32_array)?;
exports.create_named_method("mutateFloat64Array", mutate_float64_array)?;
#[cfg(feature = "latest")]
exports.create_named_method("mutateI64Array", mutate_i64_array)?;
Ok(())
}