Skip to content

Commit

Permalink
Merge 441e209 into 6baf455
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored Apr 3, 2022
2 parents 6baf455 + 441e209 commit 35b568d
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 10 deletions.
6 changes: 3 additions & 3 deletions boa_engine/src/builtins/typed_array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2951,7 +2951,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,
Expand Down
133 changes: 133 additions & 0 deletions boa_engine/src/object/jstypedarray.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use crate::{
builtins::typed_array::TypedArray,
object::{JsArray, JsObject, JsObjectType},
Context, JsResult, JsValue,
};
use boa_gc::{Finalize, Trace};
use std::ops::Deref;

/// JavaScript `TypedArray` rust object.
#[derive(Debug, Clone, Trace, Finalize)]
pub struct JsTypedArray {
inner: JsObject,
}

impl JsTypedArray {
/// Get the length of the array.
///
/// Same a `array.length` in JavaScript.
#[inline]
pub fn length(&self, context: &mut Context) -> JsResult<usize> {
self.inner.length_of_array_like(context)
}

/// Check if the array is empty, i.e. the `length` is zero.
#[inline]
pub fn is_empty(&self, context: &mut Context) -> JsResult<bool> {
self.inner.length_of_array_like(context).map(|len| len == 0)
}

#[inline]
pub fn at<T>(&self, index: T, context: &mut Context) -> JsResult<JsValue>
where
T: Into<i64>,
{
TypedArray::at(&self.inner.clone().into(), &[index.into().into()], context)
}
}

impl From<JsTypedArray> for JsObject {
#[inline]
fn from(o: JsTypedArray) -> Self {
o.inner.clone()
}
}

impl From<JsTypedArray> for JsValue {
#[inline]
fn from(o: JsTypedArray) -> Self {
o.inner.clone().into()
}
}

impl Deref for JsTypedArray {
type Target = JsObject;

#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}

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>,
{
// TODO: This is pretty inefficient, find a better way of creating typed arrays from iterators
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 },
})
}
}

impl From<$name> for JsObject {
#[inline]
fn from(o: $name) -> Self {
o.inner.inner.clone()
}
}

impl From<$name> for JsValue {
#[inline]
fn from(o: $name) -> Self {
o.inner.inner.clone().into()
}
}

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 changes: 2 additions & 0 deletions boa_engine/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,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>
Expand Down
42 changes: 35 additions & 7 deletions boa_engine/src/value/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
26 changes: 26 additions & 0 deletions boa_examples/src/bin/jstypedarray.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// This example shows how to manipulate a Javascript array using Rust code.

use boa_engine::{object::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));

for i in 0..=255 {
assert_eq!(array.at(i, context)?, JsValue::new(i));
}

context.register_global_property(
"myUint8Array",
array,
Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE,
);

Ok(())
}

0 comments on commit 35b568d

Please sign in to comment.