Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[exec Map] Map.prototype.values and Map.prototype.keys implementation #874

Merged
merged 13 commits into from
Oct 15, 2020
30 changes: 30 additions & 0 deletions boa/src/builtins/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ impl BuiltIn for Map {
entries_function,
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
)
.method(Self::keys, "keys", 0)
.method(Self::set, "set", 2)
.method(Self::delete, "delete", 1)
.method(Self::get, "get", 1)
.method(Self::clear, "clear", 0)
.method(Self::has, "has", 1)
.method(Self::for_each, "forEach", 1)
.method(Self::values, "values", 0)
.callable(false)
.build();

Expand Down Expand Up @@ -134,6 +136,20 @@ impl Map {
MapIterator::create_map_iterator(ctx, this.clone(), MapIterationKind::KeyAndValue)
}

/// `Map.prototype.keys()`
///
/// Returns a new Iterator object that contains the keys for each element in the Map object in insertion order.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.keys
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys
pub(crate) fn keys(this: &Value, _: &[Value], ctx: &mut Context) -> Result<Value> {
MapIterator::create_map_iterator(ctx, this.clone(), MapIterationKind::Key)
}

/// Helper function to set the size property.
fn set_size(this: &Value, size: usize) {
let size = DataDescriptor::new(
Expand Down Expand Up @@ -321,6 +337,20 @@ impl Map {
Ok(Value::Undefined)
}

/// `Map.prototype.values()`
///
/// Returns a new Iterator object that contains the values for each element in the Map object in insertion order.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.values
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values
pub(crate) fn values(this: &Value, _: &[Value], ctx: &mut Context) -> Result<Value> {
MapIterator::create_map_iterator(ctx, this.clone(), MapIterationKind::Value)
}

/// Helper function to get a key-value pair from an array.
fn get_key_value(value: &Value) -> Option<(Value, Value)> {
if let Value::Object(object) = value {
Expand Down
54 changes: 54 additions & 0 deletions boa/src/builtins/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,33 @@ fn has() {
assert_eq!(result, "false");
}

#[test]
fn keys() {
let mut engine = Context::new();
let init = r#"
const map1 = new Map();
map1.set('0', 'foo');
map1.set(1, 'bar');
const keysIterator = map1.keys();
let item1 = keysIterator.next();
let item2 = keysIterator.next();
let item3 = keysIterator.next();
"#;
forward(&mut engine, init);
let result = forward(&mut engine, "item1.value");
assert_eq!(result, "\"0\"");
let result = forward(&mut engine, "item1.done");
assert_eq!(result, "false");
let result = forward(&mut engine, "item2.value");
assert_eq!(result, "1");
let result = forward(&mut engine, "item2.done");
assert_eq!(result, "false");
let result = forward(&mut engine, "item3.value");
assert_eq!(result, "undefined");
let result = forward(&mut engine, "item3.done");
assert_eq!(result, "true");
}

#[test]
fn for_each() {
let mut engine = Context::new();
Expand All @@ -231,6 +258,33 @@ fn for_each() {
assert_eq!(forward(&mut engine, "sizeSum"), "9");
}

#[test]
fn values() {
let mut engine = Context::new();
let init = r#"
const map1 = new Map();
map1.set('0', 'foo');
map1.set(1, 'bar');
const valuesIterator = map1.values();
let item1 = valuesIterator.next();
let item2 = valuesIterator.next();
let item3 = valuesIterator.next();
"#;
forward(&mut engine, init);
let result = forward(&mut engine, "item1.value");
assert_eq!(result, "\"foo\"");
let result = forward(&mut engine, "item1.done");
assert_eq!(result, "false");
let result = forward(&mut engine, "item2.value");
assert_eq!(result, "\"bar\"");
let result = forward(&mut engine, "item2.done");
assert_eq!(result, "false");
let result = forward(&mut engine, "item3.value");
assert_eq!(result, "undefined");
let result = forward(&mut engine, "item3.done");
assert_eq!(result, "true");
}

#[test]
fn modify_key() {
let mut engine = Context::new();
Expand Down