diff --git a/crates/objects/src/store_builtins.rs b/crates/objects/src/store_builtins.rs index d6ddcf8..4f14309 100644 --- a/crates/objects/src/store_builtins.rs +++ b/crates/objects/src/store_builtins.rs @@ -196,19 +196,7 @@ impl ObjectStore { } fn key_equal(&self, left: &Value, right: &Value) -> Result { - let text = |value: &Value| -> Result, VmError> { - Ok(match value { - Value::Text(text) => Some(text.clone()), - Value::Object(reference) => self - .object(*reference)? - .payload() - .as_any() - .downcast_ref::() - .map(|string| string.as_str().to_owned()), - _ => None, - }) - }; - if let (Some(left), Some(right)) = (text(left)?, text(right)?) { + if let (Some(left), Some(right)) = (self.key_text(left)?, self.key_text(right)?) { return Ok(left == right); } match (left, right) { @@ -219,6 +207,19 @@ impl ObjectStore { } } + fn key_text<'a>(&'a self, value: &'a Value) -> Result, VmError> { + Ok(match value { + Value::Text(text) => Some(text.as_str()), + Value::Object(reference) => self + .object(*reference)? + .payload() + .as_any() + .downcast_ref::() + .map(EndorStringObject::as_str), + _ => None, + }) + } + pub fn new_cell(&mut self, value: Option) -> Result { self.allocate(EndorCellObject::new(value)) } diff --git a/crates/objects/tests/store.rs b/crates/objects/tests/store.rs index 7486d00..d02872f 100644 --- a/crates/objects/tests/store.rs +++ b/crates/objects/tests/store.rs @@ -5,6 +5,38 @@ use objects::{ Value, VmError, }; +#[test] +fn dictionary_text_and_managed_string_keys_share_entries_and_keep_first_identity() { + let mut store = ObjectStore::new().unwrap(); + let dict = store.new_dict().unwrap(); + for text in ["", "camera", "δΈ­ζ–‡πŸ™‚"] { + let key = store.new_string(text).unwrap(); + store + .dict_set(dict, Value::Object(key), Value::Bool(false)) + .unwrap(); + store + .dict_set(dict, Value::Text(text.into()), Value::Bool(true)) + .unwrap(); + assert_eq!( + store.dict_get_name(dict, text).unwrap(), + Some(Value::Bool(true)) + ); + assert_eq!( + store.dict_items(dict).unwrap().last().unwrap().0, + Value::Object(key) + ); + assert_eq!( + store.dict_get(dict, &Value::Object(key)).unwrap(), + Some(Value::Bool(true)) + ); + store.release(key).unwrap(); + assert!(store.dict_delete(dict, &Value::Text(text.into())).unwrap()); + assert_eq!(store.dict_get_name(dict, text).unwrap(), None); + } + store.release(dict).unwrap(); + assert_eq!(store.object_count(), 0); +} + #[test] fn standalone_storage_preserves_identity_validates_edges_and_collects_cycles() { let mut store = ObjectStore::new().unwrap();