Skip to content

Commit

Permalink
Implement Typed Array built-in (#1552)
Browse files Browse the repository at this point in the history
Co-authored-by: raskad <32105367+raskad@users.noreply.github.com>
Co-authored-by: jedel1043 <jedel0124@gmail.com>
  • Loading branch information
3 people committed Oct 4, 2021
1 parent ac7618a commit f5d87a8
Show file tree
Hide file tree
Showing 40 changed files with 5,789 additions and 344 deletions.
4 changes: 2 additions & 2 deletions boa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ exclude = ["../.vscode/*", "../Dockerfile", "../Makefile", "../.editorConfig"]
edition = "2018"

[features]
profiler = ["measureme", "once_cell"]
profiler = ["measureme"]
deser = []

# Enable Bytecode generation & execution instead of tree walking
Expand All @@ -38,10 +38,10 @@ chrono = "0.4.19"
fast-float = "0.2.0"
unicode-normalization = "0.1.19"
dyn-clone = "1.0.4"
once_cell = "1.8.0"

# Optional Dependencies
measureme = { version = "9.1.2", optional = true }
once_cell = { version = "1.8.0", optional = true }

[target.wasm32-unknown-unknown.dependencies]
getrandom = { version = "0.2.3", features = ["js"] }
Expand Down
39 changes: 24 additions & 15 deletions boa/src/builtins/array/array_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,21 @@ use crate::{
/// [spec]: https://tc39.es/ecma262/#sec-array-iterator-objects
#[derive(Debug, Clone, Finalize, Trace)]
pub struct ArrayIterator {
array: JsValue,
next_index: u32,
array: JsObject,
next_index: usize,
kind: PropertyNameKind,
done: bool,
}

impl ArrayIterator {
pub(crate) const NAME: &'static str = "ArrayIterator";

fn new(array: JsValue, kind: PropertyNameKind) -> Self {
fn new(array: JsObject, kind: PropertyNameKind) -> Self {
ArrayIterator {
array,
kind,
next_index: 0,
done: false,
}
}

Expand All @@ -40,7 +42,7 @@ impl ArrayIterator {
///
/// [spec]: https://tc39.es/ecma262/#sec-createarrayiterator
pub(crate) fn create_array_iterator(
array: JsValue,
array: JsObject,
kind: PropertyNameKind,
context: &Context,
) -> JsValue {
Expand All @@ -66,21 +68,28 @@ impl ArrayIterator {
let mut object = object.borrow_mut();
if let Some(array_iterator) = object.as_array_iterator_mut() {
let index = array_iterator.next_index;
if array_iterator.array.is_undefined() {
if array_iterator.done {
return Ok(create_iter_result_object(
JsValue::undefined(),
true,
context,
));
}
let len = array_iterator
.array
.get_field("length", context)?
.as_number()
.ok_or_else(|| context.construct_type_error("Not an array"))?
as u32;
if array_iterator.next_index >= len {
array_iterator.array = JsValue::undefined();

let len = if let Some(f) = array_iterator.array.borrow().as_typed_array() {
if f.is_detached() {
return context.throw_type_error(
"Cannot get value from typed array that has a detached array buffer",
);
}

f.array_length()
} else {
array_iterator.array.length_of_array_like(context)?
};

if index >= len {
array_iterator.done = true;
return Ok(create_iter_result_object(
JsValue::undefined(),
true,
Expand All @@ -93,11 +102,11 @@ impl ArrayIterator {
Ok(create_iter_result_object(index.into(), false, context))
}
PropertyNameKind::Value => {
let element_value = array_iterator.array.get_field(index, context)?;
let element_value = array_iterator.array.get(index, context)?;
Ok(create_iter_result_object(element_value, false, context))
}
PropertyNameKind::KeyAndValue => {
let element_value = array_iterator.array.get_field(index, context)?;
let element_value = array_iterator.array.get(index, context)?;
let result =
Array::create_array_from_list([index.into(), element_value], context);
Ok(create_iter_result_object(result.into(), false, context))
Expand Down
29 changes: 21 additions & 8 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,10 +758,11 @@ impl Array {
let len = o.length_of_array_like(context)?;
// 3. If separator is undefined, let sep be the single-element String ",".
// 4. Else, let sep be ? ToString(separator).
let separator = if let Some(separator) = args.get(0) {
separator.to_string(context)?
} else {
let separator = args.get_or_undefined(0);
let separator = if separator.is_undefined() {
JsString::new(",")
} else {
separator.to_string(context)?
};

// 5. Let R be the empty String.
Expand Down Expand Up @@ -2565,8 +2566,12 @@ impl Array {
_: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;

// 2. Return CreateArrayIterator(O, value).
Ok(ArrayIterator::create_array_iterator(
this.clone(),
o,
PropertyNameKind::Value,
context,
))
Expand All @@ -2580,11 +2585,15 @@ impl Array {
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.values
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.keys
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values
pub(crate) fn keys(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;

// 2. Return CreateArrayIterator(O, key).
Ok(ArrayIterator::create_array_iterator(
this.clone(),
o,
PropertyNameKind::Key,
context,
))
Expand All @@ -2598,15 +2607,19 @@ impl Array {
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.values
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.entries
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values
pub(crate) fn entries(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;

// 2. Return CreateArrayIterator(O, key+value).
Ok(ArrayIterator::create_array_iterator(
this.clone(),
o,
PropertyNameKind::KeyAndValue,
context,
))
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/array/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1412,7 +1412,7 @@ fn array_spread_non_iterable() {
try {
const array2 = [...5];
} catch (err) {
err.name === "TypeError" && err.message === "Not an iterable"
err.name === "TypeError" && err.message === "Value is not callable"
}
"#;
assert_eq!(forward(&mut context, init), "true");
Expand Down

0 comments on commit f5d87a8

Please sign in to comment.