roku-debug 0.21.12 → 0.21.14
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.
- package/CHANGELOG.md +26 -0
- package/dist/CompileErrorProcessor.d.ts +65 -4
- package/dist/CompileErrorProcessor.js.map +1 -1
- package/dist/LaunchConfiguration.d.ts +1 -1
- package/dist/adapters/DebugProtocolAdapter.d.ts +11 -0
- package/dist/adapters/DebugProtocolAdapter.js +47 -10
- package/dist/adapters/DebugProtocolAdapter.js.map +1 -1
- package/dist/adapters/TelnetAdapter.d.ts +6 -0
- package/dist/adapters/TelnetAdapter.js +14 -5
- package/dist/adapters/TelnetAdapter.js.map +1 -1
- package/dist/adapters/customVariableUtils.d.ts +7 -0
- package/dist/adapters/customVariableUtils.js +44 -0
- package/dist/adapters/customVariableUtils.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/debugProtocol/Constants.d.ts +44 -5
- package/dist/debugProtocol/Constants.js +39 -4
- package/dist/debugProtocol/Constants.js.map +1 -1
- package/dist/debugProtocol/client/DebugProtocolClient.d.ts +7 -2
- package/dist/debugProtocol/client/DebugProtocolClient.js +37 -7
- package/dist/debugProtocol/client/DebugProtocolClient.js.map +1 -1
- package/dist/debugProtocol/events/requests/SetExceptionBreakpointsRequest.d.ts +33 -0
- package/dist/debugProtocol/events/requests/SetExceptionBreakpointsRequest.js +73 -0
- package/dist/debugProtocol/events/requests/SetExceptionBreakpointsRequest.js.map +1 -0
- package/dist/debugProtocol/events/requests/VariablesRequest.d.ts +27 -1
- package/dist/debugProtocol/events/requests/VariablesRequest.js +47 -4
- package/dist/debugProtocol/events/requests/VariablesRequest.js.map +1 -1
- package/dist/debugProtocol/events/responses/SetExceptionBreakpointsResponse.d.ts +31 -0
- package/dist/debugProtocol/events/responses/SetExceptionBreakpointsResponse.js +59 -0
- package/dist/debugProtocol/events/responses/SetExceptionBreakpointsResponse.js.map +1 -0
- package/dist/debugProtocol/events/responses/VariablesResponse.d.ts +10 -1
- package/dist/debugProtocol/events/responses/VariablesResponse.js +11 -3
- package/dist/debugProtocol/events/responses/VariablesResponse.js.map +1 -1
- package/dist/debugProtocol/events/updates/ExceptionBreakpointErrorUpdate.d.ts +46 -0
- package/dist/debugProtocol/events/updates/ExceptionBreakpointErrorUpdate.js +103 -0
- package/dist/debugProtocol/events/updates/ExceptionBreakpointErrorUpdate.js.map +1 -0
- package/dist/debugProtocol/server/DebugProtocolServer.js +3 -0
- package/dist/debugProtocol/server/DebugProtocolServer.js.map +1 -1
- package/dist/debugSession/BrightScriptDebugSession.d.ts +6 -3
- package/dist/debugSession/BrightScriptDebugSession.js +143 -66
- package/dist/debugSession/BrightScriptDebugSession.js.map +1 -1
- package/dist/debugSession/Events.d.ts +1 -1
- package/dist/managers/BreakpointManager.d.ts +1 -1
- package/dist/util.d.ts +1 -0
- package/dist/util.js +3 -0
- package/dist/util.js.map +1 -1
- package/package.json +9 -9
- package/roku-debug-0.21.14.tgz +0 -0
- package/roku-debug-0.21.12.tgz +0 -0
|
@@ -5,7 +5,7 @@ const fsExtra = require("fs-extra");
|
|
|
5
5
|
const natural_orderby_1 = require("natural-orderby");
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const roku_deploy_1 = require("roku-deploy");
|
|
8
|
-
const
|
|
8
|
+
const debugadapter_1 = require("@vscode/debugadapter");
|
|
9
9
|
const SceneGraphDebugCommandController_1 = require("../SceneGraphDebugCommandController");
|
|
10
10
|
const util_1 = require("../util");
|
|
11
11
|
const FileUtils_1 = require("../FileUtils");
|
|
@@ -23,7 +23,7 @@ const logging_1 = require("../logging");
|
|
|
23
23
|
const VariablesResponse_1 = require("../debugProtocol/events/responses/VariablesResponse");
|
|
24
24
|
const brighterscript_1 = require("brighterscript");
|
|
25
25
|
const diagnosticSource = 'roku-debug';
|
|
26
|
-
class BrightScriptDebugSession extends
|
|
26
|
+
class BrightScriptDebugSession extends debugadapter_1.DebugSession {
|
|
27
27
|
constructor() {
|
|
28
28
|
super();
|
|
29
29
|
this.logger = logging_1.logger.createLogger(`[session]`);
|
|
@@ -42,12 +42,13 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
42
42
|
this.evaluateRefIdLookup = {};
|
|
43
43
|
this.evaluateRefIdCounter = 1;
|
|
44
44
|
this.variables = {};
|
|
45
|
-
this.variableHandles = new
|
|
45
|
+
this.variableHandles = new debugadapter_1.Handles();
|
|
46
46
|
this.tempVarPrefix = '__rokudebug__';
|
|
47
47
|
/**
|
|
48
48
|
* A magic number to represent a fake thread that will be used for showing compile errors in the UI as if they were runtime crashes
|
|
49
49
|
*/
|
|
50
50
|
this.COMPILE_ERROR_THREAD_ID = 7777;
|
|
51
|
+
this.exceptionBreakpoints = [];
|
|
51
52
|
this.evaluateRequestPromise = Promise.resolve();
|
|
52
53
|
this.evaluateVarIndexByFrameId = new Map();
|
|
53
54
|
/**
|
|
@@ -82,7 +83,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
82
83
|
path: breakpoint.srcPath
|
|
83
84
|
}
|
|
84
85
|
};
|
|
85
|
-
this.sendEvent(new
|
|
86
|
+
this.sendEvent(new debugadapter_1.BreakpointEvent(eventName, event));
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
get enableDebugProtocol() {
|
|
@@ -91,8 +92,10 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
91
92
|
/**
|
|
92
93
|
* Get a promise that resolves when the roku adapter is ready to be used
|
|
93
94
|
*/
|
|
94
|
-
getRokuAdapter() {
|
|
95
|
-
|
|
95
|
+
async getRokuAdapter() {
|
|
96
|
+
await this.rokuAdapterDeferred.promise;
|
|
97
|
+
await this.rokuAdapter.onReady();
|
|
98
|
+
return this.rokuAdapter;
|
|
96
99
|
}
|
|
97
100
|
/**
|
|
98
101
|
* The 'initialize' request is the first request called by the frontend
|
|
@@ -101,10 +104,6 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
101
104
|
initializeRequest(response, args) {
|
|
102
105
|
this.initRequestArgs = args;
|
|
103
106
|
this.logger.log('initializeRequest');
|
|
104
|
-
// since this debug adapter can accept configuration requests like 'setBreakpoint' at any time,
|
|
105
|
-
// we request them early by sending an 'initializeRequest' to the frontend.
|
|
106
|
-
// The frontend will end the configuration sequence by calling 'configurationDone' request.
|
|
107
|
-
this.sendEvent(new vscode_debugadapter_1.InitializedEvent());
|
|
108
107
|
response.body = response.body || {};
|
|
109
108
|
// This debug adapter implements the configurationDoneRequest.
|
|
110
109
|
response.body.supportsConfigurationDoneRequest = true;
|
|
@@ -116,6 +115,24 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
116
115
|
response.body.supportsStepBack = false;
|
|
117
116
|
// This debug adapter supports conditional breakpoints
|
|
118
117
|
response.body.supportsConditionalBreakpoints = true;
|
|
118
|
+
response.body.supportsExceptionFilterOptions = true;
|
|
119
|
+
response.body.supportsExceptionOptions = true;
|
|
120
|
+
//the list of exception breakpoints (we have to send them all the time, even if the device doesn't support them)
|
|
121
|
+
response.body.exceptionBreakpointFilters = [{
|
|
122
|
+
filter: 'caught',
|
|
123
|
+
supportsCondition: true,
|
|
124
|
+
conditionDescription: '__brs_err__.rethrown = true',
|
|
125
|
+
label: 'Caught Exceptions',
|
|
126
|
+
description: `Breaks on all errors, even if they're caught later.`,
|
|
127
|
+
default: false
|
|
128
|
+
}, {
|
|
129
|
+
filter: 'uncaught',
|
|
130
|
+
supportsCondition: true,
|
|
131
|
+
conditionDescription: '__brs_err__.rethrown = true',
|
|
132
|
+
label: 'Uncaught Exceptions',
|
|
133
|
+
description: 'Breaks only on errors that are not handled.',
|
|
134
|
+
default: true
|
|
135
|
+
}];
|
|
119
136
|
// This debug adapter supports breakpoints that break execution after a specified number of hits
|
|
120
137
|
response.body.supportsHitConditionalBreakpoints = true;
|
|
121
138
|
// This debug adapter supports log points by interpreting the 'logMessage' attribute of the SourceBreakpoint
|
|
@@ -125,8 +142,58 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
125
142
|
logging_1.debugServerLogOutputEventTransport.setWriter((message) => {
|
|
126
143
|
this.sendEvent(new Events_1.DebugServerLogOutputEvent(message.logger.formatMessage(message, false)));
|
|
127
144
|
});
|
|
145
|
+
// since this debug adapter can accept configuration requests like 'setBreakpoint' at any time,
|
|
146
|
+
// we request them early by sending an 'initializeRequest' to the frontend.
|
|
147
|
+
// The frontend will end the configuration sequence by calling 'configurationDone' request.
|
|
148
|
+
this.sendEvent(new debugadapter_1.InitializedEvent());
|
|
128
149
|
this.logger.log('initializeRequest finished');
|
|
129
150
|
}
|
|
151
|
+
async setExceptionBreakPointsRequest(response, args) {
|
|
152
|
+
var _a;
|
|
153
|
+
(_a = response.body) !== null && _a !== void 0 ? _a : (response.body = {});
|
|
154
|
+
try {
|
|
155
|
+
let filterOptions;
|
|
156
|
+
if (args.filterOptions) {
|
|
157
|
+
filterOptions = args.filterOptions.map(x => ({
|
|
158
|
+
filter: x.filterId,
|
|
159
|
+
conditionExpression: x.condition
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
else if (args.filters) {
|
|
163
|
+
filterOptions = args.filters.map(x => ({
|
|
164
|
+
filter: x
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
this.exceptionBreakpoints = filterOptions;
|
|
168
|
+
//ensure the rokuAdapter is loaded
|
|
169
|
+
await this.getRokuAdapter();
|
|
170
|
+
if (this.rokuAdapter.supportsExceptionBreakpoints) {
|
|
171
|
+
await this.rokuAdapter.setExceptionBreakpoints(filterOptions);
|
|
172
|
+
//if success
|
|
173
|
+
response.body.breakpoints = [
|
|
174
|
+
{ verified: true },
|
|
175
|
+
{ verified: true }
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
response.body.breakpoints = [
|
|
180
|
+
{ verified: false },
|
|
181
|
+
{ verified: false }
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
//if error (or not supported)
|
|
187
|
+
response.body.breakpoints = [
|
|
188
|
+
{ verified: false },
|
|
189
|
+
{ verified: false }
|
|
190
|
+
];
|
|
191
|
+
this.logger.error('Failed to set exception breakpoints', e);
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
this.sendResponse(response);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
130
197
|
showPopupMessage(message, severity, modal = false) {
|
|
131
198
|
this.logger.trace('[showPopupMessage]', severity, message);
|
|
132
199
|
this.sendEvent(new Events_1.PopupMessageEvent(message, severity, modal));
|
|
@@ -279,6 +346,9 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
279
346
|
const message = 'App exit detected; but launchConfiguration.stopDebuggerOnAppExit is set to false, so keeping debug session running.';
|
|
280
347
|
this.logger.log('[launchRequest]', message);
|
|
281
348
|
this.sendEvent(new Events_1.LogOutputEvent(message));
|
|
349
|
+
void this.rokuAdapter.once('connected').then(async () => {
|
|
350
|
+
await this.rokuAdapter.setExceptionBreakpoints(this.exceptionBreakpoints);
|
|
351
|
+
});
|
|
282
352
|
}
|
|
283
353
|
});
|
|
284
354
|
await this.publish();
|
|
@@ -388,7 +458,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
388
458
|
//find the first compile error (i.e. first DiagnosticSeverity.Error) if there is one
|
|
389
459
|
this.compileError = diagnostics.find(x => x.severity === brighterscript_1.DiagnosticSeverity.Error);
|
|
390
460
|
if (this.compileError) {
|
|
391
|
-
this.sendEvent(new
|
|
461
|
+
this.sendEvent(new debugadapter_1.StoppedEvent(Events_1.StoppedEventReason.exception, this.COMPILE_ERROR_THREAD_ID, `CompileError: ${this.compileError.message}`));
|
|
392
462
|
}
|
|
393
463
|
this.sendEvent(new Events_1.DiagnosticsEvent(diagnostics));
|
|
394
464
|
}
|
|
@@ -409,8 +479,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
409
479
|
const statusCode = (_b = (_a = e === null || e === void 0 ? void 0 : e.results) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode;
|
|
410
480
|
const message = e.message;
|
|
411
481
|
if (statusCode === 401) {
|
|
412
|
-
this.
|
|
413
|
-
await this.shutdown(message);
|
|
482
|
+
await this.shutdown(message, true);
|
|
414
483
|
throw e;
|
|
415
484
|
}
|
|
416
485
|
this.logger.warn('Failed to delete the dev channel...probably not a big deal', e);
|
|
@@ -441,9 +510,8 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
441
510
|
var _a, _b;
|
|
442
511
|
const statusCode = (_b = (_a = e === null || e === void 0 ? void 0 : e.results) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode;
|
|
443
512
|
const message = e.message;
|
|
444
|
-
if (statusCode && statusCode !== 200) {
|
|
445
|
-
this.
|
|
446
|
-
await this.shutdown(message);
|
|
513
|
+
if ((statusCode && statusCode !== 200) || (0, roku_deploy_1.isUpdateCheckRequiredError)(e) || (0, roku_deploy_1.isConnectionResetError)(e)) {
|
|
514
|
+
await this.shutdown(message, true);
|
|
447
515
|
throw e;
|
|
448
516
|
}
|
|
449
517
|
this.logger.error(e);
|
|
@@ -471,7 +539,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
471
539
|
const lines = logOutput.split(/\r?\n/g);
|
|
472
540
|
for (let line of lines) {
|
|
473
541
|
line += '\n';
|
|
474
|
-
this.sendEvent(new
|
|
542
|
+
this.sendEvent(new debugadapter_1.OutputEvent(line, 'stdout'));
|
|
475
543
|
this.sendEvent(new Events_1.LogOutputEvent(line));
|
|
476
544
|
}
|
|
477
545
|
}
|
|
@@ -672,7 +740,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
672
740
|
let threads = [];
|
|
673
741
|
//This is a bit of a hack. If there's a compile error, send a thread to represent it so we can show the compile error like a runtime exception
|
|
674
742
|
if (this.compileError) {
|
|
675
|
-
threads.push(new
|
|
743
|
+
threads.push(new debugadapter_1.Thread(this.COMPILE_ERROR_THREAD_ID, 'Compile Error'));
|
|
676
744
|
}
|
|
677
745
|
else {
|
|
678
746
|
//wait for the roku adapter to load
|
|
@@ -681,7 +749,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
681
749
|
if (this.rokuAdapter.isAtDebuggerPrompt) {
|
|
682
750
|
let rokuThreads = await this.rokuAdapter.getThreads();
|
|
683
751
|
for (let thread of rokuThreads) {
|
|
684
|
-
threads.push(new
|
|
752
|
+
threads.push(new debugadapter_1.Thread(thread.threadId, `Thread ${thread.threadId}`));
|
|
685
753
|
}
|
|
686
754
|
if (threads.length === 0) {
|
|
687
755
|
threads = [{
|
|
@@ -707,12 +775,12 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
707
775
|
let frames = [];
|
|
708
776
|
//this is a bit of a hack. If there's a compile error, send a full stack frame so we can show the compile error like a runtime crash
|
|
709
777
|
if (this.compileError) {
|
|
710
|
-
frames.push(new
|
|
778
|
+
frames.push(new debugadapter_1.StackFrame(0, 'Compile Error', new debugadapter_1.Source(path.basename(this.compileError.path), this.compileError.path),
|
|
711
779
|
//diagnostics are 0 based, vscode expects 1 based
|
|
712
780
|
this.compileError.range.start.line + 1, this.compileError.range.start.character + 1));
|
|
713
781
|
}
|
|
714
782
|
else if (args.threadId === 1001) {
|
|
715
|
-
frames.push(new
|
|
783
|
+
frames.push(new debugadapter_1.StackFrame(0, 'ERROR: threads would not stop', new debugadapter_1.Source('main.brs', (0, FileUtils_1.standardizePath) `${this.launchConfiguration.stagingDir}/manifest`), 1, 1));
|
|
716
784
|
this.showPopupMessage('Unable to suspend threads. Debugger is in an unstable state, please press Continue to resume debugging', 'warn');
|
|
717
785
|
}
|
|
718
786
|
else {
|
|
@@ -739,7 +807,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
739
807
|
this.logger.error('Error correcting function identifier case', { error, sourceLocation, debugFrame });
|
|
740
808
|
}
|
|
741
809
|
const filePath = (_a = sourceLocation === null || sourceLocation === void 0 ? void 0 : sourceLocation.filePath) !== null && _a !== void 0 ? _a : debugFrame.filePath;
|
|
742
|
-
const frame = new
|
|
810
|
+
const frame = new debugadapter_1.StackFrame(debugFrame.frameId, `${debugFrame.functionIdentifier}`, new debugadapter_1.Source(path.basename(filePath), filePath), (_b = sourceLocation === null || sourceLocation === void 0 ? void 0 : sourceLocation.lineNumber) !== null && _b !== void 0 ? _b : debugFrame.lineNumber, 1);
|
|
743
811
|
if (!sourceLocation) {
|
|
744
812
|
frame.presentationHint = 'subtle';
|
|
745
813
|
}
|
|
@@ -783,12 +851,12 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
783
851
|
v.request_seq = response.request_seq;
|
|
784
852
|
v.frameId = args.frameId;
|
|
785
853
|
}
|
|
786
|
-
let scope = new
|
|
854
|
+
let scope = new debugadapter_1.Scope('Local', refId, false);
|
|
787
855
|
scopes.push(scope);
|
|
788
856
|
}
|
|
789
857
|
else {
|
|
790
858
|
// NOTE: Legacy telnet support
|
|
791
|
-
scopes.push(new
|
|
859
|
+
scopes.push(new debugadapter_1.Scope('Local', this.variableHandles.create('local'), false));
|
|
792
860
|
}
|
|
793
861
|
response.body = {
|
|
794
862
|
scopes: scopes
|
|
@@ -901,13 +969,14 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
901
969
|
if (this.launchConfiguration.enableVariablesPanel) {
|
|
902
970
|
const vars = await this.rokuAdapter.getScopeVariables();
|
|
903
971
|
for (const varName of vars) {
|
|
904
|
-
let
|
|
972
|
+
let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: varName, frameId: -1 }, util_1.util.getVariablePath(varName));
|
|
973
|
+
let result = await this.rokuAdapter.getVariable(evalArgs.expression, -1);
|
|
905
974
|
let tempVar = this.getVariableFromResult(result, -1);
|
|
906
975
|
childVariables.push(tempVar);
|
|
907
976
|
}
|
|
908
977
|
}
|
|
909
978
|
else {
|
|
910
|
-
childVariables.push(new
|
|
979
|
+
childVariables.push(new debugadapter_1.Variable('variables disabled by launch.json setting', 'enableVariablesPanel: false'));
|
|
911
980
|
}
|
|
912
981
|
}
|
|
913
982
|
else {
|
|
@@ -921,7 +990,8 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
921
990
|
logger.log('variable', v);
|
|
922
991
|
//query for child vars if we haven't done it yet.
|
|
923
992
|
if (v.childVariables.length === 0) {
|
|
924
|
-
let
|
|
993
|
+
let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: v.evaluateName, frameId: v.frameId }, util_1.util.getVariablePath(v.evaluateName));
|
|
994
|
+
let result = await this.rokuAdapter.getVariable(evalArgs.expression, v.frameId);
|
|
925
995
|
let tempVar = this.getVariableFromResult(result, v.frameId);
|
|
926
996
|
tempVar.frameId = v.frameId;
|
|
927
997
|
v.childVariables = tempVar.childVariables;
|
|
@@ -981,7 +1051,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
981
1051
|
if (!this.rokuAdapter.isAtDebuggerPrompt) {
|
|
982
1052
|
let message = 'Skipped evaluate request because RokuAdapter is not accepting requests at this time';
|
|
983
1053
|
if (args.context === 'repl') {
|
|
984
|
-
this.sendEvent(new
|
|
1054
|
+
this.sendEvent(new debugadapter_1.OutputEvent(message, 'stderr'));
|
|
985
1055
|
response.body = {
|
|
986
1056
|
result: 'invalid',
|
|
987
1057
|
variablesReference: 0
|
|
@@ -993,40 +1063,25 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
993
1063
|
//is at debugger prompt
|
|
994
1064
|
}
|
|
995
1065
|
else {
|
|
996
|
-
let variablePath = util_1.util.getVariablePath(args.expression);
|
|
997
|
-
if (!variablePath && util_1.util.isAssignableExpression(args.expression)) {
|
|
998
|
-
let varIndex = this.getNextVarIndex(args.frameId);
|
|
999
|
-
let arrayVarName = this.tempVarPrefix + 'eval';
|
|
1000
|
-
if (varIndex === 0) {
|
|
1001
|
-
const response = await this.rokuAdapter.evaluate(`${arrayVarName} = []`, args.frameId);
|
|
1002
|
-
console.log(response);
|
|
1003
|
-
}
|
|
1004
|
-
let statement = `${arrayVarName}[${varIndex}] = ${args.expression}`;
|
|
1005
|
-
args.expression = `${arrayVarName}[${varIndex}]`;
|
|
1006
|
-
let commandResults = await this.rokuAdapter.evaluate(statement, args.frameId);
|
|
1007
|
-
if (commandResults.type === 'error') {
|
|
1008
|
-
throw new Error(commandResults.message);
|
|
1009
|
-
}
|
|
1010
|
-
variablePath = [arrayVarName, varIndex.toString()];
|
|
1011
|
-
}
|
|
1066
|
+
let { evalArgs, variablePath } = await this.evaluateExpressionToTempVar(args, util_1.util.getVariablePath(args.expression));
|
|
1012
1067
|
//if we found a variable path (e.g. ['a', 'b', 'c']) then do a variable lookup because it's faster and more widely supported than `evaluate`
|
|
1013
1068
|
if (variablePath) {
|
|
1014
|
-
let refId = this.getEvaluateRefId(
|
|
1069
|
+
let refId = this.getEvaluateRefId(evalArgs.expression, evalArgs.frameId);
|
|
1015
1070
|
let v;
|
|
1016
1071
|
//if we already looked this item up, return it
|
|
1017
1072
|
if (this.variables[refId]) {
|
|
1018
1073
|
v = this.variables[refId];
|
|
1019
1074
|
}
|
|
1020
1075
|
else {
|
|
1021
|
-
let result = await this.rokuAdapter.getVariable(
|
|
1076
|
+
let result = await this.rokuAdapter.getVariable(evalArgs.expression, evalArgs.frameId);
|
|
1022
1077
|
if (!result) {
|
|
1023
1078
|
throw new Error('Error: unable to evaluate expression');
|
|
1024
1079
|
}
|
|
1025
|
-
v = this.getVariableFromResult(result,
|
|
1080
|
+
v = this.getVariableFromResult(result, evalArgs.frameId);
|
|
1026
1081
|
//TODO - testing something, remove later
|
|
1027
1082
|
// eslint-disable-next-line camelcase
|
|
1028
1083
|
v.request_seq = response.request_seq;
|
|
1029
|
-
v.frameId =
|
|
1084
|
+
v.frameId = evalArgs.frameId;
|
|
1030
1085
|
}
|
|
1031
1086
|
response.body = {
|
|
1032
1087
|
result: v.value,
|
|
@@ -1038,16 +1093,16 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1038
1093
|
//run an `evaluate` call
|
|
1039
1094
|
}
|
|
1040
1095
|
else {
|
|
1041
|
-
let commandResults = await this.rokuAdapter.evaluate(
|
|
1096
|
+
let commandResults = await this.rokuAdapter.evaluate(evalArgs.expression, evalArgs.frameId);
|
|
1042
1097
|
commandResults.message = util_1.util.trimDebugPrompt(commandResults.message);
|
|
1043
1098
|
if (args.context !== 'watch') {
|
|
1044
1099
|
//clear variable cache since this action could have side-effects
|
|
1045
1100
|
this.clearState();
|
|
1046
|
-
this.sendInvalidatedEvent(null,
|
|
1101
|
+
this.sendInvalidatedEvent(null, evalArgs.frameId);
|
|
1047
1102
|
}
|
|
1048
1103
|
//if the adapter captured output (probably only telnet), print it to the vscode debug console
|
|
1049
1104
|
if (typeof commandResults.message === 'string') {
|
|
1050
|
-
this.sendEvent(new
|
|
1105
|
+
this.sendEvent(new debugadapter_1.OutputEvent(commandResults.message, commandResults.type === 'error' ? 'stderr' : 'stdio'));
|
|
1051
1106
|
}
|
|
1052
1107
|
if (this.enableDebugProtocol || (typeof commandResults.message !== 'string')) {
|
|
1053
1108
|
response.body = {
|
|
@@ -1075,6 +1130,25 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1075
1130
|
catch (_b) { }
|
|
1076
1131
|
deferred.resolve();
|
|
1077
1132
|
}
|
|
1133
|
+
async evaluateExpressionToTempVar(args, variablePath) {
|
|
1134
|
+
let returnVal = { evalArgs: args, variablePath };
|
|
1135
|
+
if (!variablePath && util_1.util.isAssignableExpression(args.expression)) {
|
|
1136
|
+
let varIndex = this.getNextVarIndex(args.frameId);
|
|
1137
|
+
let arrayVarName = this.tempVarPrefix + 'eval';
|
|
1138
|
+
if (varIndex === 0) {
|
|
1139
|
+
const response = await this.rokuAdapter.evaluate(`${arrayVarName} = []`, args.frameId);
|
|
1140
|
+
console.log(response);
|
|
1141
|
+
}
|
|
1142
|
+
let statement = `${arrayVarName}[${varIndex}] = ${args.expression}`;
|
|
1143
|
+
returnVal.evalArgs.expression = `${arrayVarName}[${varIndex}]`;
|
|
1144
|
+
let commandResults = await this.rokuAdapter.evaluate(statement, args.frameId);
|
|
1145
|
+
if (commandResults.type === 'error') {
|
|
1146
|
+
throw new Error(commandResults.message);
|
|
1147
|
+
}
|
|
1148
|
+
returnVal.variablePath = [arrayVarName, varIndex.toString()];
|
|
1149
|
+
}
|
|
1150
|
+
return returnVal;
|
|
1151
|
+
}
|
|
1078
1152
|
/**
|
|
1079
1153
|
* Called when the host stops debugging
|
|
1080
1154
|
* @param response
|
|
@@ -1128,7 +1202,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1128
1202
|
let rokuAdapter = await this.getRokuAdapter();
|
|
1129
1203
|
let threads = await rokuAdapter.getThreads();
|
|
1130
1204
|
let threadId = (_a = threads[0]) === null || _a === void 0 ? void 0 : _a.threadId;
|
|
1131
|
-
this.sendEvent(new
|
|
1205
|
+
this.sendEvent(new debugadapter_1.StoppedEvent(Events_1.StoppedEventReason.exception, threadId, exception.message));
|
|
1132
1206
|
});
|
|
1133
1207
|
// If the roku says it can't continue, we are no longer able to debug, so kill the debug session
|
|
1134
1208
|
this.rokuAdapter.on('cannot-continue', () => {
|
|
@@ -1181,7 +1255,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1181
1255
|
}
|
|
1182
1256
|
}
|
|
1183
1257
|
this.clearState();
|
|
1184
|
-
const event = new
|
|
1258
|
+
const event = new debugadapter_1.StoppedEvent(Events_1.StoppedEventReason.breakpoint,
|
|
1185
1259
|
//Not sure why, but sometimes there is no active thread. Just pick thread 0 to prevent the app from totally crashing
|
|
1186
1260
|
(_b = activeThread === null || activeThread === void 0 ? void 0 : activeThread.threadId) !== null && _b !== void 0 ? _b : 0, '' //exception text
|
|
1187
1261
|
);
|
|
@@ -1199,12 +1273,12 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1199
1273
|
// check to see if this is an dictionary or a list
|
|
1200
1274
|
if (result.keyType === 'Integer') {
|
|
1201
1275
|
// list type
|
|
1202
|
-
v = new
|
|
1276
|
+
v = new debugadapter_1.Variable(result.name, result.type, refId, result.elementCount, 0);
|
|
1203
1277
|
this.variables[refId] = v;
|
|
1204
1278
|
}
|
|
1205
1279
|
else if (result.keyType === 'String') {
|
|
1206
1280
|
// dictionary type
|
|
1207
|
-
v = new
|
|
1281
|
+
v = new debugadapter_1.Variable(result.name, result.type, refId, 0, result.elementCount);
|
|
1208
1282
|
}
|
|
1209
1283
|
}
|
|
1210
1284
|
else {
|
|
@@ -1218,30 +1292,30 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1218
1292
|
else {
|
|
1219
1293
|
value = `${result.value}`;
|
|
1220
1294
|
}
|
|
1221
|
-
v = new
|
|
1295
|
+
v = new debugadapter_1.Variable(result.name, value);
|
|
1222
1296
|
}
|
|
1223
1297
|
this.variables[refId] = v;
|
|
1224
1298
|
}
|
|
1225
1299
|
else {
|
|
1226
1300
|
if (result.highLevelType === 'primative' || result.highLevelType === 'uninitialized') {
|
|
1227
|
-
v = new
|
|
1301
|
+
v = new debugadapter_1.Variable(result.name, `${result.value}`);
|
|
1228
1302
|
}
|
|
1229
1303
|
else if (result.highLevelType === 'array') {
|
|
1230
1304
|
let refId = this.getEvaluateRefId(result.evaluateName, frameId);
|
|
1231
|
-
v = new
|
|
1305
|
+
v = new debugadapter_1.Variable(result.name, result.type, refId, (_c = (_b = result.children) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0, 0);
|
|
1232
1306
|
this.variables[refId] = v;
|
|
1233
1307
|
}
|
|
1234
1308
|
else if (result.highLevelType === 'object') {
|
|
1235
1309
|
let refId = this.getEvaluateRefId(result.evaluateName, frameId);
|
|
1236
|
-
v = new
|
|
1310
|
+
v = new debugadapter_1.Variable(result.name, result.type, refId, 0, (_e = (_d = result.children) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0);
|
|
1237
1311
|
this.variables[refId] = v;
|
|
1238
1312
|
}
|
|
1239
1313
|
else if (result.highLevelType === 'function') {
|
|
1240
|
-
v = new
|
|
1314
|
+
v = new debugadapter_1.Variable(result.name, result.value);
|
|
1241
1315
|
}
|
|
1242
1316
|
else {
|
|
1243
1317
|
//all other cases, but mostly for HighLevelType.unknown
|
|
1244
|
-
v = new
|
|
1318
|
+
v = new debugadapter_1.Variable(result.name, result.value);
|
|
1245
1319
|
}
|
|
1246
1320
|
}
|
|
1247
1321
|
v.type = result.type;
|
|
@@ -1249,6 +1323,9 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1249
1323
|
v.frameId = frameId;
|
|
1250
1324
|
v.type = result.type;
|
|
1251
1325
|
v.presentationHint = result.presentationHint ? { kind: result.presentationHint } : undefined;
|
|
1326
|
+
if (util_1.util.isTransientVariable(v.name)) {
|
|
1327
|
+
v.presentationHint = { kind: 'virtual' };
|
|
1328
|
+
}
|
|
1252
1329
|
if (result.children) {
|
|
1253
1330
|
let childVariables = [];
|
|
1254
1331
|
for (let childContainer of result.children) {
|
|
@@ -1283,7 +1360,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1283
1360
|
sendInvalidatedEvent(threadId, stackFrameId) {
|
|
1284
1361
|
//if the client supports this request, send it
|
|
1285
1362
|
if (this.initRequestArgs.supportsInvalidatedEvent) {
|
|
1286
|
-
this.sendEvent(new
|
|
1363
|
+
this.sendEvent(new debugadapter_1.InvalidatedEvent(['variables'], threadId, stackFrameId));
|
|
1287
1364
|
}
|
|
1288
1365
|
}
|
|
1289
1366
|
/**
|
|
@@ -1301,7 +1378,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1301
1378
|
* Called when the debugger is terminated. Feel free to call this as frequently as you want; we'll only run the shutdown process the first time, and return
|
|
1302
1379
|
* the same promise on subsequent calls
|
|
1303
1380
|
*/
|
|
1304
|
-
async shutdown(errorMessage) {
|
|
1381
|
+
async shutdown(errorMessage, modal = false) {
|
|
1305
1382
|
if (this.shutdownPromise === undefined) {
|
|
1306
1383
|
this.logger.log('[shutdown] Beginning shutdown sequence', errorMessage);
|
|
1307
1384
|
this.shutdownPromise = this._shutdown(errorMessage);
|
|
@@ -1311,7 +1388,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1311
1388
|
}
|
|
1312
1389
|
return this.shutdownPromise;
|
|
1313
1390
|
}
|
|
1314
|
-
async _shutdown(errorMessage) {
|
|
1391
|
+
async _shutdown(errorMessage, modal = false) {
|
|
1315
1392
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
1316
1393
|
try {
|
|
1317
1394
|
(_a = this.componentLibraryServer) === null || _a === void 0 ? void 0 : _a.stop();
|
|
@@ -1333,7 +1410,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1333
1410
|
//if there was an error message, display it to the user
|
|
1334
1411
|
if (errorMessage) {
|
|
1335
1412
|
this.logger.error(errorMessage);
|
|
1336
|
-
this.showPopupMessage(errorMessage, 'error');
|
|
1413
|
+
this.showPopupMessage(errorMessage, 'error', modal);
|
|
1337
1414
|
}
|
|
1338
1415
|
this.logger.log('Destroy rokuAdapter');
|
|
1339
1416
|
await ((_g = (_f = this.rokuAdapter) === null || _f === void 0 ? void 0 : _f.destroy) === null || _g === void 0 ? void 0 : _g.call(_f));
|
|
@@ -1346,7 +1423,7 @@ class BrightScriptDebugSession extends vscode_debugadapter_1.DebugSession {
|
|
|
1346
1423
|
this.logger.error(e);
|
|
1347
1424
|
}
|
|
1348
1425
|
this.logger.log('Send terminated event');
|
|
1349
|
-
this.sendEvent(new
|
|
1426
|
+
this.sendEvent(new debugadapter_1.TerminatedEvent());
|
|
1350
1427
|
//shut down the process
|
|
1351
1428
|
this.logger.log('super.shutdown()');
|
|
1352
1429
|
super.shutdown();
|