diff --git a/exercises/react/example.rs b/exercises/react/example.rs index 8fdd8eeb9..f3ac5c60c 100644 --- a/exercises/react/example.rs +++ b/exercises/react/example.rs @@ -47,12 +47,14 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> { } pub fn create_compute T + 'a>(&mut self, dependencies: &[CellID], compute_func: F) -> Result { + // Check all dependencies' validity before modifying any of them, + // so that we don't perform an incorrect partial write. + if !dependencies.iter().all(|&id| id < self.cells.len()) { + return Err("Nonexistent input"); + } let new_id = self.cells.len(); for &id in dependencies { - match self.cells.get_mut(id) { - Some(c) => c.dependents.push(new_id), - None => return Err("Nonexistent input"), - } + self.cells.get_mut(id).unwrap().dependents.push(new_id); } let inputs: Vec<_> = dependencies.iter().map(|&id| self.value(id).unwrap()).collect(); let initial = compute_func(&inputs); diff --git a/exercises/react/tests/react.rs b/exercises/react/tests/react.rs index 6ac600811..1a72e8943 100644 --- a/exercises/react/tests/react.rs +++ b/exercises/react/tests/react.rs @@ -53,6 +53,19 @@ fn error_creating_compute_cell_if_input_doesnt_exist() { assert!(Reactor::new().create_compute(&vec![input], |_| 0).is_err()); } +#[test] +#[ignore] +fn do_not_break_cell_if_creating_compute_cell_with_valid_and_invalid_input() { + let mut dummy_reactor = Reactor::new(); + let _ = dummy_reactor.create_input(1); + let dummy_cell = dummy_reactor.create_input(2); + let mut reactor = Reactor::new(); + let input = reactor.create_input(1); + assert!(reactor.create_compute(&vec![input, dummy_cell], |_| 0).is_err()); + assert!(reactor.set_value(input, 5).is_ok()); + assert_eq!(reactor.value(input).unwrap(), 5); +} + #[test] #[ignore] fn compute_cells_update_value_when_dependencies_are_changed() {