• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Copyright (c) 2024 Huawei Device Co., Ltd.
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9    http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17Description: Python CDP Debugger.
18"""
19
20from dataclasses import dataclass, field
21from enum import Enum
22from typing import Optional, List
23
24
25@dataclass
26class EnableAccelerateLaunchParams:
27    options = ['enableLaunchAccelerate']
28    max_scripts_cache_size: float = 1e7
29
30
31@dataclass
32class SaveAllPossibleBreakpointsParams:
33    locations: dict
34
35
36@dataclass
37class DropFrameParams:
38    dropped_depth: int = 1
39
40
41@dataclass
42class ReplyNativeCallingParams:
43    user_code: bool = True
44
45
46@dataclass
47class SetMixedDebugEnabledParams:
48    enabled: bool
49    mixed_stack_enabled: bool
50
51
52@dataclass
53class SmartStepIntoParams:
54    url: str
55    line_number: int
56
57
58@dataclass
59class PauseOnExceptionsState(Enum):
60    ALL = 'all'
61    NONE = 'none'
62    CAUGHT = 'caught'
63    UNCAUGHT = 'uncaught'
64
65
66@dataclass
67class EvaluateOnCallFrameParams:
68    expression: str
69    call_frame_id: int = 0
70    object_group: str = "console"
71    include_command_line_api: bool = True
72    silent: bool = True
73
74
75@dataclass
76class BreakLocationUrl:
77    url: str
78    line_number: int
79    column_number: Optional[int] = 0
80    condition: Optional[str] = None
81
82    def to_json(self):
83        json = {'url': self.url,
84                'lineNumber': self.line_number,
85                'columnNumber': self.column_number}
86        if self.condition is not None:
87            json['condition'] = self.condition
88        return json
89
90
91@dataclass
92class SymbolicBreakpoint:
93    functionName: str
94
95    def to_json(self):
96        return {'functionName': self.functionName}
97
98
99@dataclass
100class RemoveBreakpointsUrl:
101    url: str = ""
102
103
104@dataclass
105class SetBreakpointsLocations:
106    locations: list = field(default_factory=list)
107
108
109@dataclass
110class SymbolicBreakpoints:
111    SymbolicBreakpoints: List[SymbolicBreakpoint] = field(default_factory=list)
112
113
114def enable(params: EnableAccelerateLaunchParams | None):
115    command = {'method': 'Debugger.enable'}
116    if params is not None:
117        command['params'] = {
118            'options': params.options,
119            'maxScriptsCacheSize': params.max_scripts_cache_size
120        }
121    return command
122
123
124def resume():
125    command = {'method': 'Debugger.resume'}
126    return command
127
128
129def remove_breakpoints_by_url(params: RemoveBreakpointsUrl):
130    command = {'method': 'Debugger.removeBreakpointsByUrl',
131               'params': {'url': params.url}}
132    return command
133
134
135def get_possible_and_set_breakpoint_by_url(params: SetBreakpointsLocations):
136    locations = []
137    for location in params.locations:
138        locations.append(location.to_json())
139    command = {'method': 'Debugger.getPossibleAndSetBreakpointByUrl',
140               'params': {'locations': locations}}
141    return command
142
143
144def set_symbolic_breakpoints(params: SymbolicBreakpoints):
145    symbolicBreakpoints = []
146    for symbolicBreakpoint in params.SymbolicBreakpoints:
147        symbolicBreakpoints.append(symbolicBreakpoint.to_json())
148    command = {'method': 'Debugger.setSymbolicBreakpoints',
149               'params': {'symbolicBreakpoints': symbolicBreakpoints}}
150    return command
151
152
153def remove_symbolic_breakpoints(params: SymbolicBreakpoints):
154    symbolicBreakpoints = []
155    for symbolicBreakpoint in params.SymbolicBreakpoints:
156        symbolicBreakpoints.append(symbolicBreakpoint.to_json())
157    command = {'method': 'Debugger.removeSymbolicBreakpoints',
158               'params': {'symbolicBreakpoints': symbolicBreakpoints}}
159    return command
160
161
162def step_over():
163    command = {'method': 'Debugger.stepOver'}
164    return command
165
166
167def step_into():
168    command = {'method': 'Debugger.stepInto'}
169    return command
170
171
172def step_out():
173    command = {'method': 'Debugger.stepOut'}
174    return command
175
176
177def disable():
178    command = {'method': 'Debugger.disable'}
179    return command
180
181
182def set_pause_on_exceptions(params: PauseOnExceptionsState):
183    command = {'method': 'Debugger.setPauseOnExceptions',
184               'params': {'state': params.value}}
185    return command
186
187
188def evaluate_on_call_frame(params: EvaluateOnCallFrameParams):
189    command = {'method': 'Debugger.evaluateOnCallFrame',
190               'params': {
191                   'callFrameId': str(params.call_frame_id),
192                   'expression': params.expression,
193                   'includeCommandLineAPI': params.include_command_line_api,
194                   'objectGroup': params.object_group,
195                   'silent': params.silent}}
196    return command
197
198
199def pause():
200    command = {'method': 'Debugger.pause'}
201    return command
202
203
204def set_mixed_debug_enabled(params: SetMixedDebugEnabledParams):
205    command = {'method': 'Debugger.setMixedDebugEnabled',
206               'params': {'enabled': params.enabled, 'mixedStackEnabled': params.mixed_stack_enabled}}
207    return command
208
209
210def reply_native_calling(params: ReplyNativeCallingParams):
211    command = {'method': 'Debugger.replyNativeCalling',
212               'params': {'userCode': params.user_code}}
213    return command
214
215
216def drop_frame(params: DropFrameParams):
217    command = {'method': 'Debugger.dropFrame',
218               'params': {'droppedDepth': params.dropped_depth}}
219    return command
220
221
222def smart_step_into(params: SmartStepIntoParams):
223    command = {'method': 'Debugger.smartStepInto',
224               'params': {'url': params.url, 'lineNumber': params.line_number}}
225    return command
226
227
228def save_all_possible_breakpoints(params: SaveAllPossibleBreakpointsParams):
229    locations = {}
230    for key, value in params.locations.items():
231        positions = []
232        for pos in value:
233            if isinstance(pos, int):
234                positions.append({"lineNumber": pos, "colomnNumber": 0})
235            else:
236                positions.append({"lineNumber": pos[0], "colomnNumber": pos[1]})
237        locations[key] = positions
238    command = {'method': 'Debugger.saveAllPossibleBreakpoints',
239               'params': {'locations': locations}}
240    return command