@ton/sandbox 0.21.0-debugger.2 → 0.21.0-debugger.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,13 +14,31 @@ function registerCompiledContract(c) {
14
14
  const sm = {};
15
15
  for (let i = 0; i < locations.length; i++) {
16
16
  const di = locations[i];
17
- if (di.ret || di.vars === undefined)
18
- continue;
19
- sm[i] = {
17
+ const common = {
20
18
  path: (0, node_path_1.resolve)(di.file),
21
19
  line: di.line,
22
- variables: di.vars ?? [],
20
+ function: di.func,
23
21
  };
22
+ if (di.ret) {
23
+ sm[i] = {
24
+ ...common,
25
+ type: 'return',
26
+ };
27
+ }
28
+ else if (di.is_catch) {
29
+ sm[i] = {
30
+ ...common,
31
+ type: 'catch',
32
+ };
33
+ }
34
+ else {
35
+ sm[i] = {
36
+ ...common,
37
+ type: 'statement',
38
+ variables: di.vars ?? [],
39
+ firstStatement: di.first_stmt,
40
+ };
41
+ }
24
42
  }
25
43
  exports.defaultDebugInfoCache.set(c.code.hash().toString('base64'), {
26
44
  sourceMap: sm,
@@ -2,11 +2,19 @@
2
2
  import EventEmitter from 'node:events';
3
3
  import { Executor, GetMethodArgs, RunTransactionArgs } from '../executor/Executor';
4
4
  import { Cell, TupleItem } from '@ton/core';
5
- export type SourceMapEntry = {
5
+ export type SourceMapEntry = ({
6
6
  path: string;
7
7
  line: number;
8
+ function: string;
9
+ }) & ({
10
+ type: 'statement';
8
11
  variables: string[];
9
- };
12
+ firstStatement?: true;
13
+ } | {
14
+ type: 'return';
15
+ } | {
16
+ type: 'catch';
17
+ });
10
18
  export type SourceMap = {
11
19
  [k: number]: SourceMapEntry;
12
20
  };
@@ -26,6 +34,11 @@ export type Variable = {
26
34
  name: string;
27
35
  value: TupleItem;
28
36
  };
37
+ type StackFrame = {
38
+ function: string;
39
+ path: string;
40
+ line: number;
41
+ };
29
42
  export declare class Debuggee extends EventEmitter {
30
43
  executor: Executor;
31
44
  ptr: number;
@@ -37,7 +50,7 @@ export declare class Debuggee extends EventEmitter {
37
50
  codeCells: Map<string, Cell>;
38
51
  breakpoints: Map<string, Breakpoint[]>;
39
52
  breakpointID: number;
40
- frames: string[];
53
+ frames: StackFrame[];
41
54
  globals: GlobalEntry[];
42
55
  finishedCallback: (v: any) => void;
43
56
  constructor(executor: Executor, finishedCallback: (v: any) => void);
@@ -49,7 +62,9 @@ export declare class Debuggee extends EventEmitter {
49
62
  getAvailableLines(path: string): number[];
50
63
  isLineAvailable(path: string, line: number): boolean;
51
64
  continue(): void;
52
- step(stopEvent?: string): void;
65
+ stepIn(): void;
66
+ stepOver(): void;
67
+ stepOut(): void;
53
68
  startGetMethod(args: GetMethodArgs): void;
54
69
  startTransaction(args: RunTransactionArgs): void;
55
70
  getC7(): TupleItem;
@@ -59,6 +74,8 @@ export declare class Debuggee extends EventEmitter {
59
74
  offset: number;
60
75
  };
61
76
  getStack(): TupleItem[];
77
+ getContParam(): number;
78
+ setContParam(param: number): number;
62
79
  getLocalVariables(): Variable[] | undefined;
63
80
  getGlobalVariables(): Variable[] | undefined;
64
81
  currentDebugInfoNumber(): number | undefined;
@@ -73,7 +90,17 @@ export declare class Debuggee extends EventEmitter {
73
90
  setBreakpoint(path: string, line: number): Breakpoint;
74
91
  sendEvent(event: string, ...args: any[]): void;
75
92
  onFinished(): void;
76
- stepUntilLine(breakpointsOnly: boolean, stopEvent?: string): void;
93
+ stackFrames(): StackFrame[];
94
+ stepUntil(what: {
95
+ type: 'breakpoint';
96
+ } | {
97
+ type: 'any-line';
98
+ stopEvent: 'stopOnBreakpoint' | 'stopOnStep';
99
+ } | {
100
+ type: 'next-line';
101
+ } | {
102
+ type: 'out';
103
+ }): void;
77
104
  prepareGetMethod(args: GetMethodArgs, debugInfo: DebugInfo): void;
78
105
  prepareTransaction(args: RunTransactionArgs, code: Cell, debugInfo: DebugInfo): void;
79
106
  start(debug: boolean, stopOnEntry: boolean): void;
@@ -63,10 +63,16 @@ class Debuggee extends node_events_1.default {
63
63
  return lines.indexOf(line) >= 0;
64
64
  }
65
65
  continue() {
66
- this.stepUntilLine(true);
66
+ this.stepUntil({ type: 'breakpoint' });
67
67
  }
68
- step(stopEvent = 'stopOnStep') {
69
- this.stepUntilLine(false, stopEvent);
68
+ stepIn() {
69
+ this.stepUntil({ type: 'any-line', stopEvent: 'stopOnStep' });
70
+ }
71
+ stepOver() {
72
+ this.stepUntil({ type: 'next-line' });
73
+ }
74
+ stepOut() {
75
+ this.stepUntil({ type: 'out' });
70
76
  }
71
77
  startGetMethod(args) {
72
78
  this.ptr = this.executor.sbsGetMethodSetup(args);
@@ -112,9 +118,25 @@ class Debuggee extends node_events_1.default {
112
118
  return this.executor.sbsTransactionStack(this.ptr);
113
119
  }
114
120
  }
121
+ getContParam() {
122
+ switch (this.debugType) {
123
+ case 'get':
124
+ return this.executor.sbsGetMethodGetContParam(this.ptr);
125
+ case 'tx':
126
+ return this.executor.sbsTransactionGetContParam(this.ptr);
127
+ }
128
+ }
129
+ setContParam(param) {
130
+ switch (this.debugType) {
131
+ case 'get':
132
+ return this.executor.sbsGetMethodSetContParam(this.ptr, param);
133
+ case 'tx':
134
+ return this.executor.sbsTransactionSetContParam(this.ptr, param);
135
+ }
136
+ }
115
137
  getLocalVariables() {
116
138
  const sme = this.currentSourceMapEntry();
117
- if (sme === undefined) {
139
+ if (sme === undefined || sme.type !== 'statement') {
118
140
  return undefined;
119
141
  }
120
142
  const vars = [];
@@ -231,7 +253,20 @@ class Debuggee extends node_events_1.default {
231
253
  }
232
254
  this.finishedCallback(r);
233
255
  }
234
- stepUntilLine(breakpointsOnly, stopEvent) {
256
+ stackFrames() {
257
+ return this.frames;
258
+ }
259
+ stepUntil(what) {
260
+ let until;
261
+ switch (what.type) {
262
+ case 'next-line':
263
+ case 'out': {
264
+ until = { type: what.type, depth: this.frames.length };
265
+ break;
266
+ }
267
+ default:
268
+ until = what;
269
+ }
235
270
  while (true) {
236
271
  const finished = this.vmStep();
237
272
  if (finished) {
@@ -239,14 +274,56 @@ class Debuggee extends node_events_1.default {
239
274
  return;
240
275
  }
241
276
  const sme = this.currentSourceMapEntry();
242
- if (sme !== undefined && (!breakpointsOnly || this.hasBreakpoint(sme.path, sme.line))) {
243
- if (breakpointsOnly) {
244
- this.sendEvent('stopOnBreakpoint');
277
+ if (sme !== undefined) {
278
+ switch (sme.type) {
279
+ case 'statement': {
280
+ if (sme.firstStatement) {
281
+ this.frames.push({
282
+ function: sme.function,
283
+ path: sme.path,
284
+ line: sme.line,
285
+ });
286
+ this.setContParam(this.frames.length);
287
+ }
288
+ this.frames[this.frames.length - 1].line = sme.line;
289
+ switch (until.type) {
290
+ case 'breakpoint': {
291
+ if (this.hasBreakpoint(sme.path, sme.line)) {
292
+ this.sendEvent('stopOnBreakpoint');
293
+ return;
294
+ }
295
+ break;
296
+ }
297
+ case 'any-line': {
298
+ this.sendEvent(until.stopEvent);
299
+ return;
300
+ }
301
+ case 'next-line': {
302
+ if (this.frames.length <= until.depth) {
303
+ this.sendEvent('stopOnStep');
304
+ return;
305
+ }
306
+ break;
307
+ }
308
+ case 'out': {
309
+ if (this.frames.length < until.depth) {
310
+ this.sendEvent('stopOnStep');
311
+ return;
312
+ }
313
+ break;
314
+ }
315
+ }
316
+ break;
317
+ }
318
+ case 'return': {
319
+ this.frames.pop();
320
+ break;
321
+ }
322
+ case 'catch': {
323
+ this.frames = this.frames.slice(0, this.getContParam());
324
+ break;
325
+ }
245
326
  }
246
- else if (stopEvent !== undefined) {
247
- this.sendEvent(stopEvent);
248
- }
249
- return;
250
327
  }
251
328
  }
252
329
  }
@@ -263,7 +340,7 @@ class Debuggee extends node_events_1.default {
263
340
  start(debug, stopOnEntry) {
264
341
  if (debug) {
265
342
  if (stopOnEntry) {
266
- this.step('stopOnEntry');
343
+ this.stepUntil({ type: 'any-line', stopEvent: 'stopOnBreakpoint' });
267
344
  }
268
345
  else {
269
346
  this.continue();
@@ -139,15 +139,15 @@ class TVMDebugSession extends debugadapter_1.LoggingDebugSession {
139
139
  this.sendResponse(response);
140
140
  }
141
141
  nextRequest(response, args, request) {
142
- this.debuggee.step();
142
+ this.debuggee.stepOver();
143
143
  this.sendResponse(response);
144
144
  }
145
145
  stepInRequest(response, args, request) {
146
- this.debuggee.step();
146
+ this.debuggee.stepIn();
147
147
  this.sendResponse(response);
148
148
  }
149
149
  stepOutRequest(response, args, request) {
150
- this.debuggee.step();
150
+ this.debuggee.stepOut();
151
151
  this.sendResponse(response);
152
152
  }
153
153
  stackTraceRequest(response, args, request) {
@@ -159,26 +159,37 @@ class TVMDebugSession extends debugadapter_1.LoggingDebugSession {
159
159
  this.sendResponse(response);
160
160
  return;
161
161
  }
162
- response.body.totalFrames = 1;
163
- if (args.startFrame ?? 0 > 0) {
162
+ const frames = this.debuggee.stackFrames();
163
+ response.body.totalFrames = frames.length;
164
+ if (args.startFrame ?? 0 >= frames.length) {
164
165
  response.body.stackFrames = [];
165
166
  this.sendResponse(response);
166
167
  return;
167
168
  }
168
- response.body.stackFrames = [{
169
- id: TVMDebugSession.stackFrameID,
170
- name: 'func',
171
- line: sme.line,
169
+ response.body.stackFrames = [];
170
+ for (let i = args.startFrame ?? 0; i < frames.length; i++) {
171
+ const frame = frames[i];
172
+ response.body.stackFrames.push({
173
+ id: i === frames.length - 1 ? TVMDebugSession.stackFrameID : 0,
174
+ name: frame.function,
175
+ line: frame.line,
172
176
  column: 0,
173
177
  source: {
174
- name: (0, node_path_1.basename)(sme.path),
175
- path: sme.path,
178
+ name: (0, node_path_1.basename)(frame.path),
179
+ path: frame.path,
176
180
  },
177
- }];
181
+ });
182
+ }
183
+ response.body.stackFrames.reverse();
178
184
  this.sendResponse(response);
179
185
  }
180
186
  scopesRequest(response, args, request) {
181
187
  response.body = response.body || {};
188
+ if (args.frameId !== TVMDebugSession.stackFrameID) {
189
+ response.body.scopes = [];
190
+ this.sendResponse(response);
191
+ return;
192
+ }
182
193
  const sme = this.debuggee.currentSourceMapEntry();
183
194
  if (sme === undefined) {
184
195
  response.body.scopes = [];
@@ -99,6 +99,8 @@ export declare class Executor implements IExecutor {
99
99
  sbsGetMethodStep(ptr: number): boolean;
100
100
  sbsGetMethodStack(ptr: number): TupleItem[];
101
101
  sbsGetMethodC7(ptr: number): TupleItem;
102
+ sbsGetMethodGetContParam(ptr: number): number;
103
+ sbsGetMethodSetContParam(ptr: number, param: number): number;
102
104
  sbsGetMethodCodePos(ptr: number): {
103
105
  hash: string;
104
106
  offset: number;
@@ -116,5 +118,7 @@ export declare class Executor implements IExecutor {
116
118
  };
117
119
  sbsTransactionStack(ptr: number): TupleItem[];
118
120
  sbsTransactionC7(ptr: number): TupleItem;
121
+ sbsTransactionGetContParam(ptr: number): number;
122
+ sbsTransactionSetContParam(ptr: number, param: number): number;
119
123
  sbsTransactionResult(ptr: number): EmulationResult;
120
124
  }
@@ -253,6 +253,17 @@ class Executor {
253
253
  ]));
254
254
  return (0, core_1.parseTuple)((0, core_1.beginCell)().storeUint(1, 24).storeRef(core_1.Cell.EMPTY).storeSlice(core_1.Cell.fromBase64(resp).beginParse()).endCell())[0];
255
255
  }
256
+ sbsGetMethodGetContParam(ptr) {
257
+ return this.invoke('_sbs_get_cont_param', [
258
+ ptr
259
+ ]);
260
+ }
261
+ sbsGetMethodSetContParam(ptr, param) {
262
+ return this.invoke('_sbs_set_cont_param', [
263
+ ptr,
264
+ param
265
+ ]);
266
+ }
256
267
  sbsGetMethodCodePos(ptr) {
257
268
  const resp = this.extractString(this.invoke('_sbs_get_code_pos', [
258
269
  ptr
@@ -317,6 +328,17 @@ class Executor {
317
328
  ]));
318
329
  return (0, core_1.parseTuple)((0, core_1.beginCell)().storeUint(1, 24).storeRef(core_1.Cell.EMPTY).storeSlice(core_1.Cell.fromBase64(resp).beginParse()).endCell())[0];
319
330
  }
331
+ sbsTransactionGetContParam(ptr) {
332
+ return this.invoke('_em_sbs_get_cont_param', [
333
+ ptr
334
+ ]);
335
+ }
336
+ sbsTransactionSetContParam(ptr, param) {
337
+ return this.invoke('_em_sbs_set_cont_param', [
338
+ ptr,
339
+ param
340
+ ]);
341
+ }
320
342
  sbsTransactionResult(ptr) {
321
343
  const result = JSON.parse(this.extractString(this.invoke('_em_sbs_result', [
322
344
  ptr