From 0f72bf556ea7c842ae7e6216b929f67201199e64 Mon Sep 17 00:00:00 2001 From: letmutx Date: Tue, 22 Oct 2019 22:36:52 +0530 Subject: [PATCH] Enable obj[key] = value syntax. (#161) * wip: setting keys in objects * handle array case when setting objects --- src/lib/exec.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++ src/lib/js/object.rs | 2 +- src/lib/js/value.rs | 11 ++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/lib/exec.rs b/src/lib/exec.rs index 11ea7393fd..c752d9fb52 100644 --- a/src/lib/exec.rs +++ b/src/lib/exec.rs @@ -415,6 +415,13 @@ impl Executor for Interpreter { let val_obj = self.run(obj)?; val_obj.borrow().set_field(field.clone(), val.clone()); } + ExprDef::GetField(ref obj, ref field) => { + let val_obj = self.run(obj)?; + let val_field = self.run(field)?; + val_obj + .borrow() + .set_field(val_field.to_string(), val.clone()); + } _ => (), } Ok(val) @@ -703,4 +710,45 @@ mod tests { assert_eq!(exec(scenario), pass); } + + #[test] + fn object_field_set() { + let scenario = r#" + let m = {}; + m['key'] = 22; + m['key'] + "#; + assert_eq!(exec(scenario), String::from("22")); + } + + #[test] + fn array_field_set() { + let element_changes = r#" + let m = [1, 2, 3]; + m[1] = 5; + m[1] + "#; + assert_eq!(exec(element_changes), String::from("5")); + + let length_changes = r#" + let m = [1, 2, 3]; + m[10] = 52; + m.length + "#; + assert_eq!(exec(length_changes), String::from("11")); + + let negative_index_wont_affect_length = r#" + let m = [1, 2, 3]; + m[-11] = 5; + m.length + "#; + assert_eq!(exec(negative_index_wont_affect_length), String::from("3")); + + let non_num_key_wont_affect_length = r#" + let m = [1, 2, 3]; + m["magic"] = 5; + m.length + "#; + assert_eq!(exec(non_num_key_wont_affect_length), String::from("3")); + } } diff --git a/src/lib/js/object.rs b/src/lib/js/object.rs index 4228aeb75e..eb5aba8575 100644 --- a/src/lib/js/object.rs +++ b/src/lib/js/object.rs @@ -402,7 +402,7 @@ impl Object { } } -#[derive(Trace, Finalize, Clone, Debug)] +#[derive(Trace, Finalize, Clone, Debug, Eq, PartialEq)] pub enum ObjectKind { Function, Array, diff --git a/src/lib/js/value.rs b/src/lib/js/value.rs index 711895f8b7..0abb86123a 100644 --- a/src/lib/js/value.rs +++ b/src/lib/js/value.rs @@ -402,6 +402,17 @@ impl ValueData { pub fn set_field(&self, field: String, val: Value) -> Value { match *self { ValueData::Object(ref obj) => { + if obj.borrow().kind == ObjectKind::Array { + if let Ok(num) = field.parse::() { + if num > 0 { + let len: i32 = from_value(self.get_field_slice("length")) + .expect("Could not convert argument to i32"); + if len < (num + 1) as i32 { + self.set_field_slice("length", to_value(num + 1)); + } + } + } + } obj.borrow_mut() .properties .insert(field, Property::default().value(val.clone()));