From 49a172cd79271acfdbe469e621ed789f344010c7 Mon Sep 17 00:00:00 2001 From: joshwd36 Date: Sun, 17 Jan 2021 22:47:41 +0000 Subject: [PATCH] Fix panics from multiple borrows of Map. --- boa/src/builtins/map/mod.rs | 42 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/boa/src/builtins/map/mod.rs b/boa/src/builtins/map/mod.rs index 70e35191ff0..3b9c293743a 100644 --- a/boa/src/builtins/map/mod.rs +++ b/boa/src/builtins/map/mod.rs @@ -342,20 +342,48 @@ impl Map { let callback_arg = &args[0]; let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined); - if let Value::Object(ref object) = this { - let object = object.borrow(); - if let Some(map) = object.as_map_ref().cloned() { - for (key, value) in map { - let arguments = [value, key, this.clone()]; - - context.call(callback_arg, &this_arg, &arguments)?; + let mut index = 0; + + while index < Map::get_size(this, context)? { + let arguments = if let Value::Object(ref object) = this { + let object = object.borrow(); + if let Some(map) = object.as_map_ref() { + if let Some((key, value)) = map.get_index(index) { + Some([value.clone(), key.clone(), this.clone()]) + } else { + None + } + } else { + return context.throw_type_error("'this' is not a Map"); } + } else { + return context.throw_type_error("'this' is not a Map"); + }; + + if let Some(arguments) = arguments { + context.call(callback_arg, &this_arg, &arguments)?; } + + index += 1; } Ok(Value::Undefined) } + /// Helper function to get the size of the map. + fn get_size(map: &Value, context: &mut Context) -> Result { + if let Value::Object(ref object) = map { + let object = object.borrow(); + if let Some(map) = object.as_map_ref() { + Ok(map.len()) + } else { + Err(context.construct_type_error("'this' is not a Map")) + } + } else { + Err(context.construct_type_error("'this' is not a Map")) + } + } + /// `Map.prototype.values()` /// /// Returns a new Iterator object that contains the values for each element in the Map object in insertion order.