Skip to content

Commit cf48c75

Browse files
MayankRaj435Your Name
andauthored
feat: Add missing JsTypedArray wrapper methods (boa-dev#5009)
This PR adds missing Rust wrapper methods for `TypedArray` in `JsTypedArray` and its subclasses, specifically resolving part of boa-dev#3252. ### Changes: - Added `entries()`, `keys()`, `values()`, `@@iterator()` (using `values`), and `toString()` (using `Array.prototype.toString`). - Changed visibility of `entries` and `values` in `BuiltinTypedArray` to `pub(crate)` to allow access from the wrappers. - Added comprehensive unit tests in `jstypedarray.rs` verify the new methods. All unit tests pass. --------- Co-authored-by: Your Name <test@example.com>
1 parent 55aed13 commit cf48c75

2 files changed

Lines changed: 212 additions & 2 deletions

File tree

core/engine/src/builtins/typed_array/builtin.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,11 @@ impl BuiltinTypedArray {
624624
/// - [ECMAScript reference][spec]
625625
///
626626
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries
627-
fn entries(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
627+
pub(crate) fn entries(
628+
this: &JsValue,
629+
_: &[JsValue],
630+
context: &mut Context,
631+
) -> JsResult<JsValue> {
628632
// 1. Let O be the this value.
629633
// 2. Perform ? ValidateTypedArray(O, seq-cst).
630634
let (ta, _) = TypedArray::validate(this, Ordering::SeqCst)?;
@@ -2546,7 +2550,11 @@ impl BuiltinTypedArray {
25462550
/// - [ECMAScript reference][spec]
25472551
///
25482552
/// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
2549-
fn values(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
2553+
pub(crate) fn values(
2554+
this: &JsValue,
2555+
_: &[JsValue],
2556+
context: &mut Context,
2557+
) -> JsResult<JsValue> {
25502558
// 1. Let O be the this value.
25512559
// 2. Perform ? ValidateTypedArray(O, seq-cst).
25522560
let (ta, _) = TypedArray::validate(this, Ordering::SeqCst)?;

core/engine/src/object/builtins/jstypedarray.rs

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,41 @@ impl JsTypedArray {
877877
})
878878
}
879879

880+
/// Calls `TypedArray.prototype.entries()`.
881+
#[inline]
882+
pub fn entries(&self, context: &mut Context) -> JsResult<JsValue> {
883+
BuiltinTypedArray::entries(&self.inner.clone().into(), &[], context)
884+
}
885+
886+
/// Calls `TypedArray.prototype.keys()`.
887+
#[inline]
888+
pub fn keys(&self, context: &mut Context) -> JsResult<JsValue> {
889+
BuiltinTypedArray::keys(&self.inner.clone().into(), &[], context)
890+
}
891+
892+
/// Calls `TypedArray.prototype.values()`.
893+
#[inline]
894+
pub fn values(&self, context: &mut Context) -> JsResult<JsValue> {
895+
BuiltinTypedArray::values(&self.inner.clone().into(), &[], context)
896+
}
897+
898+
/// Calls `TypedArray.prototype[@@iterator]()`.
899+
#[inline]
900+
pub fn iterator(&self, context: &mut Context) -> JsResult<JsValue> {
901+
BuiltinTypedArray::values(&self.inner.clone().into(), &[], context)
902+
}
903+
904+
/// Calls `TypedArray.prototype.toString()`.
905+
#[inline]
906+
pub fn to_string(&self, context: &mut Context) -> JsResult<JsString> {
907+
// TypedArray.prototype.toString is the same as Array.prototype.toString
908+
let result = crate::builtins::Array::to_string(&self.inner.clone().into(), &[], context)?;
909+
result
910+
.as_string()
911+
.js_expect("Array.prototype.toString always returns string")
912+
.map_err(Into::into)
913+
}
914+
880915
/// It is a getter that returns the same string as the typed array constructor's name.
881916
/// It returns `Ok(JsValue::Undefined)` if the this value is not one of the typed array subclasses.
882917
///
@@ -1348,3 +1383,170 @@ fn typed_iterators_f32() {
13481383
let vec2 = array.iter(context).collect::<Vec<_>>();
13491384
assert_eq!(vec, vec2);
13501385
}
1386+
1387+
#[test]
1388+
fn typed_array_to_string() {
1389+
let context = &mut Context::default();
1390+
let vec = vec![1u8, 2, 3];
1391+
let array = JsUint8Array::from_iter(vec, context).unwrap();
1392+
assert_eq!(
1393+
array.to_string(context).unwrap(),
1394+
crate::js_string!("1,2,3")
1395+
);
1396+
}
1397+
1398+
#[test]
1399+
fn typed_array_entries() {
1400+
let context = &mut Context::default();
1401+
let vec = vec![1u8, 2];
1402+
let array = JsUint8Array::from_iter(vec, context).unwrap();
1403+
let entries = array.entries(context).unwrap();
1404+
let mut entries_vec = Vec::new();
1405+
let next_str = crate::js_string!("next");
1406+
loop {
1407+
let next_fn = entries
1408+
.as_object()
1409+
.unwrap()
1410+
.get(next_str.clone(), context)
1411+
.unwrap();
1412+
let result = next_fn
1413+
.as_object()
1414+
.unwrap()
1415+
.call(&entries, &[], context)
1416+
.unwrap();
1417+
if result
1418+
.as_object()
1419+
.unwrap()
1420+
.get(crate::js_string!("done"), context)
1421+
.unwrap()
1422+
.to_boolean()
1423+
{
1424+
break;
1425+
}
1426+
entries_vec.push(
1427+
result
1428+
.as_object()
1429+
.unwrap()
1430+
.get(crate::js_string!("value"), context)
1431+
.unwrap(),
1432+
);
1433+
}
1434+
assert_eq!(entries_vec.len(), 2);
1435+
}
1436+
1437+
#[test]
1438+
fn typed_array_keys() {
1439+
let context = &mut Context::default();
1440+
let vec = vec![1u8, 2];
1441+
let array = JsUint8Array::from_iter(vec, context).unwrap();
1442+
let keys = array.keys(context).unwrap();
1443+
let mut keys_vec = Vec::new();
1444+
let next_str = crate::js_string!("next");
1445+
loop {
1446+
let next_fn = keys
1447+
.as_object()
1448+
.unwrap()
1449+
.get(next_str.clone(), context)
1450+
.unwrap();
1451+
let result = next_fn
1452+
.as_object()
1453+
.unwrap()
1454+
.call(&keys, &[], context)
1455+
.unwrap();
1456+
if result
1457+
.as_object()
1458+
.unwrap()
1459+
.get(crate::js_string!("done"), context)
1460+
.unwrap()
1461+
.to_boolean()
1462+
{
1463+
break;
1464+
}
1465+
keys_vec.push(
1466+
result
1467+
.as_object()
1468+
.unwrap()
1469+
.get(crate::js_string!("value"), context)
1470+
.unwrap(),
1471+
);
1472+
}
1473+
assert_eq!(keys_vec, vec![JsValue::new(0), JsValue::new(1)]);
1474+
}
1475+
1476+
#[test]
1477+
fn typed_array_values() {
1478+
let context = &mut Context::default();
1479+
let vec = vec![1u8, 2];
1480+
let array = JsUint8Array::from_iter(vec, context).unwrap();
1481+
let values = array.values(context).unwrap();
1482+
let mut values_vec = Vec::new();
1483+
let next_str = crate::js_string!("next");
1484+
loop {
1485+
let next_fn = values
1486+
.as_object()
1487+
.unwrap()
1488+
.get(next_str.clone(), context)
1489+
.unwrap();
1490+
let result = next_fn
1491+
.as_object()
1492+
.unwrap()
1493+
.call(&values, &[], context)
1494+
.unwrap();
1495+
if result
1496+
.as_object()
1497+
.unwrap()
1498+
.get(crate::js_string!("done"), context)
1499+
.unwrap()
1500+
.to_boolean()
1501+
{
1502+
break;
1503+
}
1504+
values_vec.push(
1505+
result
1506+
.as_object()
1507+
.unwrap()
1508+
.get(crate::js_string!("value"), context)
1509+
.unwrap(),
1510+
);
1511+
}
1512+
assert_eq!(values_vec, vec![JsValue::new(1), JsValue::new(2)]);
1513+
}
1514+
1515+
#[test]
1516+
fn typed_array_iterator() {
1517+
let context = &mut Context::default();
1518+
let vec = vec![1u8, 2];
1519+
let array = JsUint8Array::from_iter(vec, context).unwrap();
1520+
let values = array.iterator(context).unwrap();
1521+
let mut values_vec = Vec::new();
1522+
let next_str = crate::js_string!("next");
1523+
loop {
1524+
let next_fn = values
1525+
.as_object()
1526+
.unwrap()
1527+
.get(next_str.clone(), context)
1528+
.unwrap();
1529+
let result = next_fn
1530+
.as_object()
1531+
.unwrap()
1532+
.call(&values, &[], context)
1533+
.unwrap();
1534+
if result
1535+
.as_object()
1536+
.unwrap()
1537+
.get(crate::js_string!("done"), context)
1538+
.unwrap()
1539+
.to_boolean()
1540+
{
1541+
break;
1542+
}
1543+
values_vec.push(
1544+
result
1545+
.as_object()
1546+
.unwrap()
1547+
.get(crate::js_string!("value"), context)
1548+
.unwrap(),
1549+
);
1550+
}
1551+
assert_eq!(values_vec, vec![JsValue::new(1), JsValue::new(2)]);
1552+
}

0 commit comments

Comments
 (0)