roku-debug 0.21.22 → 0.21.23

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.
@@ -49,7 +49,6 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
49
49
  this.evaluateRefIdLookup = {};
50
50
  this.evaluateRefIdCounter = 1;
51
51
  this.variables = {};
52
- this.variableHandles = new debugadapter_1.Handles();
53
52
  this.tempVarPrefix = '__rokudebug__';
54
53
  /**
55
54
  * 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
@@ -258,7 +257,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
258
257
  * @returns
259
258
  */
260
259
  normalizeLaunchConfig(config) {
261
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
260
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
262
261
  (_a = config.cwd) !== null && _a !== void 0 ? _a : (config.cwd = process.cwd());
263
262
  (_b = config.outDir) !== null && _b !== void 0 ? _b : (config.outDir = (0, FileUtils_1.standardizePath) `${config.cwd}/out`);
264
263
  (_c = config.stagingDir) !== null && _c !== void 0 ? _c : (config.stagingDir = (0, FileUtils_1.standardizePath) `${config.outDir}/.roku-deploy-staging`);
@@ -273,6 +272,11 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
273
272
  (_m = config.rewriteDevicePathsInLogs) !== null && _m !== void 0 ? _m : (config.rewriteDevicePathsInLogs = true);
274
273
  (_o = config.autoResolveVirtualVariables) !== null && _o !== void 0 ? _o : (config.autoResolveVirtualVariables = false);
275
274
  (_p = config.enhanceREPLCompletions) !== null && _p !== void 0 ? _p : (config.enhanceREPLCompletions = true);
275
+ // migrate the old `enableVariablesPanel` setting to the new `deferScopeLoading` setting
276
+ if (typeof config.enableVariablesPanel !== 'boolean') {
277
+ config.enableVariablesPanel = true;
278
+ }
279
+ (_q = config.deferScopeLoading) !== null && _q !== void 0 ? _q : (config.deferScopeLoading = config.enableVariablesPanel === false);
276
280
  return config;
277
281
  }
278
282
  async launchRequest(response, config) {
@@ -990,56 +994,49 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
990
994
  this.logger.error('Error getting stacktrace', { error, args });
991
995
  }
992
996
  }
993
- async scopesRequest(response, args) {
997
+ scopesRequest(response, args) {
994
998
  const logger = this.logger.createLogger(`scopesRequest ${this.idCounter}`);
995
999
  logger.info('begin', { args });
996
1000
  try {
997
1001
  const scopes = new Array();
998
- if ((0, DebugProtocolAdapter_1.isDebugProtocolAdapter)(this.rokuAdapter)) {
999
- let refId = this.getEvaluateRefId('', args.frameId);
1000
- let v;
1001
- //if we already looked this item up, return it
1002
- if (this.variables[refId]) {
1003
- v = this.variables[refId];
1004
- }
1005
- else {
1006
- let result = await this.rokuAdapter.getLocalVariables(args.frameId);
1007
- if (!result) {
1008
- throw new Error(`Could not get scopes`);
1009
- }
1010
- v = await this.getVariableFromResult(result, args.frameId);
1011
- //TODO - testing something, remove later
1012
- // eslint-disable-next-line camelcase
1013
- v.request_seq = response.request_seq;
1014
- v.frameId = args.frameId;
1015
- }
1016
- scopes.push({
1017
- name: 'Local',
1018
- variablesReference: v.variablesReference,
1019
- expensive: false,
1020
- presentationHint: 'locals'
1021
- });
1002
+ let v;
1003
+ // create the locals scope
1004
+ let localsRefId = this.getEvaluateRefId('$$locals', args.frameId);
1005
+ if (this.variables[localsRefId]) {
1006
+ v = this.variables[localsRefId];
1022
1007
  }
1023
1008
  else {
1024
- // NOTE: Legacy telnet support
1025
- scopes.push({
1026
- name: 'Local',
1027
- variablesReference: this.variableHandles.create('local'),
1028
- expensive: false,
1029
- presentationHint: 'locals'
1030
- });
1009
+ v = {
1010
+ variablesReference: localsRefId,
1011
+ name: 'Locals',
1012
+ value: '',
1013
+ type: '$$Locals',
1014
+ frameId: args.frameId,
1015
+ isScope: true,
1016
+ childVariables: []
1017
+ };
1018
+ this.variables[localsRefId] = v;
1031
1019
  }
1032
- let refId = this.getEvaluateRefId('$$registry', Infinity);
1020
+ scopes.push({
1021
+ name: 'Local',
1022
+ variablesReference: v.variablesReference,
1023
+ // Flag the locals scope as expensive if the client asked that it be loaded lazily
1024
+ expensive: this.launchConfiguration.deferScopeLoading,
1025
+ presentationHint: 'locals'
1026
+ });
1027
+ // create the registry scope
1028
+ let registryRefId = this.getEvaluateRefId('$$registry', Infinity);
1033
1029
  scopes.push({
1034
1030
  name: 'Registry',
1035
- variablesReference: refId,
1031
+ variablesReference: registryRefId,
1036
1032
  expensive: true
1037
1033
  });
1038
- this.variables[refId] = {
1039
- variablesReference: refId,
1034
+ this.variables[registryRefId] = {
1035
+ variablesReference: registryRefId,
1040
1036
  name: 'Registry',
1041
1037
  value: '',
1042
1038
  type: '$$Registry',
1039
+ isScope: true,
1043
1040
  childVariables: []
1044
1041
  };
1045
1042
  response.body = {
@@ -1160,99 +1157,77 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1160
1157
  response.message = 'Debug session is not paused';
1161
1158
  return this.sendResponse(response);
1162
1159
  }
1163
- const reference = this.variableHandles.get(args.variablesReference);
1164
- if (reference) {
1165
- logger.log('reference', reference);
1166
- // NOTE: Legacy telnet support for local vars
1167
- if (this.launchConfiguration.enableVariablesPanel) {
1168
- const vars = await this.rokuAdapter.getScopeVariables();
1169
- for (const varName of vars) {
1170
- let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: varName, frameId: -1 }, util_1.util.getVariablePath(varName));
1171
- let result = await this.rokuAdapter.getVariable(evalArgs.expression, -1);
1172
- let tempVar = await this.getVariableFromResult(result, -1);
1173
- updatedVariables.push(tempVar);
1174
- }
1175
- }
1176
- else {
1177
- updatedVariables.push(new debugadapter_1.Variable('variables disabled by launch.json setting', 'enableVariablesPanel: false'));
1178
- }
1179
- this.variables[args.variablesReference] = new debugadapter_1.Variable('', '', args.variablesReference, 0, updatedVariables.length);
1180
- this.variables[args.variablesReference].childVariables = updatedVariables;
1160
+ //find the variable with this reference
1161
+ let v = this.variables[args.variablesReference];
1162
+ if (!v) {
1163
+ response.success = false;
1164
+ response.message = `Variable reference has expired`;
1165
+ return this.sendResponse(response);
1181
1166
  }
1182
- else {
1183
- //find the variable with this reference
1184
- let v = this.variables[args.variablesReference];
1185
- if (!v) {
1186
- response.success = false;
1187
- response.message = `Variable reference has expired`;
1188
- return this.sendResponse(response);
1189
- }
1190
- logger.log('variable', v);
1191
- if (v.type === '$$Registry' && v.childVariables.length === 0) {
1192
- // This is a special scope variable used to load registry data via an ECP call
1193
- // Send the registry ECP call for the `dev` app as side loaded apps are always `dev`
1194
- await (0, ecpRegistryUtils_1.populateVariableFromRegistryEcp)({ host: this.launchConfiguration.host, remotePort: this.launchConfiguration.remotePort, appId: 'dev' }, v, this.variables, this.getEvaluateRefId.bind(this));
1195
- }
1196
- //query for child vars if we haven't done it yet or DAP is asking to resolve a lazy variable
1197
- if (v.childVariables.length === 0 || v.isResolved) {
1198
- let tempVar;
1199
- if (!v.isResolved) {
1200
- // Evaluate the variable
1201
- try {
1202
- let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: v.evaluateName, frameId: v.frameId }, util_1.util.getVariablePath(v.evaluateName));
1203
- let result = await this.rokuAdapter.getVariable(evalArgs.expression, v.frameId);
1204
- tempVar = await this.getVariableFromResult(result, v.frameId);
1205
- tempVar.frameId = v.frameId;
1206
- // Determine if the variable has changed
1207
- sendInvalidatedEvent = v.type !== tempVar.type || v.indexedVariables !== tempVar.indexedVariables;
1208
- }
1209
- catch (error) {
1210
- logger.error('Error getting variables', error);
1211
- tempVar = new debugadapter_1.Variable('Error', `❌ Error: ${error.message}`);
1212
- tempVar.type = '';
1213
- tempVar.childVariables = [];
1214
- sendInvalidatedEvent = true;
1215
- response.success = false;
1216
- response.message = error.message;
1217
- }
1218
- // Merge the resulting updates together
1219
- v.childVariables = tempVar.childVariables;
1220
- v.value = tempVar.value;
1221
- v.type = tempVar.type;
1222
- v.indexedVariables = tempVar.indexedVariables;
1223
- v.namedVariables = tempVar.namedVariables;
1167
+ logger.log('variable', v);
1168
+ // Populate scope level values if needed
1169
+ if (v.isScope) {
1170
+ await this.populateScopeVariables(v, args);
1171
+ }
1172
+ //query for child vars if we haven't done it yet or DAP is asking to resolve a lazy variable
1173
+ if (v.childVariables.length === 0 || v.isResolved) {
1174
+ let tempVar;
1175
+ if (!v.isResolved) {
1176
+ // Evaluate the variable
1177
+ try {
1178
+ let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: v.evaluateName, frameId: v.frameId }, util_1.util.getVariablePath(v.evaluateName));
1179
+ let result = await this.rokuAdapter.getVariable(evalArgs.expression, v.frameId);
1180
+ tempVar = await this.getVariableFromResult(result, v.frameId);
1181
+ tempVar.frameId = v.frameId;
1182
+ // Determine if the variable has changed
1183
+ sendInvalidatedEvent = v.type !== tempVar.type || v.indexedVariables !== tempVar.indexedVariables;
1224
1184
  }
1225
- frameId = v.frameId;
1226
- if (((_b = v === null || v === void 0 ? void 0 : v.presentationHint) === null || _b === void 0 ? void 0 : _b.lazy) || v.isResolved) {
1227
- // If this was a lazy variable we need to respond with the updated variable and not the children
1228
- if (v.isResolved && v.childVariables.length > 0) {
1229
- updatedVariables = v.childVariables;
1230
- }
1231
- else {
1232
- updatedVariables = [v];
1233
- }
1234
- v.isResolved = true;
1185
+ catch (error) {
1186
+ logger.error('Error getting variables', error);
1187
+ tempVar = new debugadapter_1.Variable('Error', `❌ Error: ${error.message}`);
1188
+ tempVar.type = '';
1189
+ tempVar.childVariables = [];
1190
+ sendInvalidatedEvent = true;
1191
+ response.success = false;
1192
+ response.message = error.message;
1235
1193
  }
1236
- else {
1194
+ // Merge the resulting updates together
1195
+ v.childVariables = tempVar.childVariables;
1196
+ v.value = tempVar.value;
1197
+ v.type = tempVar.type;
1198
+ v.indexedVariables = tempVar.indexedVariables;
1199
+ v.namedVariables = tempVar.namedVariables;
1200
+ }
1201
+ frameId = v.frameId;
1202
+ if (((_b = v === null || v === void 0 ? void 0 : v.presentationHint) === null || _b === void 0 ? void 0 : _b.lazy) || v.isResolved) {
1203
+ // If this was a lazy variable we need to respond with the updated variable and not the children
1204
+ if (v.isResolved && v.childVariables.length > 0) {
1237
1205
  updatedVariables = v.childVariables;
1238
1206
  }
1239
- // If the variable has no children, set the reference to 0
1240
- // so it does not look expandable in the Ui
1241
- if (v.childVariables.length === 0) {
1242
- v.variablesReference = 0;
1243
- }
1244
- // If the variable was resolve in the past we may not have fetched a new temp var
1245
- tempVar !== null && tempVar !== void 0 ? tempVar : (tempVar = v);
1246
- if (v === null || v === void 0 ? void 0 : v.presentationHint) {
1247
- v.presentationHint.lazy = (_c = tempVar.presentationHint) === null || _c === void 0 ? void 0 : _c.lazy;
1248
- }
1249
1207
  else {
1250
- v.presentationHint = tempVar.presentationHint;
1208
+ updatedVariables = [v];
1251
1209
  }
1210
+ v.isResolved = true;
1252
1211
  }
1253
1212
  else {
1254
1213
  updatedVariables = v.childVariables;
1255
1214
  }
1215
+ // If the variable has no children, set the reference to 0
1216
+ // so it does not look expandable in the Ui
1217
+ if (v.childVariables.length === 0) {
1218
+ v.variablesReference = 0;
1219
+ }
1220
+ // If the variable was resolve in the past we may not have fetched a new temp var
1221
+ tempVar !== null && tempVar !== void 0 ? tempVar : (tempVar = v);
1222
+ if (v === null || v === void 0 ? void 0 : v.presentationHint) {
1223
+ v.presentationHint.lazy = (_c = tempVar.presentationHint) === null || _c === void 0 ? void 0 : _c.lazy;
1224
+ }
1225
+ else {
1226
+ v.presentationHint = tempVar.presentationHint;
1227
+ }
1228
+ }
1229
+ else {
1230
+ updatedVariables = v.childVariables;
1256
1231
  }
1257
1232
  // Only send the updated variables if we are not going to trigger an invalidated event.
1258
1233
  // This is to prevent the UI from updating twice and makes the experience much smoother to the end user.
@@ -1310,6 +1285,79 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1310
1285
  }
1311
1286
  return filteredUpdatedVariables;
1312
1287
  }
1288
+ /**
1289
+ * Takes a scope variable and populates its child variables based on the scope type and the current adapter type.
1290
+ * @param v scope variable to populate
1291
+ * @param args
1292
+ */
1293
+ async populateScopeVariables(v, args) {
1294
+ if (v.childVariables.length > 0) {
1295
+ // Already populated
1296
+ return;
1297
+ }
1298
+ let tempVar;
1299
+ try {
1300
+ if (v.type === '$$Locals') {
1301
+ if (this.rokuAdapter.isDebugProtocolAdapter()) {
1302
+ let result = await this.rokuAdapter.getLocalVariables(v.frameId);
1303
+ tempVar = await this.getVariableFromResult(result, v.frameId);
1304
+ }
1305
+ else if (this.rokuAdapter.isTelnetAdapter()) {
1306
+ // NOTE: Legacy telnet support
1307
+ let variables = [];
1308
+ const varNames = await this.rokuAdapter.getScopeVariables();
1309
+ // Fetch each variable individually
1310
+ for (const varName of varNames) {
1311
+ let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: varName, frameId: -1 }, util_1.util.getVariablePath(varName));
1312
+ let result = await this.rokuAdapter.getVariable(evalArgs.expression, -1);
1313
+ let tempLocalsVar = await this.getVariableFromResult(result, -1);
1314
+ variables.push(tempLocalsVar);
1315
+ }
1316
+ tempVar = {
1317
+ ...v,
1318
+ childVariables: variables,
1319
+ namedVariables: variables.length,
1320
+ indexedVariables: 0
1321
+ };
1322
+ }
1323
+ // Merge the resulting updates together onto the original variable
1324
+ v.childVariables = tempVar.childVariables;
1325
+ v.namedVariables = tempVar.namedVariables;
1326
+ v.indexedVariables = tempVar.indexedVariables;
1327
+ }
1328
+ else if (v.type === '$$Registry') {
1329
+ // This is a special scope variable used to load registry data via an ECP call
1330
+ // Send the registry ECP call for the `dev` app as side loaded apps are always `dev`
1331
+ await (0, ecpRegistryUtils_1.populateVariableFromRegistryEcp)({ host: this.launchConfiguration.host, remotePort: this.launchConfiguration.remotePort, appId: 'dev' }, v, this.variables, this.getEvaluateRefId.bind(this));
1332
+ }
1333
+ }
1334
+ catch (error) {
1335
+ logging_1.logger.error(`Error getting variables for scope ${v.type}`, error);
1336
+ tempVar = {
1337
+ name: '',
1338
+ value: `❌ Error: ${error.message}`,
1339
+ variablesReference: 0,
1340
+ childVariables: []
1341
+ };
1342
+ v.childVariables = [tempVar];
1343
+ v.namedVariables = 1;
1344
+ v.indexedVariables = 0;
1345
+ }
1346
+ // Mark the scope as resolved so we don't re-fetch the variables
1347
+ v.isResolved = true;
1348
+ // If the scope has no children, add a single child to indicate there are no values
1349
+ if (v.childVariables.length === 0) {
1350
+ tempVar = {
1351
+ name: '',
1352
+ value: `No values for scope '${v.name}'`,
1353
+ variablesReference: 0,
1354
+ childVariables: []
1355
+ };
1356
+ v.childVariables = [tempVar];
1357
+ v.namedVariables = 1;
1358
+ v.indexedVariables = 0;
1359
+ }
1360
+ }
1313
1361
  getNextVarIndex(frameId) {
1314
1362
  if (!this.evaluateVarIndexByFrameId.has(frameId)) {
1315
1363
  this.evaluateVarIndexByFrameId.set(frameId, 0);
@@ -1323,7 +1371,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1323
1371
  //ensure the rokuAdapter is loaded
1324
1372
  await this.getRokuAdapter();
1325
1373
  let deferred = (0, util_1.defer)();
1326
- if (args.context === 'repl' && !this.enableDebugProtocol && args.expression.trim().startsWith('>')) {
1374
+ if (args.context === 'repl' && this.rokuAdapter.isTelnetAdapter() && args.expression.trim().startsWith('>')) {
1327
1375
  this.clearState();
1328
1376
  this.rokuAdapter.clearCache();
1329
1377
  const expression = args.expression.replace(/^\s*>\s*/, '');
@@ -1893,7 +1941,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1893
1941
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1894
1942
  let v;
1895
1943
  if (result) {
1896
- if (this.enableDebugProtocol) {
1944
+ if (this.rokuAdapter.isDebugProtocolAdapter()) {
1897
1945
  let refId = this.getEvaluateRefId(result.evaluateName, frameId);
1898
1946
  if (result.isCustom && !((_a = result.presentationHint) === null || _a === void 0 ? void 0 : _a.lazy) && result.evaluateNow) {
1899
1947
  try {
@@ -1953,7 +2001,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1953
2001
  }
1954
2002
  this.variables[refId] = v;
1955
2003
  }
1956
- else {
2004
+ else if (this.rokuAdapter.isTelnetAdapter()) {
1957
2005
  if (result.highLevelType === 'primative' || result.highLevelType === 'uninitialized') {
1958
2006
  v = new debugadapter_1.Variable(result.name, `${result.value}`);
1959
2007
  }