Skip to content

Commit ee558b7

Browse files
committed
Support the scope and variables requests
Retrieve the list of variables at the current scope and show them under the variables pane. IoT.js-VSCode-DCO-1.0-Signed-off-by: Robert Sipka rsipka.uszeged@partner.samsung.com
1 parent 77c23f7 commit ee558b7

File tree

3 files changed

+248
-6
lines changed

3 files changed

+248
-6
lines changed

src/IotjsDebugger.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
'use strict';
1818

1919
import {
20-
DebugSession, InitializedEvent, OutputEvent, Thread, Source,
20+
DebugSession, Handles, InitializedEvent, OutputEvent, Thread, Scope, Source,
2121
StoppedEvent, StackFrame, TerminatedEvent, Event, ErrorDestination
2222
} from 'vscode-debugadapter';
2323
import { DebugProtocol } from 'vscode-debugprotocol';
@@ -30,7 +30,7 @@ import { IAttachRequestArguments, ILaunchRequestArguments, SourceSendingOptions,
3030
import { JerryDebuggerClient, JerryDebuggerOptions } from './JerryDebuggerClient';
3131
import {
3232
JerryDebugProtocolDelegate, JerryDebugProtocolHandler, JerryMessageScriptParsed, JerryEvalResult,
33-
JerryMessageExceptionHit, JerryMessageBreakpointHit, JerryBacktraceResult
33+
JerryMessageExceptionHit, JerryMessageBreakpointHit, JerryBacktraceResult, JerryScopeVariable, JerryScopeChain
3434
} from './JerryProtocolHandler';
3535
import { EVAL_RESULT_SUBTYPE, CLIENT as CLIENT_PACKAGE } from './JerryProtocolConstants';
3636
import { Breakpoint } from './JerryBreakpoints';
@@ -48,6 +48,7 @@ class IotjsDebugSession extends DebugSession {
4848
private _debuggerClient: JerryDebuggerClient;
4949
private _protocolhandler: JerryDebugProtocolHandler;
5050
private _sourceSendingOptions: SourceSendingOptions;
51+
private _variableHandles = new Handles<string>();
5152

5253
public constructor() {
5354
super();
@@ -451,6 +452,55 @@ class IotjsDebugSession extends DebugSession {
451452
}
452453
}
453454

455+
456+
protected async scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments
457+
): Promise<void> {
458+
try {
459+
const scopesArray: Array<JerryScopeChain> = await this._protocolhandler.requestScopes();
460+
const scopes = new Array<Scope>();
461+
462+
for (let scope of scopesArray) {
463+
scopes.push(new Scope(scope.name,
464+
this._variableHandles.create(scope.variablesReference.toString()),
465+
scope.expensive));
466+
}
467+
468+
response.body = {
469+
scopes: scopes
470+
};
471+
472+
this.sendResponse(response);
473+
} catch (error) {
474+
this.log(error.message, LOG_LEVEL.ERROR);
475+
this.sendErrorResponse(response, 0, (<Error>error).message);
476+
}
477+
}
478+
479+
protected async variablesRequest(response: DebugProtocol.VariablesResponse,
480+
args: DebugProtocol.VariablesArguments
481+
): Promise<void> {
482+
try {
483+
const variables = new Array<DebugProtocol.Variable>();
484+
const id = this._variableHandles.get(args.variablesReference);
485+
const scopeVariables: Array<JerryScopeVariable> = await this._protocolhandler.requestVariables(Number(id));
486+
487+
for (let variable of scopeVariables) {
488+
variables.push({name: variable.name,
489+
type: variable.type,
490+
value: variable.value,
491+
variablesReference: 0});
492+
}
493+
494+
response.body = {
495+
variables: variables
496+
};
497+
this.sendResponse(response);
498+
} catch (error) {
499+
this.log(error.message, LOG_LEVEL.ERROR);
500+
this.sendErrorResponse(response, 0, (<Error>error).message);
501+
}
502+
}
503+
454504
protected customRequest(command: string, response: DebugProtocol.Response, args: any): void {
455505
switch (command) {
456506
case 'sendSource': {

src/JerryProtocolConstants.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
'use strict';
1818

1919
// Expected JerryScript debugger protocol version.
20-
export const JERRY_DEBUGGER_VERSION = 6;
20+
export const JERRY_DEBUGGER_VERSION = 7;
2121

2222
// Packages sent from the server to the client.
2323
export enum SERVER {
@@ -47,7 +47,11 @@ export enum SERVER {
4747
JERRY_DEBUGGER_EVAL_RESULT_END = 24,
4848
JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25,
4949
JERRY_DEBUGGER_OUTPUT_RESULT = 26,
50-
JERRY_DEBUGGER_OUTPUT_RESULT_END = 27
50+
JERRY_DEBUGGER_OUTPUT_RESULT_END = 27,
51+
JERRY_DEBUGGER_SCOPE_CHAIN = 28,
52+
JERRY_DEBUGGER_SCOPE_CHAIN_END = 29,
53+
JERRY_DEBUGGER_SCOPE_VARIABLES = 30,
54+
JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31
5155
}
5256

5357
// Subtypes of eval.
@@ -91,5 +95,29 @@ export enum CLIENT {
9195
JERRY_DEBUGGER_FINISH = 15,
9296
JERRY_DEBUGGER_GET_BACKTRACE = 16,
9397
JERRY_DEBUGGER_EVAL = 17,
94-
JERRY_DEBUGGER_EVAL_PART = 18
98+
JERRY_DEBUGGER_EVAL_PART = 18,
99+
JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19,
100+
JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20
101+
}
102+
103+
// Types of scope chain.
104+
export enum JERRY_DEBUGGER_SCOPE_TYPE {
105+
JERRY_DEBUGGER_SCOPE_WITH = 1,
106+
JERRY_DEBUGGER_SCOPE_LOCAL = 2,
107+
JERRY_DEBUGGER_SCOPE_CLOSURE = 3,
108+
JERRY_DEBUGGER_SCOPE_GLOBAL = 4,
109+
JERRY_DEBUGGER_SCOPE_CATCH = 5
110+
}
111+
112+
// Type of scope variables.
113+
export enum JERRY_DEBUGGER_SCOPE_VARIABLES {
114+
JERRY_DEBUGGER_VALUE_NONE = 1,
115+
JERRY_DEBUGGER_VALUE_UNDEFINED = 2,
116+
JERRY_DEBUGGER_VALUE_NULL = 3,
117+
JERRY_DEBUGGER_VALUE_BOOLEAN = 4,
118+
JERRY_DEBUGGER_VALUE_NUMBER = 5,
119+
JERRY_DEBUGGER_VALUE_STRING = 6,
120+
JERRY_DEBUGGER_VALUE_FUNCTION = 7,
121+
JERRY_DEBUGGER_VALUE_ARRAY = 8,
122+
JERRY_DEBUGGER_VALUE_OBJECT = 9
95123
}

src/JerryProtocolHandler.ts

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ class PendingRequest {
123123
}
124124
}
125125

126+
export interface JerryScopeChain {
127+
name: string;
128+
variablesReference: number;
129+
expensive: boolean;
130+
}
131+
132+
export interface JerryScopeVariable {
133+
name: string;
134+
type: string;
135+
value: string;
136+
}
137+
126138
// abstracts away the details of the protocol
127139
export class JerryDebugProtocolHandler {
128140
public debuggerClient?: JerryDebuggerClient;
@@ -149,6 +161,8 @@ export class JerryDebugProtocolHandler {
149161
private functions: FunctionMap = {};
150162
private newFunctions: FunctionMap = {};
151163
private backtraceData: JerryBacktraceResult = {totalFrames : 0, backtrace: []};
164+
private scopeMessage?: Array<number> = [];
165+
private scopeVariableMessage?: string = '';
152166

153167
private nextScriptID: number = 1;
154168
private exceptionData?: Uint8Array;
@@ -197,7 +211,11 @@ export class JerryDebugProtocolHandler {
197211
[SP.SERVER.JERRY_DEBUGGER_BACKTRACE_END]: this.onBacktrace,
198212
[SP.SERVER.JERRY_DEBUGGER_EVAL_RESULT]: this.onEvalResult,
199213
[SP.SERVER.JERRY_DEBUGGER_EVAL_RESULT_END]: this.onEvalResult,
200-
[SP.SERVER.JERRY_DEBUGGER_WAIT_FOR_SOURCE]: this.onWaitForSource
214+
[SP.SERVER.JERRY_DEBUGGER_WAIT_FOR_SOURCE]: this.onWaitForSource,
215+
[SP.SERVER.JERRY_DEBUGGER_SCOPE_CHAIN]: this.onScopeChain,
216+
[SP.SERVER.JERRY_DEBUGGER_SCOPE_CHAIN_END]: this.onScopeChainEnd,
217+
[SP.SERVER.JERRY_DEBUGGER_SCOPE_VARIABLES]: this.onScopeVariables,
218+
[SP.SERVER.JERRY_DEBUGGER_SCOPE_VARIABLES_END]: this.onScopeVariablesEnd
201219
};
202220

203221
this.requestQueue = [];
@@ -586,6 +604,132 @@ export class JerryDebugProtocolHandler {
586604
return this.backtraceData;
587605
}
588606

607+
public onScopeChain(data: Uint8Array): void {
608+
this.logPacket('ScopeChain');
609+
610+
for (let i = 1; i < data.byteLength; i++) {
611+
this.scopeMessage.push(data[i]);
612+
}
613+
}
614+
615+
public onScopeChainEnd(data: Uint8Array): Array<JerryScopeChain> {
616+
this.logPacket('ScopeChainEnd');
617+
618+
for (let i = 1; i < data.byteLength; i++) {
619+
this.scopeMessage.push(data[i]);
620+
}
621+
622+
const scopes: Array<JerryScopeChain> = [];
623+
for (let i = 0; i < this.scopeMessage.length; i++) {
624+
switch (this.scopeMessage[i]) {
625+
case SP.JERRY_DEBUGGER_SCOPE_TYPE.JERRY_DEBUGGER_SCOPE_WITH: {
626+
scopes.push({name: 'with', variablesReference: i, expensive: true});
627+
break;
628+
}
629+
case SP.JERRY_DEBUGGER_SCOPE_TYPE.JERRY_DEBUGGER_SCOPE_LOCAL: {
630+
scopes.push({name: 'local', variablesReference: i, expensive: true});
631+
break;
632+
}
633+
case SP.JERRY_DEBUGGER_SCOPE_TYPE.JERRY_DEBUGGER_SCOPE_CLOSURE: {
634+
scopes.push({name: 'closure', variablesReference: i, expensive: true});
635+
break;
636+
}
637+
case SP.JERRY_DEBUGGER_SCOPE_TYPE.JERRY_DEBUGGER_SCOPE_GLOBAL: {
638+
scopes.push({name: 'global', variablesReference: i, expensive: true});
639+
break;
640+
}
641+
case SP.JERRY_DEBUGGER_SCOPE_TYPE.JERRY_DEBUGGER_SCOPE_CATCH: {
642+
scopes.push({name: 'catch', variablesReference: i, expensive: true});
643+
break;
644+
}
645+
default: {
646+
throw new Error('Invalid scope chain type!');
647+
}
648+
}
649+
}
650+
this.scopeMessage = [];
651+
652+
return scopes;
653+
}
654+
655+
public onScopeVariables(data: Uint8Array): void {
656+
this.logPacket('ScopeVariables');
657+
for (let i = 1; i < data.byteLength; i++) {
658+
this.scopeVariableMessage += String.fromCharCode(data[i]);
659+
}
660+
}
661+
662+
public onScopeVariablesEnd(data: Uint8Array): Array<JerryScopeVariable> {
663+
this.logPacket('ScopeVariablesEnd');
664+
665+
for (let i = 1; i < data.byteLength; i++) {
666+
this.scopeVariableMessage += String.fromCharCode(data[i]);
667+
}
668+
669+
let buff_pos = 0;
670+
const scopeVariablesArray: Array<JerryScopeVariable> = [];
671+
672+
while (buff_pos < this.scopeVariableMessage.length) {
673+
let scopeVariable: JerryScopeVariable = {name: '', type: '', value: ''};
674+
675+
// Process name.
676+
let name_length = this.scopeVariableMessage[buff_pos++].charCodeAt(0);
677+
scopeVariable.name = this.scopeVariableMessage.substring(buff_pos, buff_pos + name_length);
678+
679+
buff_pos += name_length;
680+
681+
// Process type
682+
let value_type: SP.JERRY_DEBUGGER_SCOPE_VARIABLES = this.scopeVariableMessage[buff_pos++].charCodeAt(0);
683+
let value_length = this.scopeVariableMessage[buff_pos++].charCodeAt(0);
684+
685+
scopeVariable.value = this.scopeVariableMessage.substring(buff_pos, buff_pos + value_length);
686+
buff_pos += value_length;
687+
688+
switch (value_type) {
689+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_UNDEFINED): {
690+
scopeVariable.type = 'undefined';
691+
break;
692+
}
693+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_NULL): {
694+
scopeVariable.type = 'Null';
695+
break;
696+
}
697+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_BOOLEAN): {
698+
scopeVariable.type = 'Boolean';
699+
break;
700+
}
701+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_NUMBER): {
702+
scopeVariable.type = 'Number';
703+
break;
704+
}
705+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_STRING): {
706+
scopeVariable.type = 'String';
707+
break;
708+
}
709+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_FUNCTION): {
710+
scopeVariable.type = 'Function';
711+
break;
712+
}
713+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_ARRAY): {
714+
scopeVariable.type = 'Array';
715+
scopeVariable.value = '[' + scopeVariable.value + ']';
716+
break;
717+
}
718+
case (SP.JERRY_DEBUGGER_SCOPE_VARIABLES.JERRY_DEBUGGER_VALUE_OBJECT): {
719+
scopeVariable.type = 'Object';
720+
break;
721+
}
722+
default: {
723+
throw new Error('Invalid scope variable type!');
724+
}
725+
}
726+
scopeVariablesArray.push(scopeVariable);
727+
}
728+
this.scopeVariableMessage = '';
729+
730+
return scopeVariablesArray;
731+
}
732+
589733
public onEvalResult(data: Uint8Array): JerryEvalResult {
590734
this.logPacket('Eval Result');
591735

@@ -776,6 +920,26 @@ export class JerryDebugProtocolHandler {
776920
1]));
777921
}
778922

923+
public requestScopes(): Promise<any> {
924+
if (!this.lastBreakpointHit) {
925+
return Promise.reject(new Error('scope chain not allowed while app running'));
926+
}
927+
928+
return this.sendRequest(encodeMessage(this.byteConfig, 'B',
929+
[SP.CLIENT.JERRY_DEBUGGER_GET_SCOPE_CHAIN]));
930+
}
931+
932+
public requestVariables(level?: number): Promise<any> {
933+
if (!this.lastBreakpointHit) {
934+
return Promise.reject(new Error('scope variables not allowed while app running'));
935+
}
936+
937+
return this.sendRequest(encodeMessage(this.byteConfig, 'BI',
938+
[SP.CLIENT.JERRY_DEBUGGER_GET_SCOPE_VARIABLES,
939+
level]));
940+
941+
}
942+
779943
logPacket(description: string, ignorable: boolean = false) {
780944
// certain packets are ignored while evals are pending
781945
const ignored = (ignorable && this.evalsPending) ? 'Ignored: ' : '';

0 commit comments

Comments
 (0)