blob: 99b1131364409577cf7885863a6c83b013fa025d [file]
# Copyright 2026 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import annotations
from typing import TYPE_CHECKING
from pydap.models import EvaluateArguments, StackTraceArguments
from shared.protocol.base import Response
from shared.protocol.evaluate import EvaluateRequest, EvaluateResponse
if TYPE_CHECKING:
from daemon.daemon import Daemon
COMMAND_NAME = "evaluate"
async def handle(daemon: Daemon, req: EvaluateRequest) -> Response:
if not daemon.zxdb_writer:
return Response(
success=False, message="Not connected to zxdb DAP server"
)
try:
if req.thread_id not in daemon.stopped_threads:
return Response(
success=False,
message=(
'Thread not stopped, use "fx debug cli pause '
f'{req.thread_id}" to stop the thread, or set a breakpoint '
'with "fx debug cli break".'
),
)
# TODO(https://fxbug.dev/524209338): Paginate stack_trace call to avoid unbounded IPC.
# Retrieve stack trace to get the frameId at the requested frame_index
stack_resp = await daemon.dap_client.stack_trace(
daemon.zxdb_writer,
StackTraceArguments(
thread_id=req.thread_id,
),
)
if not stack_resp.body or not stack_resp.body.stack_frames:
return Response(success=False, message="No stack frames found")
if req.frame_index < 0 or req.frame_index >= len(
stack_resp.body.stack_frames
):
return Response(
success=False,
message=(
f"Frame index {req.frame_index} out of range (stack has"
f" {len(stack_resp.body.stack_frames)} frames)"
),
)
frame = stack_resp.body.stack_frames[req.frame_index]
# Execute evaluation
eval_resp = await daemon.dap_client.evaluate(
daemon.zxdb_writer,
EvaluateArguments(
expression=req.expression,
context="repl",
frame_id=frame.id,
),
)
if not eval_resp.success or not eval_resp.body:
return Response(
success=False,
message=eval_resp.message or "Evaluation failed",
)
# TODO(https://fxbug.dev/529329366): Support variablesReference in the evaluate response.
return Response(
success=True,
body=EvaluateResponse(
result=eval_resp.body.result,
type=eval_resp.body.type,
),
)
except Exception as e:
return Response(
success=False, message=f"Failed to evaluate expression: {e}"
)