diff --git a/boa/src/builtins/map/mod.rs b/boa/src/builtins/map/mod.rs index 3bfe6de9c7..f60f0ea56d 100644 --- a/boa/src/builtins/map/mod.rs +++ b/boa/src/builtins/map/mod.rs @@ -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(); @@ -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 { + 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( @@ -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 { + 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 { diff --git a/boa/src/builtins/map/tests.rs b/boa/src/builtins/map/tests.rs index 481d3d8c1c..1a145cdc31 100644 --- a/boa/src/builtins/map/tests.rs +++ b/boa/src/builtins/map/tests.rs @@ -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(); @@ -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();