Browse Source

Feature `JsTypedArray`s (#2003)

This PR adds a wrapper around the raw builtins for JavaScript typed arrays, like #1746
pull/2031/head
Halid Odat 2 years ago
parent
commit
17aa57040d
  1. 140
      boa_engine/src/builtins/typed_array/mod.rs
  2. 394
      boa_engine/src/object/jstypedarray.rs
  3. 2
      boa_engine/src/object/mod.rs
  4. 42
      boa_engine/src/value/conversions.rs
  5. 46
      boa_examples/src/bin/jstypedarray.rs

140
boa_engine/src/builtins/typed_array/mod.rs

@ -114,7 +114,7 @@ macro_rules! typed_array {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray
fn constructor(
pub(crate) fn constructor(
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
@ -549,7 +549,7 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.at
fn at(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn at(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -622,7 +622,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.bytelength
fn byte_length(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn byte_length(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
@ -651,7 +655,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.byteoffset
fn byte_offset(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn byte_offset(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
@ -877,7 +885,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.every
fn every(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn every(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -936,7 +948,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill
fn fill(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn fill(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1016,7 +1032,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
fn filter(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn filter(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1097,7 +1117,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.find
fn find(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn find(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1155,7 +1179,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex
fn findindex(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn findindex(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1212,7 +1240,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach
fn foreach(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn foreach(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1264,7 +1296,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes
fn includes(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn includes(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1337,7 +1373,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof
fn index_of(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn index_of(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1419,7 +1459,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
fn join(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn join(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1476,7 +1520,7 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys
fn keys(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn keys(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let o = this
@ -1504,7 +1548,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof
fn last_index_of(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn last_index_of(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1578,7 +1626,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.length
fn length(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn length(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
// 3. Assert: O has [[ViewedArrayBuffer]] and [[ArrayLength]] internal slots.
@ -1607,7 +1659,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.map
fn map(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn map(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1665,7 +1721,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
fn reduce(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn reduce(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1742,7 +1802,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright
fn reduceright(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn reduceright(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1822,7 +1886,11 @@ impl TypedArray {
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
#[allow(clippy::float_cmp)]
fn reverse(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn reverse(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -1877,7 +1945,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.set
fn set(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn set(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let target be the this value.
// 2. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
// 3. Assert: target has a [[ViewedArrayBuffer]] internal slot.
@ -2255,7 +2327,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice
fn slice(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn slice(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -2420,7 +2496,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.some
fn some(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn some(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
let obj = this
@ -2478,7 +2558,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
fn sort(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn sort(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
let compare_fn = match args.get(0) {
None | Some(JsValue::Undefined) => None,
@ -2686,7 +2770,11 @@ impl TypedArray {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray
fn subarray(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn subarray(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
@ -2951,7 +3039,7 @@ impl TypedArray {
}
/// <https://tc39.es/ecma262/#sec-initializetypedarrayfromlist>
fn initialize_from_list(
pub(crate) fn initialize_from_list(
o: &JsObject,
values: Vec<JsValue>,
context: &mut Context,

394
boa_engine/src/object/jstypedarray.rs

@ -0,0 +1,394 @@
use crate::{
builtins::typed_array::TypedArray,
object::{JsArray, JsObject, JsObjectType},
value::IntoOrUndefined,
Context, JsResult, JsString, JsValue,
};
use boa_gc::{Finalize, Trace};
use std::ops::Deref;
/// JavaScript `TypedArray` rust object.
#[derive(Debug, Clone, Trace, Finalize)]
pub struct JsTypedArray {
inner: JsValue,
}
impl JsTypedArray {
#[inline]
pub fn from_object(object: JsObject, context: &mut Context) -> JsResult<Self> {
if object.borrow().is_typed_array() {
Ok(Self {
inner: object.into(),
})
} else {
context.throw_type_error("object is not an TypedArray")
}
}
/// Get the length of the array.
///
/// Same a `array.length` in JavaScript.
#[inline]
pub fn length(&self, context: &mut Context) -> JsResult<usize> {
Ok(TypedArray::length(&self.inner, &[], context)?
.as_number()
.map(|x| x as usize)
.expect("length should return a number"))
}
/// Check if the array is empty, i.e. the `length` is zero.
#[inline]
pub fn is_empty(&self, context: &mut Context) -> JsResult<bool> {
Ok(self.length(context)? == 0)
}
#[inline]
pub fn at<T>(&self, index: T, context: &mut Context) -> JsResult<JsValue>
where
T: Into<i64>,
{
TypedArray::at(&self.inner, &[index.into().into()], context)
}
#[inline]
pub fn byte_length(&self, context: &mut Context) -> JsResult<usize> {
Ok(TypedArray::byte_length(&self.inner, &[], context)?
.as_number()
.map(|x| x as usize)
.expect("byteLength should return a number"))
}
#[inline]
pub fn byte_offset(&self, context: &mut Context) -> JsResult<usize> {
Ok(TypedArray::byte_offset(&self.inner, &[], context)?
.as_number()
.map(|x| x as usize)
.expect("byteLength should return a number"))
}
#[inline]
pub fn fill<T>(
&self,
value: T,
start: Option<usize>,
end: Option<usize>,
context: &mut Context,
) -> JsResult<Self>
where
T: Into<JsValue>,
{
TypedArray::fill(
&self.inner,
&[
value.into(),
start.into_or_undefined(),
end.into_or_undefined(),
],
context,
)?;
Ok(self.clone())
}
pub fn every(
&self,
predicate: JsObject,
this_arg: Option<JsValue>,
context: &mut Context,
) -> JsResult<bool> {
let result = TypedArray::every(
&self.inner,
&[predicate.into(), this_arg.into_or_undefined()],
context,
)?
.as_boolean()
.expect("TypedArray.prototype.every should always return boolean");
Ok(result)
}
#[inline]
pub fn some(
&self,
callback: JsObject,
this_arg: Option<JsValue>,
context: &mut Context,
) -> JsResult<bool> {
let result = TypedArray::some(
&self.inner,
&[callback.into(), this_arg.into_or_undefined()],
context,
)?
.as_boolean()
.expect("TypedArray.prototype.some should always return boolean");
Ok(result)
}
#[inline]
pub fn sort(&self, compare_fn: Option<JsObject>, context: &mut Context) -> JsResult<Self> {
TypedArray::sort(&self.inner, &[compare_fn.into_or_undefined()], context)?;
Ok(self.clone())
}
#[inline]
pub fn filter(
&self,
callback: JsObject,
this_arg: Option<JsValue>,
context: &mut Context,
) -> JsResult<Self> {
let object = TypedArray::filter(
&self.inner,
&[callback.into(), this_arg.into_or_undefined()],
context,
)?;
Ok(Self { inner: object })
}
#[inline]
pub fn map(
&self,
callback: JsObject,
this_arg: Option<JsValue>,
context: &mut Context,
) -> JsResult<Self> {
let object = TypedArray::map(
&self.inner,
&[callback.into(), this_arg.into_or_undefined()],
context,
)?;
Ok(Self { inner: object })
}
#[inline]
pub fn reduce(
&self,
callback: JsObject,
initial_value: Option<JsValue>,
context: &mut Context,
) -> JsResult<JsValue> {
TypedArray::reduce(
&self.inner,
&[callback.into(), initial_value.into_or_undefined()],
context,
)
}
#[inline]
pub fn reduce_right(
&self,
callback: JsObject,
initial_value: Option<JsValue>,
context: &mut Context,
) -> JsResult<JsValue> {
TypedArray::reduceright(
&self.inner,
&[callback.into(), initial_value.into_or_undefined()],
context,
)
}
#[inline]
pub fn reverse(&self, context: &mut Context) -> JsResult<Self> {
TypedArray::reverse(&self.inner, &[], context)?;
Ok(self.clone())
}
#[inline]
pub fn slice(
&self,
start: Option<usize>,
end: Option<usize>,
context: &mut Context,
) -> JsResult<Self> {
let object = TypedArray::slice(
&self.inner,
&[start.into_or_undefined(), end.into_or_undefined()],
context,
)?;
Ok(Self { inner: object })
}
#[inline]
pub fn find(
&self,
predicate: JsObject,
this_arg: Option<JsValue>,
context: &mut Context,
) -> JsResult<JsValue> {
TypedArray::find(
&self.inner,
&[predicate.into(), this_arg.into_or_undefined()],
context,
)
}
#[inline]
pub fn index_of<T>(
&self,
search_element: T,
from_index: Option<usize>,
context: &mut Context,
) -> JsResult<Option<usize>>
where
T: Into<JsValue>,
{
let index = TypedArray::index_of(
&self.inner,
&[search_element.into(), from_index.into_or_undefined()],
context,
)?
.as_number()
.expect("TypedArray.prototype.indexOf should always return number");
#[allow(clippy::float_cmp)]
if index == -1.0 {
Ok(None)
} else {
Ok(Some(index as usize))
}
}
#[inline]
pub fn last_index_of<T>(
&self,
search_element: T,
from_index: Option<usize>,
context: &mut Context,
) -> JsResult<Option<usize>>
where
T: Into<JsValue>,
{
let index = TypedArray::last_index_of(
&self.inner,
&[search_element.into(), from_index.into_or_undefined()],
context,
)?
.as_number()
.expect("TypedArray.prototype.lastIndexOf should always return number");
#[allow(clippy::float_cmp)]
if index == -1.0 {
Ok(None)
} else {
Ok(Some(index as usize))
}
}
#[inline]
pub fn join(&self, separator: Option<JsString>, context: &mut Context) -> JsResult<JsString> {
TypedArray::join(&self.inner, &[separator.into_or_undefined()], context).map(|x| {
x.as_string()
.cloned()
.expect("TypedArray.prototype.join always returns string")
})
}
}
impl From<JsTypedArray> for JsObject {
#[inline]
fn from(o: JsTypedArray) -> Self {
o.inner
.as_object()
.expect("should always be an object")
.clone()
}
}
impl From<JsTypedArray> for JsValue {
#[inline]
fn from(o: JsTypedArray) -> Self {
o.inner.clone()
}
}
impl Deref for JsTypedArray {
type Target = JsObject;
#[inline]
fn deref(&self) -> &Self::Target {
self.inner.as_object().expect("should always be an object")
}
}
impl JsObjectType for JsTypedArray {}
macro_rules! JsTypedArrayType {
($name:ident, $constructor_function:ident, $constructor_object:ident, $element:ty) => {
#[doc = concat!("JavaScript `", stringify!($constructor_function), "` rust object.")]
#[derive(Debug, Clone, Trace, Finalize)]
pub struct $name {
inner: JsTypedArray,
}
impl $name {
#[inline]
pub fn from_iter<I>(elements: I, context: &mut Context) -> JsResult<Self>
where
I: IntoIterator<Item = $element>,
{
let array = JsArray::from_iter(elements.into_iter().map(JsValue::new), context);
let new_target = context
.intrinsics()
.constructors()
.$constructor_object()
.constructor()
.into();
let object = crate::builtins::typed_array::$constructor_function::constructor(
&new_target,
&[array.into()],
context,
)?
.as_object()
.expect("object")
.clone();
Ok(Self {
inner: JsTypedArray {
inner: object.into(),
},
})
}
}
impl From<$name> for JsObject {
#[inline]
fn from(o: $name) -> Self {
o.inner
.inner
.as_object()
.expect("should always be an object")
.clone()
}
}
impl From<$name> for JsValue {
#[inline]
fn from(o: $name) -> Self {
o.inner.inner.clone()
}
}
impl Deref for $name {
type Target = JsTypedArray;
#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
};
}
JsTypedArrayType!(JsUint8Array, Uint8Array, typed_uint8_array, u8);
JsTypedArrayType!(JsInt8Array, Int8Array, typed_int8_array, i8);
JsTypedArrayType!(JsUint16Array, Uint16Array, typed_uint16_array, u16);
JsTypedArrayType!(JsInt16Array, Int16Array, typed_int16_array, i16);
JsTypedArrayType!(JsUint32Array, Uint32Array, typed_uint32_array, u32);
JsTypedArrayType!(JsInt32Array, Int32Array, typed_int32_array, i32);
JsTypedArrayType!(JsFloat32Array, Float32Array, typed_float32_array, f32);
JsTypedArrayType!(JsFloat64Array, Float64Array, typed_float64_array, f64);

2
boa_engine/src/object/mod.rs

@ -59,10 +59,12 @@ mod tests;
pub(crate) mod internal_methods;
mod jsarray;
mod jsobject;
mod jstypedarray;
mod operations;
mod property_map;
pub use jsarray::*;
pub use jstypedarray::*;
pub(crate) trait JsObjectType:
Into<JsValue> + Into<JsObject> + Deref<Target = JsObject>

42
boa_engine/src/value/conversions.rs

@ -42,30 +42,58 @@ impl Display for TryFromCharError {
}
}
impl From<f64> for JsValue {
impl From<f32> for JsValue {
#[allow(clippy::float_cmp)]
#[inline]
fn from(value: f64) -> Self {
fn from(value: f32) -> Self {
// if value as i32 as f64 == value {
// Self::Integer(value as i32)
// } else {
Self::Rational(value)
Self::Rational(value.into())
// }
}
}
impl From<f32> for JsValue {
impl From<f64> for JsValue {
#[allow(clippy::float_cmp)]
#[inline]
fn from(value: f32) -> Self {
// if value as i32 as f32 == value {
fn from(value: f64) -> Self {
// if value as i32 as f64 == value {
// Self::Integer(value as i32)
// } else {
Self::Rational(value.into())
Self::Rational(value)
// }
}
}
impl From<u8> for JsValue {
#[inline]
fn from(value: u8) -> Self {
Self::Integer(value.into())
}
}
impl From<i8> for JsValue {
#[inline]
fn from(value: i8) -> Self {
Self::Integer(value.into())
}
}
impl From<u16> for JsValue {
#[inline]
fn from(value: u16) -> Self {
Self::Integer(value.into())
}
}
impl From<i16> for JsValue {
#[inline]
fn from(value: i16) -> Self {
Self::Integer(value.into())
}
}
impl From<u32> for JsValue {
#[inline]
fn from(value: u32) -> Self {

46
boa_examples/src/bin/jstypedarray.rs

@ -0,0 +1,46 @@
// This example shows how to manipulate a Javascript array using Rust code.
use boa_engine::{
object::{FunctionBuilder, JsUint8Array},
property::Attribute,
Context, JsResult, JsValue,
};
fn main() -> JsResult<()> {
// We create a new `Context` to create a new Javascript executor.
let context = &mut Context::default();
let data: Vec<u8> = (0..=255).collect();
let array = JsUint8Array::from_iter(data, context)?;
assert_eq!(array.get(0, context)?, JsValue::new(0));
let mut sum = 0;
for i in 0..=255 {
assert_eq!(array.at(i, context)?, JsValue::new(i));
sum += i;
}
let callback = FunctionBuilder::native(context, |_this, args, context| {
let accumulator = args.get(0).cloned().unwrap_or_default();
let value = args.get(1).cloned().unwrap_or_default();
accumulator.add(&value, context)
})
.build();
assert_eq!(
array.reduce(callback, Some(JsValue::new(0)), context)?,
JsValue::new(sum)
);
context.register_global_property(
"myUint8Array",
array,
Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE,
);
Ok(())
}
Loading…
Cancel
Save