|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
//! This module implements the global `Map` objest.
|
|
|
|
|
//! This module implements the global `Map` object.
|
|
|
|
|
//!
|
|
|
|
|
//! The JavaScript `Map` class is a global object that is used in the construction of maps; which
|
|
|
|
|
//! are high-level, key-value stores.
|
|
|
|
@ -31,6 +31,7 @@ use map_iterator::MapIterator;
|
|
|
|
|
use self::ordered_map::MapLock; |
|
|
|
|
|
|
|
|
|
use super::JsArgs; |
|
|
|
|
use num_traits::Zero; |
|
|
|
|
|
|
|
|
|
pub mod ordered_map; |
|
|
|
|
#[cfg(test)] |
|
|
|
@ -248,7 +249,17 @@ impl Map {
|
|
|
|
|
|
|
|
|
|
let size = if let Some(object) = this.as_object() { |
|
|
|
|
if let Some(map) = object.borrow_mut().as_map_mut() { |
|
|
|
|
map.insert(key.clone(), value.clone()); |
|
|
|
|
let key = match key { |
|
|
|
|
JsValue::Rational(r) => { |
|
|
|
|
if r.is_zero() { |
|
|
|
|
JsValue::Rational(0f64) |
|
|
|
|
} else { |
|
|
|
|
key.clone() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
_ => key.clone(), |
|
|
|
|
}; |
|
|
|
|
map.insert(key, value.clone()); |
|
|
|
|
map.len() |
|
|
|
|
} else { |
|
|
|
|
return Err(context.construct_type_error("'this' is not a Map")); |
|
|
|
@ -309,6 +320,19 @@ impl Map {
|
|
|
|
|
) -> JsResult<JsValue> { |
|
|
|
|
let key = args.get_or_undefined(0); |
|
|
|
|
|
|
|
|
|
const JS_ZERO: &JsValue = &JsValue::Rational(0f64); |
|
|
|
|
|
|
|
|
|
let key = match key { |
|
|
|
|
JsValue::Rational(r) => { |
|
|
|
|
if r.is_zero() { |
|
|
|
|
JS_ZERO |
|
|
|
|
} else { |
|
|
|
|
key |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
_ => key, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if let JsValue::Object(ref object) = this { |
|
|
|
|
let object = object.borrow(); |
|
|
|
|
if let Some(map) = object.as_map_ref() { |
|
|
|
@ -333,11 +357,23 @@ impl Map {
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.clear
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear
|
|
|
|
|
pub(crate) fn clear(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult<JsValue> { |
|
|
|
|
this.set_data(ObjectData::map(OrderedMap::new())); |
|
|
|
|
|
|
|
|
|
pub(crate) fn clear(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> { |
|
|
|
|
// 1. Let M be the this value.
|
|
|
|
|
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
|
|
|
|
// 3. Let entries be the List that is M.[[MapData]].
|
|
|
|
|
// 4. For each Record { [[Key]], [[Value]] } p of entries, do
|
|
|
|
|
// a. Set p.[[Key]] to empty.
|
|
|
|
|
// b. Set p.[[Value]] to empty.
|
|
|
|
|
Self::set_size(this, 0); |
|
|
|
|
|
|
|
|
|
if let Some(object) = this.as_object() { |
|
|
|
|
if let Some(map) = object.borrow_mut().as_map_mut() { |
|
|
|
|
map.clear(); |
|
|
|
|
} else { |
|
|
|
|
return context.throw_type_error("'this' is not a Map"); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return context.throw_type_error("'this' is not a Map"); |
|
|
|
|
} |
|
|
|
|
Ok(JsValue::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -388,6 +424,12 @@ impl Map {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let callback_arg = &args[0]; |
|
|
|
|
|
|
|
|
|
if !callback_arg.is_function() { |
|
|
|
|
let name = callback_arg.to_string(context)?; |
|
|
|
|
return context.throw_type_error(format!("{} is not a function", name)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let this_arg = args.get_or_undefined(1); |
|
|
|
|
|
|
|
|
|
let mut index = 0; |
|
|
|
|