From e6ad879a899a924ce15692203f3186b46c0e9a0d Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:17:00 +0000 Subject: [PATCH 1/2] Optimize JavaScriptSupport._find_and_extract_body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hot loop replaced recursive AST traversal with an iterative stack-based DFS and eliminated per-node UTF-8 decoding by comparing byte slices via a single `memoryview` and pre-encoded target name. Line profiler shows the original recursive `find_function_node` consumed 90% of runtime (9.79 ms), while the optimized iterative loop distributes work across `node.type` checks (34.8%) and `stack.pop()` (4.1%), totaling lower overhead per node. The large-scale test with 1000 variable declarations improved 29.9% (683 µs → 526 µs), confirming the win scales with AST size. Smaller test cases regressed 8–17% due to loop setup cost exceeding recursion savings on trivial trees, a reasonable trade-off for the target workload. --- codeflash/languages/javascript/support.py | 61 +++++++++++++---------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index f1a570740..22ceeab98 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -17,6 +17,7 @@ from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file from codeflash.languages.registry import register_language from codeflash.models.models import FunctionParent +from codeflash.cli_cmds.console import logger if TYPE_CHECKING: from collections.abc import Sequence @@ -1196,31 +1197,41 @@ def _find_and_extract_body(self, source: str, function_name: str, analyzer: Tree source_bytes = source.encode("utf8") tree = analyzer.parse(source_bytes) - def find_function_node(node, target_name: str): - """Recursively find a function/method with the given name.""" + mv = memoryview(source_bytes) + target_name_bytes = function_name.encode("utf8") + + func_node = None + func_types = ( + "function_declaration", + "function", + "generator_function_declaration", + "generator_function", + ) + decl_types = ("lexical_declaration", "variable_declaration") + value_fn_types = ("arrow_function", "function_expression", "generator_function") + + stack = [tree.root_node] + while stack: + node = stack.pop() + # Check method definitions if node.type == "method_definition": name_node = node.child_by_field_name("name") if name_node: - name = source_bytes[name_node.start_byte : name_node.end_byte].decode("utf8") - if name == target_name: - return node + if mv[name_node.start_byte : name_node.end_byte] == target_name_bytes: + func_node = node + break # Check function declarations - if node.type in ( - "function_declaration", - "function", - "generator_function_declaration", - "generator_function", - ): + if node.type in func_types: name_node = node.child_by_field_name("name") if name_node: - name = source_bytes[name_node.start_byte : name_node.end_byte].decode("utf8") - if name == target_name: - return node + if mv[name_node.start_byte : name_node.end_byte] == target_name_bytes: + func_node = node + break # Check arrow functions and function expressions assigned to variables - if node.type in ("lexical_declaration", "variable_declaration"): + if node.type in decl_types: for child in node.children: if child.type == "variable_declarator": name_node = child.child_by_field_name("name") @@ -1228,21 +1239,17 @@ def find_function_node(node, target_name: str): if ( name_node and value_node - and value_node.type in ("arrow_function", "function_expression", "generator_function") + and value_node.type in value_fn_types ): - name = source_bytes[name_node.start_byte : name_node.end_byte].decode("utf8") - if name == target_name: - return value_node - - # Recurse into children - for child in node.children: - result = find_function_node(child, target_name) - if result: - return result + if mv[name_node.start_byte : name_node.end_byte] == target_name_bytes: + func_node = value_node + break + if func_node: + break - return None + if node.children: + stack.extend(node.children) - func_node = find_function_node(tree.root_node, function_name) if not func_node: logger.debug("Could not find function '%s' in optimized code for body extraction", function_name) return None From db318676a0e84d7a896a9ab487d442beb1fb38cc Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:20:53 +0000 Subject: [PATCH 2/2] fix: remove redundant logger import shadowing module-level logger --- codeflash/languages/javascript/support.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index 22ceeab98..cf5d389f1 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -17,7 +17,6 @@ from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file from codeflash.languages.registry import register_language from codeflash.models.models import FunctionParent -from codeflash.cli_cmds.console import logger if TYPE_CHECKING: from collections.abc import Sequence @@ -1201,12 +1200,7 @@ def _find_and_extract_body(self, source: str, function_name: str, analyzer: Tree target_name_bytes = function_name.encode("utf8") func_node = None - func_types = ( - "function_declaration", - "function", - "generator_function_declaration", - "generator_function", - ) + func_types = ("function_declaration", "function", "generator_function_declaration", "generator_function") decl_types = ("lexical_declaration", "variable_declaration") value_fn_types = ("arrow_function", "function_expression", "generator_function") @@ -1236,11 +1230,7 @@ def _find_and_extract_body(self, source: str, function_name: str, analyzer: Tree if child.type == "variable_declarator": name_node = child.child_by_field_name("name") value_node = child.child_by_field_name("value") - if ( - name_node - and value_node - and value_node.type in value_fn_types - ): + if name_node and value_node and value_node.type in value_fn_types: if mv[name_node.start_byte : name_node.end_byte] == target_name_bytes: func_node = value_node break