From db89ce33f45a1604f544c70419271cae5de575f2 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Sun, 31 Mar 2024 13:04:42 -0400 Subject: [PATCH] chore(lsp): remove recursion in recurse_dependents (#23153) Was investigating a separate stack overflow (that I've now found in the node resolution code) and came across this. We should avoid recursion (this is very old code). --- cli/lsp/documents.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 8feeab8de4..8479768a0f 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -648,16 +648,20 @@ pub fn to_lsp_range(range: &deno_graph::Range) -> lsp::Range { fn recurse_dependents( specifier: &ModuleSpecifier, map: &HashMap>, - dependents: &mut HashSet, -) { - if let Some(deps) = map.get(specifier) { - for dep in deps { - if !dependents.contains(dep) { - dependents.insert(dep.clone()); - recurse_dependents(dep, map, dependents); +) -> Vec { + let mut dependents = HashSet::new(); + let mut pending = VecDeque::new(); + pending.push_front(specifier); + while let Some(specifier) = pending.pop_front() { + if let Some(deps) = map.get(specifier) { + for dep in deps { + if dependents.insert(dep) { + pending.push_front(dep); + } } } } + dependents.into_iter().cloned().collect() } #[derive(Debug)] @@ -1106,10 +1110,8 @@ impl Documents { specifier: &ModuleSpecifier, ) -> Vec { self.calculate_dependents_if_dirty(); - let mut dependents = HashSet::new(); if let Some(specifier) = self.resolve_specifier(specifier) { - recurse_dependents(&specifier, &self.dependents_map, &mut dependents); - dependents.into_iter().collect() + recurse_dependents(&specifier, &self.dependents_map) } else { vec![] }