roku-debug 0.21.16 → 0.21.17

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.
Files changed (260) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/LaunchConfiguration.d.ts +22 -0
  3. package/dist/adapters/DebugProtocolAdapter.d.ts +12 -4
  4. package/dist/adapters/DebugProtocolAdapter.js +47 -6
  5. package/dist/adapters/DebugProtocolAdapter.js.map +1 -1
  6. package/dist/adapters/TelnetAdapter.d.ts +2 -13
  7. package/dist/adapters/TelnetAdapter.js +13 -10
  8. package/dist/adapters/TelnetAdapter.js.map +1 -1
  9. package/dist/adapters/customVariableUtils.d.ts +4 -0
  10. package/dist/adapters/customVariableUtils.js +398 -26
  11. package/dist/adapters/customVariableUtils.js.map +1 -1
  12. package/dist/adapters/customVariables/ifAppInfo.d.ts +2 -0
  13. package/dist/adapters/customVariables/ifAppInfo.js +50 -0
  14. package/dist/adapters/customVariables/ifAppInfo.js.map +1 -0
  15. package/dist/adapters/customVariables/ifAppManager.d.ts +2 -0
  16. package/dist/adapters/customVariables/ifAppManager.js +34 -0
  17. package/dist/adapters/customVariables/ifAppManager.js.map +1 -0
  18. package/dist/adapters/customVariables/ifAppMemoryMonitor.d.ts +2 -0
  19. package/dist/adapters/customVariables/ifAppMemoryMonitor.js +34 -0
  20. package/dist/adapters/customVariables/ifAppMemoryMonitor.js.map +1 -0
  21. package/dist/adapters/customVariables/ifArray.d.ts +2 -0
  22. package/dist/adapters/customVariables/ifArray.js +18 -0
  23. package/dist/adapters/customVariables/ifArray.js.map +1 -0
  24. package/dist/adapters/customVariables/ifAudioMetadata.d.ts +2 -0
  25. package/dist/adapters/customVariables/ifAudioMetadata.js +33 -0
  26. package/dist/adapters/customVariables/ifAudioMetadata.js.map +1 -0
  27. package/dist/adapters/customVariables/ifAudioResource.d.ts +2 -0
  28. package/dist/adapters/customVariables/ifAudioResource.js +34 -0
  29. package/dist/adapters/customVariables/ifAudioResource.js.map +1 -0
  30. package/dist/adapters/customVariables/ifByteArray.d.ts +2 -0
  31. package/dist/adapters/customVariables/ifByteArray.js +50 -0
  32. package/dist/adapters/customVariables/ifByteArray.js.map +1 -0
  33. package/dist/adapters/customVariables/ifCECStatus.d.ts +2 -0
  34. package/dist/adapters/customVariables/ifCECStatus.js +18 -0
  35. package/dist/adapters/customVariables/ifCECStatus.js.map +1 -0
  36. package/dist/adapters/customVariables/ifChannelStore.d.ts +2 -0
  37. package/dist/adapters/customVariables/ifChannelStore.js +34 -0
  38. package/dist/adapters/customVariables/ifChannelStore.js.map +1 -0
  39. package/dist/adapters/customVariables/ifDateTime.d.ts +2 -0
  40. package/dist/adapters/customVariables/ifDateTime.js +146 -0
  41. package/dist/adapters/customVariables/ifDateTime.js.map +1 -0
  42. package/dist/adapters/customVariables/ifDeviceInfo.d.ts +2 -0
  43. package/dist/adapters/customVariables/ifDeviceInfo.js +346 -0
  44. package/dist/adapters/customVariables/ifDeviceInfo.js.map +1 -0
  45. package/dist/adapters/customVariables/ifDraw2d.d.ts +2 -0
  46. package/dist/adapters/customVariables/ifDraw2d.js +34 -0
  47. package/dist/adapters/customVariables/ifDraw2d.js.map +1 -0
  48. package/dist/adapters/customVariables/ifEnum.d.ts +2 -0
  49. package/dist/adapters/customVariables/ifEnum.js +26 -0
  50. package/dist/adapters/customVariables/ifEnum.js.map +1 -0
  51. package/dist/adapters/customVariables/ifFileSystem.d.ts +2 -0
  52. package/dist/adapters/customVariables/ifFileSystem.js +18 -0
  53. package/dist/adapters/customVariables/ifFileSystem.js.map +1 -0
  54. package/dist/adapters/customVariables/ifFont.d.ts +2 -0
  55. package/dist/adapters/customVariables/ifFont.js +42 -0
  56. package/dist/adapters/customVariables/ifFont.js.map +1 -0
  57. package/dist/adapters/customVariables/ifFontRegistry.d.ts +2 -0
  58. package/dist/adapters/customVariables/ifFontRegistry.js +34 -0
  59. package/dist/adapters/customVariables/ifFontRegistry.js.map +1 -0
  60. package/dist/adapters/customVariables/ifGetMessagePort.d.ts +2 -0
  61. package/dist/adapters/customVariables/ifGetMessagePort.js +17 -0
  62. package/dist/adapters/customVariables/ifGetMessagePort.js.map +1 -0
  63. package/dist/adapters/customVariables/ifHdmiStatus.d.ts +2 -0
  64. package/dist/adapters/customVariables/ifHdmiStatus.js +42 -0
  65. package/dist/adapters/customVariables/ifHdmiStatus.js.map +1 -0
  66. package/dist/adapters/customVariables/ifHttpAgent.d.ts +2 -0
  67. package/dist/adapters/customVariables/ifHttpAgent.js +8 -0
  68. package/dist/adapters/customVariables/ifHttpAgent.js.map +1 -0
  69. package/dist/adapters/customVariables/ifImageMetadata.d.ts +2 -0
  70. package/dist/adapters/customVariables/ifImageMetadata.js +34 -0
  71. package/dist/adapters/customVariables/ifImageMetadata.js.map +1 -0
  72. package/dist/adapters/customVariables/ifInput.d.ts +2 -0
  73. package/dist/adapters/customVariables/ifInput.js +18 -0
  74. package/dist/adapters/customVariables/ifInput.js.map +1 -0
  75. package/dist/adapters/customVariables/ifList.d.ts +2 -0
  76. package/dist/adapters/customVariables/ifList.js +34 -0
  77. package/dist/adapters/customVariables/ifList.js.map +1 -0
  78. package/dist/adapters/customVariables/ifListToArray.d.ts +2 -0
  79. package/dist/adapters/customVariables/ifListToArray.js +18 -0
  80. package/dist/adapters/customVariables/ifListToArray.js.map +1 -0
  81. package/dist/adapters/customVariables/ifMessagePort.d.ts +2 -0
  82. package/dist/adapters/customVariables/ifMessagePort.js +18 -0
  83. package/dist/adapters/customVariables/ifMessagePort.js.map +1 -0
  84. package/dist/adapters/customVariables/ifMicrophone.d.ts +2 -0
  85. package/dist/adapters/customVariables/ifMicrophone.js +18 -0
  86. package/dist/adapters/customVariables/ifMicrophone.js.map +1 -0
  87. package/dist/adapters/customVariables/ifPath.d.ts +2 -0
  88. package/dist/adapters/customVariables/ifPath.js +26 -0
  89. package/dist/adapters/customVariables/ifPath.js.map +1 -0
  90. package/dist/adapters/customVariables/ifProgramGuide.d.ts +2 -0
  91. package/dist/adapters/customVariables/ifProgramGuide.js +18 -0
  92. package/dist/adapters/customVariables/ifProgramGuide.js.map +1 -0
  93. package/dist/adapters/customVariables/ifRegion.d.ts +2 -0
  94. package/dist/adapters/customVariables/ifRegion.js +98 -0
  95. package/dist/adapters/customVariables/ifRegion.js.map +1 -0
  96. package/dist/adapters/customVariables/ifRegistry.d.ts +2 -0
  97. package/dist/adapters/customVariables/ifRegistry.js +26 -0
  98. package/dist/adapters/customVariables/ifRegistry.js.map +1 -0
  99. package/dist/adapters/customVariables/ifRegistrySection.d.ts +2 -0
  100. package/dist/adapters/customVariables/ifRegistrySection.js +18 -0
  101. package/dist/adapters/customVariables/ifRegistrySection.js.map +1 -0
  102. package/dist/adapters/customVariables/ifSGNodeBoundingRect.d.ts +2 -0
  103. package/dist/adapters/customVariables/ifSGNodeBoundingRect.js +34 -0
  104. package/dist/adapters/customVariables/ifSGNodeBoundingRect.js.map +1 -0
  105. package/dist/adapters/customVariables/ifSGNodeChildren.d.ts +2 -0
  106. package/dist/adapters/customVariables/ifSGNodeChildren.js +74 -0
  107. package/dist/adapters/customVariables/ifSGNodeChildren.js.map +1 -0
  108. package/dist/adapters/customVariables/ifSGNodeDict.d.ts +2 -0
  109. package/dist/adapters/customVariables/ifSGNodeDict.js +18 -0
  110. package/dist/adapters/customVariables/ifSGNodeDict.js.map +1 -0
  111. package/dist/adapters/customVariables/ifSGNodeField.d.ts +2 -0
  112. package/dist/adapters/customVariables/ifSGNodeField.js +26 -0
  113. package/dist/adapters/customVariables/ifSGNodeField.js.map +1 -0
  114. package/dist/adapters/customVariables/ifSGNodeFocus.d.ts +2 -0
  115. package/dist/adapters/customVariables/ifSGNodeFocus.js +26 -0
  116. package/dist/adapters/customVariables/ifSGNodeFocus.js.map +1 -0
  117. package/dist/adapters/customVariables/ifSGNodeHttpAgentAccess.d.ts +2 -0
  118. package/dist/adapters/customVariables/ifSGNodeHttpAgentAccess.js +17 -0
  119. package/dist/adapters/customVariables/ifSGNodeHttpAgentAccess.js.map +1 -0
  120. package/dist/adapters/customVariables/ifSGScreen.d.ts +2 -0
  121. package/dist/adapters/customVariables/ifSGScreen.js +34 -0
  122. package/dist/adapters/customVariables/ifSGScreen.js.map +1 -0
  123. package/dist/adapters/customVariables/ifSocket.d.ts +2 -0
  124. package/dist/adapters/customVariables/ifSocket.js +58 -0
  125. package/dist/adapters/customVariables/ifSocket.js.map +1 -0
  126. package/dist/adapters/customVariables/ifSocketAddress.d.ts +2 -0
  127. package/dist/adapters/customVariables/ifSocketAddress.js +42 -0
  128. package/dist/adapters/customVariables/ifSocketAddress.js.map +1 -0
  129. package/dist/adapters/customVariables/ifSocketAsync.d.ts +2 -0
  130. package/dist/adapters/customVariables/ifSocketAsync.js +42 -0
  131. package/dist/adapters/customVariables/ifSocketAsync.js.map +1 -0
  132. package/dist/adapters/customVariables/ifSocketCastOption.d.ts +2 -0
  133. package/dist/adapters/customVariables/ifSocketCastOption.js +42 -0
  134. package/dist/adapters/customVariables/ifSocketCastOption.js.map +1 -0
  135. package/dist/adapters/customVariables/ifSocketConnection.d.ts +2 -0
  136. package/dist/adapters/customVariables/ifSocketConnection.js +26 -0
  137. package/dist/adapters/customVariables/ifSocketConnection.js.map +1 -0
  138. package/dist/adapters/customVariables/ifSocketConnectionOption.d.ts +2 -0
  139. package/dist/adapters/customVariables/ifSocketConnectionOption.js +42 -0
  140. package/dist/adapters/customVariables/ifSocketConnectionOption.js.map +1 -0
  141. package/dist/adapters/customVariables/ifSocketConnectionStatus.d.ts +2 -0
  142. package/dist/adapters/customVariables/ifSocketConnectionStatus.js +50 -0
  143. package/dist/adapters/customVariables/ifSocketConnectionStatus.js.map +1 -0
  144. package/dist/adapters/customVariables/ifSocketOption.d.ts +2 -0
  145. package/dist/adapters/customVariables/ifSocketOption.js +66 -0
  146. package/dist/adapters/customVariables/ifSocketOption.js.map +1 -0
  147. package/dist/adapters/customVariables/ifSocketStatus.d.ts +2 -0
  148. package/dist/adapters/customVariables/ifSocketStatus.js +90 -0
  149. package/dist/adapters/customVariables/ifSocketStatus.js.map +1 -0
  150. package/dist/adapters/customVariables/ifSourceIdentity.d.ts +2 -0
  151. package/dist/adapters/customVariables/ifSourceIdentity.js +18 -0
  152. package/dist/adapters/customVariables/ifSourceIdentity.js.map +1 -0
  153. package/dist/adapters/customVariables/ifSprite.d.ts +2 -0
  154. package/dist/adapters/customVariables/ifSprite.js +90 -0
  155. package/dist/adapters/customVariables/ifSprite.js.map +1 -0
  156. package/dist/adapters/customVariables/ifString.d.ts +2 -0
  157. package/dist/adapters/customVariables/ifString.js +26 -0
  158. package/dist/adapters/customVariables/ifString.js.map +1 -0
  159. package/dist/adapters/customVariables/ifStringOps.d.ts +2 -0
  160. package/dist/adapters/customVariables/ifStringOps.js +98 -0
  161. package/dist/adapters/customVariables/ifStringOps.js.map +1 -0
  162. package/dist/adapters/customVariables/ifTextToSpeech.d.ts +2 -0
  163. package/dist/adapters/customVariables/ifTextToSpeech.js +74 -0
  164. package/dist/adapters/customVariables/ifTextToSpeech.js.map +1 -0
  165. package/dist/adapters/customVariables/ifTextureRequest.d.ts +2 -0
  166. package/dist/adapters/customVariables/ifTextureRequest.js +26 -0
  167. package/dist/adapters/customVariables/ifTextureRequest.js.map +1 -0
  168. package/dist/adapters/customVariables/ifTimeSpan.d.ts +2 -0
  169. package/dist/adapters/customVariables/ifTimeSpan.js +34 -0
  170. package/dist/adapters/customVariables/ifTimeSpan.js.map +1 -0
  171. package/dist/adapters/customVariables/ifToStr.d.ts +2 -0
  172. package/dist/adapters/customVariables/ifToStr.js +18 -0
  173. package/dist/adapters/customVariables/ifToStr.js.map +1 -0
  174. package/dist/adapters/customVariables/ifUrlTransfer.d.ts +2 -0
  175. package/dist/adapters/customVariables/ifUrlTransfer.js +50 -0
  176. package/dist/adapters/customVariables/ifUrlTransfer.js.map +1 -0
  177. package/dist/adapters/customVariables/ifVideoPlayer.d.ts +2 -0
  178. package/dist/adapters/customVariables/ifVideoPlayer.js +34 -0
  179. package/dist/adapters/customVariables/ifVideoPlayer.js.map +1 -0
  180. package/dist/adapters/customVariables/ifXMLElement.d.ts +2 -0
  181. package/dist/adapters/customVariables/ifXMLElement.js +58 -0
  182. package/dist/adapters/customVariables/ifXMLElement.js.map +1 -0
  183. package/dist/adapters/customVariables/ifXMLList.d.ts +2 -0
  184. package/dist/adapters/customVariables/ifXMLList.js +34 -0
  185. package/dist/adapters/customVariables/ifXMLList.js.map +1 -0
  186. package/dist/adapters/customVariables/index.d.ts +78 -0
  187. package/dist/adapters/customVariables/index.js +159 -0
  188. package/dist/adapters/customVariables/index.js.map +1 -0
  189. package/dist/adapters/customVariables/roAppMemoryNotificationEvent.d.ts +2 -0
  190. package/dist/adapters/customVariables/roAppMemoryNotificationEvent.js +18 -0
  191. package/dist/adapters/customVariables/roAppMemoryNotificationEvent.js.map +1 -0
  192. package/dist/adapters/customVariables/roAudioPlayerEvent.d.ts +2 -0
  193. package/dist/adapters/customVariables/roAudioPlayerEvent.js +138 -0
  194. package/dist/adapters/customVariables/roAudioPlayerEvent.js.map +1 -0
  195. package/dist/adapters/customVariables/roCECStatusEvent.d.ts +2 -0
  196. package/dist/adapters/customVariables/roCECStatusEvent.js +34 -0
  197. package/dist/adapters/customVariables/roCECStatusEvent.js.map +1 -0
  198. package/dist/adapters/customVariables/roChannelStoreEvent.d.ts +2 -0
  199. package/dist/adapters/customVariables/roChannelStoreEvent.js +58 -0
  200. package/dist/adapters/customVariables/roChannelStoreEvent.js.map +1 -0
  201. package/dist/adapters/customVariables/roDeviceInfoEvent.d.ts +2 -0
  202. package/dist/adapters/customVariables/roDeviceInfoEvent.js +34 -0
  203. package/dist/adapters/customVariables/roDeviceInfoEvent.js.map +1 -0
  204. package/dist/adapters/customVariables/roFileSystemEvent.d.ts +2 -0
  205. package/dist/adapters/customVariables/roFileSystemEvent.js +34 -0
  206. package/dist/adapters/customVariables/roFileSystemEvent.js.map +1 -0
  207. package/dist/adapters/customVariables/roHdmiStatusEvent.d.ts +2 -0
  208. package/dist/adapters/customVariables/roHdmiStatusEvent.js +42 -0
  209. package/dist/adapters/customVariables/roHdmiStatusEvent.js.map +1 -0
  210. package/dist/adapters/customVariables/roInputEvent.d.ts +2 -0
  211. package/dist/adapters/customVariables/roInputEvent.js +26 -0
  212. package/dist/adapters/customVariables/roInputEvent.js.map +1 -0
  213. package/dist/adapters/customVariables/roMicrophoneEvent.d.ts +2 -0
  214. package/dist/adapters/customVariables/roMicrophoneEvent.js +34 -0
  215. package/dist/adapters/customVariables/roMicrophoneEvent.js.map +1 -0
  216. package/dist/adapters/customVariables/roSGNodeEvent.d.ts +2 -0
  217. package/dist/adapters/customVariables/roSGNodeEvent.js +50 -0
  218. package/dist/adapters/customVariables/roSGNodeEvent.js.map +1 -0
  219. package/dist/adapters/customVariables/roSGScreenEvent.d.ts +2 -0
  220. package/dist/adapters/customVariables/roSGScreenEvent.js +18 -0
  221. package/dist/adapters/customVariables/roSGScreenEvent.js.map +1 -0
  222. package/dist/adapters/customVariables/roSocketEvent.d.ts +2 -0
  223. package/dist/adapters/customVariables/roSocketEvent.js +18 -0
  224. package/dist/adapters/customVariables/roSocketEvent.js.map +1 -0
  225. package/dist/adapters/customVariables/roSystemLogEvent.d.ts +2 -0
  226. package/dist/adapters/customVariables/roSystemLogEvent.js +18 -0
  227. package/dist/adapters/customVariables/roSystemLogEvent.js.map +1 -0
  228. package/dist/adapters/customVariables/roTextToSpeechEvent.d.ts +2 -0
  229. package/dist/adapters/customVariables/roTextToSpeechEvent.js +34 -0
  230. package/dist/adapters/customVariables/roTextToSpeechEvent.js.map +1 -0
  231. package/dist/adapters/customVariables/roTextureRequestEvent.d.ts +2 -0
  232. package/dist/adapters/customVariables/roTextureRequestEvent.js +42 -0
  233. package/dist/adapters/customVariables/roTextureRequestEvent.js.map +1 -0
  234. package/dist/adapters/customVariables/roUniversalControlEvent.d.ts +2 -0
  235. package/dist/adapters/customVariables/roUniversalControlEvent.js +58 -0
  236. package/dist/adapters/customVariables/roUniversalControlEvent.js.map +1 -0
  237. package/dist/adapters/customVariables/roUrlEvent.d.ts +2 -0
  238. package/dist/adapters/customVariables/roUrlEvent.js +66 -0
  239. package/dist/adapters/customVariables/roUrlEvent.js.map +1 -0
  240. package/dist/adapters/customVariables/roVideoPlayerEvent.d.ts +2 -0
  241. package/dist/adapters/customVariables/roVideoPlayerEvent.js +154 -0
  242. package/dist/adapters/customVariables/roVideoPlayerEvent.js.map +1 -0
  243. package/dist/adapters/customVariables/utils.d.ts +6 -0
  244. package/dist/adapters/customVariables/utils.js +32 -0
  245. package/dist/adapters/customVariables/utils.js.map +1 -0
  246. package/dist/debugSession/BrightScriptDebugSession.d.ts +28 -0
  247. package/dist/debugSession/BrightScriptDebugSession.js +413 -75
  248. package/dist/debugSession/BrightScriptDebugSession.js.map +1 -1
  249. package/dist/interfaces.d.ts +1 -0
  250. package/dist/managers/ProjectManager.d.ts +2 -1
  251. package/dist/managers/ProjectManager.js +4 -3
  252. package/dist/managers/ProjectManager.js.map +1 -1
  253. package/dist/managers/SourceMapManager.d.ts +3 -0
  254. package/dist/managers/SourceMapManager.js +46 -29
  255. package/dist/managers/SourceMapManager.js.map +1 -1
  256. package/dist/util.js +1 -2
  257. package/dist/util.js.map +1 -1
  258. package/package.json +1 -1
  259. package/roku-debug-0.21.17.tgz +0 -0
  260. package/roku-debug-0.21.16.tgz +0 -0
@@ -22,11 +22,13 @@ const BreakpointManager_1 = require("../managers/BreakpointManager");
22
22
  const logging_1 = require("../logging");
23
23
  const VariablesResponse_1 = require("../debugProtocol/events/responses/VariablesResponse");
24
24
  const brighterscript_1 = require("brighterscript");
25
+ const debounce_1 = require("debounce");
25
26
  const diagnosticSource = 'roku-debug';
26
27
  class BrightScriptDebugSession extends debugadapter_1.DebugSession {
27
28
  constructor() {
28
29
  super();
29
30
  this.logger = logging_1.logger.createLogger(`[session]`);
31
+ this.isWindowsPlatform = process.platform.startsWith('win');
30
32
  /**
31
33
  * A sequence used to help identify log statements for requests
32
34
  */
@@ -49,6 +51,10 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
49
51
  */
50
52
  this.COMPILE_ERROR_THREAD_ID = 7777;
51
53
  this.exceptionBreakpoints = [];
54
+ this.pendingSendLogPromise = Promise.resolve();
55
+ this.debounceSendInvalidatedEvent = (0, debounce_1.debounce)((threadId, frameId) => {
56
+ this.sendInvalidatedEvent(threadId, frameId);
57
+ }, 50);
52
58
  this.evaluateRequestPromise = Promise.resolve();
53
59
  this.evaluateVarIndexByFrameId = new Map();
54
60
  /**
@@ -239,7 +245,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
239
245
  * @returns
240
246
  */
241
247
  normalizeLaunchConfig(config) {
242
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
248
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
243
249
  (_a = config.cwd) !== null && _a !== void 0 ? _a : (config.cwd = process.cwd());
244
250
  (_b = config.outDir) !== null && _b !== void 0 ? _b : (config.outDir = (0, FileUtils_1.standardizePath) `${config.cwd}/out`);
245
251
  (_c = config.stagingDir) !== null && _c !== void 0 ? _c : (config.stagingDir = (0, FileUtils_1.standardizePath) `${config.outDir}/.roku-deploy-staging`);
@@ -251,6 +257,8 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
251
257
  (_j = config.brightScriptConsolePort) !== null && _j !== void 0 ? _j : (config.brightScriptConsolePort = 8085);
252
258
  (_k = config.stagingDir) !== null && _k !== void 0 ? _k : (config.stagingDir = config.stagingFolderPath);
253
259
  (_l = config.emitChannelPublishedEvent) !== null && _l !== void 0 ? _l : (config.emitChannelPublishedEvent = true);
260
+ (_m = config.rewriteDevicePathsInLogs) !== null && _m !== void 0 ? _m : (config.rewriteDevicePathsInLogs = true);
261
+ (_o = config.autoResolveVirtualVariables) !== null && _o !== void 0 ? _o : (config.autoResolveVirtualVariables = false);
254
262
  return config;
255
263
  }
256
264
  async launchRequest(response, config) {
@@ -312,12 +320,12 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
312
320
  //pass along the console output
313
321
  if (this.launchConfiguration.consoleOutput === 'full') {
314
322
  this.rokuAdapter.on('console-output', (data) => {
315
- this.sendLogOutput(data);
323
+ void this.sendLogOutput(data);
316
324
  });
317
325
  }
318
326
  else {
319
327
  this.rokuAdapter.on('unhandled-console-output', (data) => {
320
- this.sendLogOutput(data);
328
+ void this.sendLogOutput(data);
321
329
  });
322
330
  }
323
331
  // Send chanperf events to the extension
@@ -543,15 +551,125 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
543
551
  */
544
552
  sendLogOutput(logOutput) {
545
553
  this.fileLoggingManager.writeRokuDeviceLog(logOutput);
546
- const lines = logOutput.split(/\r?\n/g);
547
- for (let i = 0; i < lines.length; i++) {
548
- let line = lines[i];
549
- if (i < lines.length - 1) {
550
- line += '\n';
554
+ this.pendingSendLogPromise = this.pendingSendLogPromise.then(async () => {
555
+ logOutput = await this.convertBacktracePaths(logOutput);
556
+ const lines = logOutput.split(/\r?\n/g);
557
+ for (let i = 0; i < lines.length; i++) {
558
+ let line = lines[i];
559
+ if (i < lines.length - 1) {
560
+ line += '\n';
561
+ }
562
+ if (this.launchConfiguration.rewriteDevicePathsInLogs) {
563
+ let potentialPaths = this.getPotentialPkgPaths(line);
564
+ for (let potentialPath of potentialPaths) {
565
+ let originalLocation = await this.projectManager.getSourceLocation(potentialPath.path, potentialPath.lineNumber, potentialPath.columnNumber);
566
+ if (originalLocation) {
567
+ let replacement;
568
+ replacement = originalLocation.filePath.replaceAll(' ', '%20');
569
+ if (replacement !== originalLocation.filePath) {
570
+ if (this.isWindowsPlatform) {
571
+ replacement = `vscode://file/${replacement}`;
572
+ }
573
+ else {
574
+ replacement = `file://${replacement}`;
575
+ }
576
+ }
577
+ replacement += `:${originalLocation.lineNumber}`;
578
+ if (potentialPath.columnNumber !== undefined) {
579
+ replacement += `:${originalLocation.columnIndex + 1}`;
580
+ }
581
+ line = line.replaceAll(potentialPath.fullMatch, replacement);
582
+ }
583
+ }
584
+ }
585
+ this.sendEvent(new debugadapter_1.OutputEvent(line, 'stdout'));
586
+ this.sendEvent(new Events_1.LogOutputEvent(line));
587
+ }
588
+ });
589
+ return this.pendingSendLogPromise;
590
+ }
591
+ /**
592
+ * Extracts potential package paths from a given line of text.
593
+ *
594
+ * This method uses a regular expression to find matches in the provided line
595
+ * and returns an array of objects containing details about each match.
596
+ *
597
+ * @param input - The line of text to search for potential package paths.
598
+ * @returns An array of objects, each containing:
599
+ * - `fullMatch`: The full matched string.
600
+ * - `path`: The extracted path from the match.
601
+ * - `lineNumber`: The line number extracted from the match.
602
+ * - `columnNumber`: The column number extracted from the match, or `undefined` if not found.
603
+ */
604
+ getPotentialPkgPaths(input) {
605
+ var _a, _b;
606
+ // https://regex101.com/r/ixpQiq/1
607
+ let matches = input.matchAll(/((?:\.\.\.|[A-Za-z_0-9]*pkg\:\/)[A-Za-z_0-9 \/\.]+\.[A-Za-z_0-9 \/]+)(?:(?:\:)(\d+)(?:\:(\d+))?|\((\d+)(?:\:(\d+))?\))/ig);
608
+ let paths = [];
609
+ if (matches) {
610
+ for (let match of matches) {
611
+ let fullMatch = match[0];
612
+ let path = match[1];
613
+ let lineNumber = parseInt((_a = match[2]) !== null && _a !== void 0 ? _a : match[4]);
614
+ let columnNumber = parseInt((_b = match[3]) !== null && _b !== void 0 ? _b : match[5]);
615
+ if (isNaN(columnNumber)) {
616
+ columnNumber = undefined;
617
+ }
618
+ paths.push({
619
+ fullMatch: fullMatch,
620
+ path: path,
621
+ lineNumber: lineNumber,
622
+ columnNumber: columnNumber
623
+ });
624
+ }
625
+ }
626
+ return paths;
627
+ }
628
+ /**
629
+ * Converts the filename property in backtrace objects in the given input string to source paths if found
630
+ */
631
+ async convertBacktracePaths(input) {
632
+ if (!this.launchConfiguration.rewriteDevicePathsInLogs) {
633
+ return input;
634
+ }
635
+ // Why does this not work? It should work, but it doesn't. I'm not sure why.
636
+ // let matches = input.matchAll(this.deviceBacktraceObjectRegex);
637
+ // https://regex101.com/r/y1koaV/2
638
+ let deviceBacktraceObjectRegex = /{\s+filename:\s+"([A-Za-z0-9_\.\/\: ]+)"\s+function\:\s+".+"\s+(line_number\:\s+(\d+))\s+}/gi;
639
+ let matches = [];
640
+ let match = deviceBacktraceObjectRegex.exec(input);
641
+ while (match) {
642
+ matches.push(match);
643
+ match = deviceBacktraceObjectRegex.exec(input);
644
+ }
645
+ if (matches) {
646
+ for (let match of matches) {
647
+ let fullMatch = match[0];
648
+ let filePath = match[1];
649
+ let fullLineNumber = match[2];
650
+ let lineNumber = parseInt(match[3]);
651
+ let originalLocation = await this.projectManager.getSourceLocation(filePath, lineNumber);
652
+ if (originalLocation) {
653
+ let fileReplacement;
654
+ fileReplacement = originalLocation.filePath.replaceAll(' ', '%20');
655
+ if (fileReplacement !== originalLocation.filePath) {
656
+ if (this.isWindowsPlatform) {
657
+ fileReplacement = `vscode://file/${fileReplacement}`;
658
+ }
659
+ else {
660
+ fileReplacement = `file://${fileReplacement}`;
661
+ }
662
+ }
663
+ fileReplacement += `:${originalLocation.lineNumber}`;
664
+ let lineNumberReplacement = fullLineNumber.replace(lineNumber.toString(), originalLocation.lineNumber.toString());
665
+ // replace the full backtrace object with the an updated version so we don't modify other parts of the log output that might contain the same file path
666
+ let completeReplacement = fullMatch.replace(filePath, fileReplacement);
667
+ completeReplacement = completeReplacement.replace(fullLineNumber, lineNumberReplacement);
668
+ input = input.replaceAll(fullMatch, completeReplacement);
669
+ }
551
670
  }
552
- this.sendEvent(new debugadapter_1.OutputEvent(line, 'stdout'));
553
- this.sendEvent(new Events_1.LogOutputEvent(line));
554
671
  }
672
+ return input;
555
673
  }
556
674
  async runAutomaticSceneGraphCommands(commands) {
557
675
  if (commands) {
@@ -855,7 +973,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
855
973
  if (!result) {
856
974
  throw new Error(`Could not get scopes`);
857
975
  }
858
- v = this.getVariableFromResult(result, args.frameId);
976
+ v = await this.getVariableFromResult(result, args.frameId);
859
977
  //TODO - testing something, remove later
860
978
  // eslint-disable-next-line camelcase
861
979
  v.request_seq = response.request_seq;
@@ -969,13 +1087,15 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
969
1087
  this.logger.info('[stepBackRequest] end');
970
1088
  }
971
1089
  async variablesRequest(response, args) {
972
- var _a, _b;
1090
+ var _a, _b, _c, _d;
973
1091
  const logger = this.logger.createLogger('[variablesRequest]');
1092
+ let sendInvalidatedEvent = false;
1093
+ let frameId = null;
974
1094
  try {
975
1095
  logger.log('begin', { args });
976
1096
  //ensure the rokuAdapter is loaded
977
1097
  await this.getRokuAdapter();
978
- let childVariables = [];
1098
+ let updatedVariables = [];
979
1099
  //wait for any `evaluate` commands to finish so we have a higher likely hood of being at a debugger prompt
980
1100
  await this.evaluateRequestPromise;
981
1101
  if (((_a = this.rokuAdapter) === null || _a === void 0 ? void 0 : _a.isAtDebuggerPrompt) !== true) {
@@ -993,13 +1113,15 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
993
1113
  for (const varName of vars) {
994
1114
  let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: varName, frameId: -1 }, util_1.util.getVariablePath(varName));
995
1115
  let result = await this.rokuAdapter.getVariable(evalArgs.expression, -1);
996
- let tempVar = this.getVariableFromResult(result, -1);
997
- childVariables.push(tempVar);
1116
+ let tempVar = await this.getVariableFromResult(result, -1);
1117
+ updatedVariables.push(tempVar);
998
1118
  }
999
1119
  }
1000
1120
  else {
1001
- childVariables.push(new debugadapter_1.Variable('variables disabled by launch.json setting', 'enableVariablesPanel: false'));
1121
+ updatedVariables.push(new debugadapter_1.Variable('variables disabled by launch.json setting', 'enableVariablesPanel: false'));
1002
1122
  }
1123
+ this.variables[args.variablesReference] = new debugadapter_1.Variable('', '', args.variablesReference, 0, updatedVariables.length);
1124
+ this.variables[args.variablesReference].childVariables = updatedVariables;
1003
1125
  }
1004
1126
  else {
1005
1127
  //find the variable with this reference
@@ -1010,49 +1132,120 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1010
1132
  return this.sendResponse(response);
1011
1133
  }
1012
1134
  logger.log('variable', v);
1013
- //query for child vars if we haven't done it yet.
1014
- if (v.childVariables.length === 0) {
1015
- let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: v.evaluateName, frameId: v.frameId }, util_1.util.getVariablePath(v.evaluateName));
1016
- let result = await this.rokuAdapter.getVariable(evalArgs.expression, v.frameId);
1017
- let tempVar = this.getVariableFromResult(result, v.frameId);
1018
- tempVar.frameId = v.frameId;
1019
- v.childVariables = tempVar.childVariables;
1020
- }
1021
- childVariables = v.childVariables;
1022
- }
1023
- //if the variable is an array, send only the requested range
1024
- if (Array.isArray(childVariables) && args.filter === 'indexed') {
1025
- //only send the variable range requested by the debugger
1026
- childVariables = childVariables.slice(args.start, args.start + args.count);
1027
- }
1028
- let filteredChildVariables = this.launchConfiguration.showHiddenVariables !== true ? childVariables.filter((child) => !child.name.startsWith(this.tempVarPrefix)) : childVariables;
1029
- if (this.launchConfiguration.showHiddenVariables !== true) {
1030
- filteredChildVariables = filteredChildVariables.filter((child) => {
1031
- //A transient variable that we show when there is a value
1032
- if (child.name === '__brs_err__' && child.type !== VariablesResponse_1.VariableType.Uninitialized) {
1033
- return true;
1135
+ //query for child vars if we haven't done it yet or DAP is asking to resolve a lazy variable
1136
+ if (v.childVariables.length === 0 || v.isResolved) {
1137
+ let tempVar;
1138
+ if (!v.isResolved) {
1139
+ // Evaluate the variable
1140
+ try {
1141
+ let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: v.evaluateName, frameId: v.frameId }, util_1.util.getVariablePath(v.evaluateName));
1142
+ let result = await this.rokuAdapter.getVariable(evalArgs.expression, v.frameId);
1143
+ tempVar = await this.getVariableFromResult(result, v.frameId);
1144
+ tempVar.frameId = v.frameId;
1145
+ // Determine if the variable has changed
1146
+ sendInvalidatedEvent = v.type !== tempVar.type || v.indexedVariables !== tempVar.indexedVariables;
1147
+ }
1148
+ catch (error) {
1149
+ logger.error('Error getting variables', error);
1150
+ tempVar = new debugadapter_1.Variable('Error', `❌ Error: ${error.message}`);
1151
+ tempVar.type = '';
1152
+ tempVar.childVariables = [];
1153
+ sendInvalidatedEvent = true;
1154
+ response.success = false;
1155
+ response.message = error.message;
1156
+ }
1157
+ // Merge the resulting updates together
1158
+ v.childVariables = tempVar.childVariables;
1159
+ v.value = tempVar.value;
1160
+ v.type = tempVar.type;
1161
+ v.indexedVariables = tempVar.indexedVariables;
1162
+ v.namedVariables = tempVar.namedVariables;
1034
1163
  }
1035
- else if (util_1.util.isTransientVariable(child.name)) {
1036
- return false;
1164
+ frameId = v.frameId;
1165
+ if (((_b = v === null || v === void 0 ? void 0 : v.presentationHint) === null || _b === void 0 ? void 0 : _b.lazy) || v.isResolved) {
1166
+ // If this was a lazy variable we need to respond with the updated variable and not the children
1167
+ if (v.isResolved && v.childVariables.length > 0) {
1168
+ updatedVariables = v.childVariables;
1169
+ }
1170
+ else {
1171
+ updatedVariables = [v];
1172
+ }
1173
+ v.isResolved = true;
1037
1174
  }
1038
1175
  else {
1039
- return true;
1176
+ updatedVariables = v.childVariables;
1040
1177
  }
1041
- });
1178
+ // If the variable has no children, set the reference to 0
1179
+ // so it does not look expandable in the Ui
1180
+ if (v.childVariables.length === 0) {
1181
+ v.variablesReference = 0;
1182
+ }
1183
+ // If the variable was resolve in the past we may not have fetched a new temp var
1184
+ tempVar !== null && tempVar !== void 0 ? tempVar : (tempVar = v);
1185
+ if (v === null || v === void 0 ? void 0 : v.presentationHint) {
1186
+ v.presentationHint.lazy = (_c = tempVar.presentationHint) === null || _c === void 0 ? void 0 : _c.lazy;
1187
+ }
1188
+ else {
1189
+ v.presentationHint = tempVar.presentationHint;
1190
+ }
1191
+ }
1192
+ else {
1193
+ updatedVariables = v.childVariables;
1194
+ }
1042
1195
  }
1043
1196
  response.body = {
1044
- variables: filteredChildVariables
1197
+ variables: this.filterVariablesUpdates(updatedVariables, args, this.variables[args.variablesReference])
1045
1198
  };
1046
1199
  }
1047
1200
  catch (error) {
1048
1201
  logger.error('Error during variablesRequest', error, { args });
1049
1202
  response.success = false;
1050
- response.message = (_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : 'Error during variablesRequest';
1203
+ response.message = (_d = error === null || error === void 0 ? void 0 : error.message) !== null && _d !== void 0 ? _d : 'Error during variablesRequest';
1051
1204
  }
1052
1205
  finally {
1053
1206
  logger.info('end', { response });
1054
1207
  }
1055
1208
  this.sendResponse(response);
1209
+ if (sendInvalidatedEvent) {
1210
+ this.debounceSendInvalidatedEvent(null, frameId);
1211
+ }
1212
+ }
1213
+ filterVariablesUpdates(updatedVariables, args, v) {
1214
+ var _a;
1215
+ if (!updatedVariables || !v) {
1216
+ return [];
1217
+ }
1218
+ let start = (_a = args.start) !== null && _a !== void 0 ? _a : 0;
1219
+ //if the variable is an array, send only the requested range
1220
+ if (Array.isArray(updatedVariables) && args.filter === 'indexed') {
1221
+ //only send the variable range requested by the debugger
1222
+ if (!args.count) {
1223
+ updatedVariables = updatedVariables.slice(0, v.indexedVariables);
1224
+ }
1225
+ else {
1226
+ updatedVariables = updatedVariables.slice(start, start + args.count);
1227
+ }
1228
+ }
1229
+ if (Array.isArray(updatedVariables) && args.filter === 'named') {
1230
+ // We currently do not support named variable paging so we always send all named variables
1231
+ updatedVariables = updatedVariables.slice(v.indexedVariables);
1232
+ }
1233
+ let filteredUpdatedVariables = this.launchConfiguration.showHiddenVariables !== true ? updatedVariables.filter((child) => !child.name.startsWith(this.tempVarPrefix)) : updatedVariables;
1234
+ if (this.launchConfiguration.showHiddenVariables !== true) {
1235
+ filteredUpdatedVariables = filteredUpdatedVariables.filter((child) => {
1236
+ //A transient variable that we show when there is a value
1237
+ if (child.name === '__brs_err__' && child.type !== VariablesResponse_1.VariableType.Uninitialized) {
1238
+ return true;
1239
+ }
1240
+ else if (util_1.util.isTransientVariable(child.name)) {
1241
+ return false;
1242
+ }
1243
+ else {
1244
+ return true;
1245
+ }
1246
+ });
1247
+ }
1248
+ return filteredUpdatedVariables;
1056
1249
  }
1057
1250
  getNextVarIndex(frameId) {
1058
1251
  if (!this.evaluateVarIndexByFrameId.has(frameId)) {
@@ -1098,7 +1291,9 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1098
1291
  }
1099
1292
  //is at debugger prompt
1100
1293
  }
1101
- else {
1294
+ else if (args.expression.trim()) {
1295
+ // We trim and check that the expression is not an empty string so that we do not send empty expressions to the Roku
1296
+ // This happens mostly when hovering over leading whitespace in the editor
1102
1297
  let { evalArgs, variablePath } = await this.evaluateExpressionToTempVar(args, util_1.util.getVariablePath(args.expression));
1103
1298
  //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`
1104
1299
  if (variablePath) {
@@ -1113,7 +1308,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1113
1308
  if (!result) {
1114
1309
  throw new Error('Error: unable to evaluate expression');
1115
1310
  }
1116
- v = this.getVariableFromResult(result, evalArgs.frameId);
1311
+ v = await this.getVariableFromResult(result, evalArgs.frameId);
1117
1312
  //TODO - testing something, remove later
1118
1313
  // eslint-disable-next-line camelcase
1119
1314
  v.request_seq = response.request_seq;
@@ -1131,14 +1326,20 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1131
1326
  else {
1132
1327
  let commandResults = await this.rokuAdapter.evaluate(evalArgs.expression, evalArgs.frameId);
1133
1328
  commandResults.message = util_1.util.trimDebugPrompt(commandResults.message);
1134
- if (args.context !== 'watch') {
1135
- //clear variable cache since this action could have side-effects
1329
+ if (args.context === 'repl') {
1330
+ // Clear variable cache since this action could have side-effects
1331
+ // Only do this for REPL requests as hovers and watches should not clear the cache
1136
1332
  this.clearState();
1137
1333
  this.sendInvalidatedEvent(null, evalArgs.frameId);
1138
1334
  }
1139
- //if the adapter captured output (probably only telnet), print it to the vscode debug console
1335
+ // If the adapter captured output (probably only telnet), log the results
1140
1336
  if (typeof commandResults.message === 'string') {
1141
- this.sendEvent(new debugadapter_1.OutputEvent(commandResults.message, commandResults.type === 'error' ? 'stderr' : 'stdio'));
1337
+ this.logger.debug('evaluateRequest', { commandResults });
1338
+ if (args.context === 'repl') {
1339
+ // If the command was a repl command, send the output to the debug console for the developer as well
1340
+ // We limit this to repl only so you don't get extra logs when hovering over variables ro running watches
1341
+ this.sendEvent(new debugadapter_1.OutputEvent(commandResults.message, commandResults.type === 'error' ? 'stderr' : 'stdio'));
1342
+ }
1142
1343
  }
1143
1344
  if (this.enableDebugProtocol || (typeof commandResults.message !== 'string')) {
1144
1345
  response.body = {
@@ -1171,13 +1372,14 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1171
1372
  if (!variablePath && util_1.util.isAssignableExpression(args.expression)) {
1172
1373
  let varIndex = this.getNextVarIndex(args.frameId);
1173
1374
  let arrayVarName = this.tempVarPrefix + 'eval';
1375
+ let command = '';
1174
1376
  if (varIndex === 0) {
1175
- const response = await this.rokuAdapter.evaluate(`${arrayVarName} = []`, args.frameId);
1176
- console.log(response);
1377
+ command += `if type(${arrayVarName}) = "<uninitialized>" then ${arrayVarName} = []\n`;
1177
1378
  }
1178
1379
  let statement = `${arrayVarName}[${varIndex}] = ${args.expression}`;
1179
1380
  returnVal.evalArgs.expression = `${arrayVarName}[${varIndex}]`;
1180
- let commandResults = await this.rokuAdapter.evaluate(statement, args.frameId);
1381
+ command += statement;
1382
+ let commandResults = await this.rokuAdapter.evaluate(command, args.frameId);
1181
1383
  if (commandResults.type === 'error') {
1182
1384
  throw new Error(commandResults.message);
1183
1385
  }
@@ -1185,6 +1387,49 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1185
1387
  }
1186
1388
  return returnVal;
1187
1389
  }
1390
+ async bulkEvaluateExpressionToTempVar(frameId, argsArray, variablePathArray) {
1391
+ let results = {
1392
+ evaluations: [],
1393
+ bulkVarName: ''
1394
+ };
1395
+ let storedVariables = [];
1396
+ let command = '';
1397
+ for (let i = 0; i < argsArray.length; i++) {
1398
+ let args = argsArray[i];
1399
+ let variablePath = variablePathArray[i];
1400
+ let returnVal = { evalArgs: args, variablePath };
1401
+ if (!variablePath && util_1.util.isAssignableExpression(args.expression)) {
1402
+ let varIndex = this.getNextVarIndex(frameId);
1403
+ let arrayVarName = this.tempVarPrefix + 'eval';
1404
+ if (varIndex === 0) {
1405
+ command += `if type(${arrayVarName}) = "<uninitialized>" then ${arrayVarName} = []\n`;
1406
+ }
1407
+ let statement = `${arrayVarName}[${varIndex}] = ${args.expression}\n`;
1408
+ returnVal.evalArgs.expression = `${arrayVarName}[${varIndex}]`;
1409
+ command += statement;
1410
+ storedVariables.push(`${arrayVarName}[${varIndex}]`);
1411
+ returnVal.variablePath = [arrayVarName, varIndex.toString()];
1412
+ }
1413
+ results.evaluations[i] = returnVal;
1414
+ }
1415
+ if (command) {
1416
+ // create a bulk container for the command results
1417
+ let varIndex = this.getNextVarIndex(frameId);
1418
+ let arrayVarName = this.tempVarPrefix + 'eval';
1419
+ let bulkContainerStatement = `${arrayVarName}[${varIndex}] = [\n`;
1420
+ for (let storedVariable of storedVariables) {
1421
+ bulkContainerStatement += `${storedVariable},\n`;
1422
+ }
1423
+ bulkContainerStatement += `]`;
1424
+ command += bulkContainerStatement;
1425
+ results.bulkVarName = `${arrayVarName}[${varIndex}]`;
1426
+ let commandResults = await this.rokuAdapter.evaluate(command, frameId);
1427
+ if (commandResults.type === 'error') {
1428
+ throw new Error(commandResults.message);
1429
+ }
1430
+ }
1431
+ return results;
1432
+ }
1188
1433
  /**
1189
1434
  * Called when the host stops debugging
1190
1435
  * @param response
@@ -1304,28 +1549,57 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1304
1549
  this.clearState();
1305
1550
  return threads;
1306
1551
  }
1307
- getVariableFromResult(result, frameId) {
1308
- var _a, _b, _c, _d, _e;
1552
+ async getVariableFromResult(result, frameId, maxDepth = 1) {
1553
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1309
1554
  let v;
1310
1555
  if (result) {
1311
1556
  if (this.enableDebugProtocol) {
1312
1557
  let refId = this.getEvaluateRefId(result.evaluateName, frameId);
1558
+ if (result.isCustom && !((_a = result.presentationHint) === null || _a === void 0 ? void 0 : _a.lazy) && result.evaluateNow) {
1559
+ try {
1560
+ // We should not wait to resolve this variable later. Fetch, store, and merge the results right away.
1561
+ let { evalArgs } = await this.evaluateExpressionToTempVar({ expression: result.evaluateName, frameId: frameId }, util_1.util.getVariablePath(result.evaluateName));
1562
+ let newResult = await this.rokuAdapter.getVariable(evalArgs.expression, frameId);
1563
+ this.mergeEvaluateContainers(result, newResult);
1564
+ }
1565
+ catch (error) {
1566
+ logging_1.logger.error('Error getting variables', error);
1567
+ this.mergeEvaluateContainers(result, {
1568
+ name: result.name,
1569
+ evaluateName: result.evaluateName,
1570
+ children: [],
1571
+ value: `❌ Error: ${error.message}`,
1572
+ type: '',
1573
+ highLevelType: undefined,
1574
+ keyType: undefined
1575
+ });
1576
+ }
1577
+ }
1313
1578
  if (result.keyType) {
1579
+ let value = `${(_b = result.value) !== null && _b !== void 0 ? _b : result.type}`;
1580
+ let indexedVariables = result.indexedVariables;
1581
+ let namedVariables = result.namedVariables;
1582
+ if (indexedVariables === undefined || namedVariables === undefined) {
1583
+ // If either indexed or named variables are undefined, we should tell the debugger to ask for everything
1584
+ // by supplying undefined values for both
1585
+ indexedVariables = undefined;
1586
+ namedVariables = undefined;
1587
+ }
1314
1588
  // check to see if this is an dictionary or a list
1315
1589
  if (result.keyType === 'Integer') {
1316
1590
  // list type
1317
- v = new debugadapter_1.Variable(result.name, result.type, refId, result.elementCount, 0);
1318
- this.variables[refId] = v;
1591
+ v = new debugadapter_1.Variable(result.name, value, refId, indexedVariables, namedVariables);
1319
1592
  }
1320
1593
  else if (result.keyType === 'String') {
1321
1594
  // dictionary type
1322
- v = new debugadapter_1.Variable(result.name, result.type, refId, 0, result.elementCount);
1595
+ v = new debugadapter_1.Variable(result.name, value, refId, indexedVariables, namedVariables);
1323
1596
  }
1597
+ v.type = result.type;
1324
1598
  }
1325
1599
  else {
1326
1600
  let value;
1327
1601
  if (result.type === VariablesResponse_1.VariableType.Invalid) {
1328
- value = (_a = result.value) !== null && _a !== void 0 ? _a : 'Invalid';
1602
+ value = (_c = result.value) !== null && _c !== void 0 ? _c : 'Invalid';
1329
1603
  }
1330
1604
  else if (result.type === VariablesResponse_1.VariableType.Uninitialized) {
1331
1605
  value = 'Uninitialized';
@@ -1333,7 +1607,9 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1333
1607
  else {
1334
1608
  value = `${result.value}`;
1335
1609
  }
1336
- v = new debugadapter_1.Variable(result.name, value);
1610
+ // If the variable is lazy we must assign a refId to inform the system
1611
+ // to request this variable again in the future for value resolution
1612
+ v = new debugadapter_1.Variable(result.name, value, ((_d = result === null || result === void 0 ? void 0 : result.presentationHint) === null || _d === void 0 ? void 0 : _d.lazy) ? refId : 0);
1337
1613
  }
1338
1614
  this.variables[refId] = v;
1339
1615
  }
@@ -1343,45 +1619,101 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1343
1619
  }
1344
1620
  else if (result.highLevelType === 'array') {
1345
1621
  let refId = this.getEvaluateRefId(result.evaluateName, frameId);
1346
- 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);
1622
+ v = new debugadapter_1.Variable(result.name, result.type, refId, (_f = (_e = result.children) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0, 0);
1347
1623
  this.variables[refId] = v;
1348
1624
  }
1349
1625
  else if (result.highLevelType === 'object') {
1350
- let refId = this.getEvaluateRefId(result.evaluateName, frameId);
1351
- 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);
1626
+ let refId;
1627
+ //handle collections
1628
+ if (this.rokuAdapter.isScrapableContainObject(result.type)) {
1629
+ refId = this.getEvaluateRefId(result.evaluateName, frameId);
1630
+ }
1631
+ v = new debugadapter_1.Variable(result.name, result.type, refId, 0, (_h = (_g = result.children) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0);
1352
1632
  this.variables[refId] = v;
1353
1633
  }
1354
1634
  else if (result.highLevelType === 'function') {
1355
- v = new debugadapter_1.Variable(result.name, result.value);
1635
+ v = new debugadapter_1.Variable(result.name, `${result.value}`);
1356
1636
  }
1357
1637
  else {
1358
1638
  //all other cases, but mostly for HighLevelType.unknown
1359
- v = new debugadapter_1.Variable(result.name, result.value);
1639
+ v = new debugadapter_1.Variable(result.name, `${result.value}`);
1360
1640
  }
1361
1641
  }
1362
1642
  v.type = result.type;
1363
1643
  v.evaluateName = result.evaluateName;
1364
1644
  v.frameId = frameId;
1365
1645
  v.type = result.type;
1366
- v.presentationHint = result.presentationHint ? { kind: result.presentationHint } : undefined;
1646
+ v.presentationHint = result.presentationHint ? { kind: (_j = result.presentationHint) === null || _j === void 0 ? void 0 : _j.kind, lazy: (_k = result.presentationHint) === null || _k === void 0 ? void 0 : _k.lazy } : undefined;
1367
1647
  if (util_1.util.isTransientVariable(v.name)) {
1368
1648
  v.presentationHint = { kind: 'virtual' };
1369
1649
  }
1370
- if (result.children) {
1371
- let childVariables = [];
1372
- for (let childContainer of result.children) {
1373
- let childVar = this.getVariableFromResult(childContainer, frameId);
1374
- childVariables.push(childVar);
1650
+ if (result.children && maxDepth > 0) {
1651
+ if (!v.childVariables) {
1652
+ v.childVariables = [];
1653
+ }
1654
+ // Create a mapping of the children to their index so we can evaluate them in bulk
1655
+ let indexMappedChildren = result.children.map((child, index) => {
1656
+ var _a;
1657
+ let remapped = { child: child, index: index, evaluate: !!(child.isCustom && !((_a = child.presentationHint) === null || _a === void 0 ? void 0 : _a.lazy) && child.evaluateNow) };
1658
+ return remapped;
1659
+ });
1660
+ if (this.enableDebugProtocol) {
1661
+ let childrenToEvaluate = indexMappedChildren.filter(x => x.evaluate);
1662
+ let evaluateArgsArray = childrenToEvaluate.map(x => {
1663
+ return { expression: x.child.evaluateName, frameId: frameId };
1664
+ });
1665
+ let variablePathArray = childrenToEvaluate.map(x => {
1666
+ return util_1.util.getVariablePath(x.child.evaluateName);
1667
+ });
1668
+ try {
1669
+ let bulkEvaluations = await this.bulkEvaluateExpressionToTempVar(frameId, evaluateArgsArray, variablePathArray);
1670
+ if (bulkEvaluations.bulkVarName) {
1671
+ let newResults = await this.rokuAdapter.getVariable(bulkEvaluations.bulkVarName, frameId);
1672
+ childrenToEvaluate.map((mappedChild, index) => {
1673
+ let newResult = newResults.children[index];
1674
+ this.mergeEvaluateContainers(mappedChild.child, newResult);
1675
+ mappedChild.child.evaluateNow = false;
1676
+ return mappedChild;
1677
+ });
1678
+ }
1679
+ }
1680
+ catch (error) {
1681
+ this.logger.error('Error getting bulk variables, will fall back to var by var lookups', error);
1682
+ }
1375
1683
  }
1376
- v.childVariables = childVariables;
1684
+ // If bulk evaluations failed, there is fall back logic in `getVariableFromResult` to do individual evaluations
1685
+ v.childVariables = await Promise.all(indexMappedChildren.map(async (mappedChild) => {
1686
+ return this.getVariableFromResult(mappedChild.child, frameId, maxDepth - 1);
1687
+ }));
1688
+ }
1689
+ else {
1690
+ v.childVariables = [];
1377
1691
  }
1378
1692
  // if the var is an array and debugProtocol is enabled, include the array size
1379
1693
  if (this.enableDebugProtocol && v.type === VariablesResponse_1.VariableType.Array) {
1380
- v.value = `${v.type}(${result.elementCount})`;
1694
+ if (isNaN(result.indexedVariables)) {
1695
+ v.value = v.type;
1696
+ }
1697
+ else {
1698
+ v.value = `${v.type}(${result.indexedVariables})`;
1699
+ }
1381
1700
  }
1382
1701
  }
1383
1702
  return v;
1384
1703
  }
1704
+ /**
1705
+ * Helper function to merge the results of an evaluate call into an existing EvaluateContainer
1706
+ * Used primarily for custom variables
1707
+ */
1708
+ mergeEvaluateContainers(original, updated) {
1709
+ original.children = updated.children;
1710
+ original.value = updated.value;
1711
+ original.type = updated.type;
1712
+ original.highLevelType = updated.highLevelType;
1713
+ original.keyType = updated.keyType;
1714
+ original.indexedVariables = updated.indexedVariables;
1715
+ original.namedVariables = updated.namedVariables;
1716
+ }
1385
1717
  getEvaluateRefId(expression, frameId) {
1386
1718
  let evaluateRefId = `${expression}-${frameId}`;
1387
1719
  if (!this.evaluateRefIdLookup[evaluateRefId]) {
@@ -1430,13 +1762,19 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1430
1762
  return this.shutdownPromise;
1431
1763
  }
1432
1764
  async _shutdown(errorMessage, modal = false) {
1433
- var _a, _b, _c, _d, _e, _f, _g;
1765
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
1434
1766
  try {
1435
1767
  (_a = this.componentLibraryServer) === null || _a === void 0 ? void 0 : _a.stop();
1436
1768
  void ((_c = (_b = this.rendezvousTracker) === null || _b === void 0 ? void 0 : _b.destroy) === null || _c === void 0 ? void 0 : _c.call(_b));
1769
+ try {
1770
+ (_e = (_d = this.sourceMapManager) === null || _d === void 0 ? void 0 : _d.destroy) === null || _e === void 0 ? void 0 : _e.call(_d);
1771
+ }
1772
+ catch (e) {
1773
+ this.logger.error(e);
1774
+ }
1437
1775
  //if configured, delete the staging directory
1438
1776
  if (!this.launchConfiguration.retainStagingFolder) {
1439
- const stagingDirs = (_e = (_d = this.projectManager) === null || _d === void 0 ? void 0 : _d.getStagingDirs()) !== null && _e !== void 0 ? _e : [];
1777
+ const stagingDirs = (_g = (_f = this.projectManager) === null || _f === void 0 ? void 0 : _f.getStagingDirs()) !== null && _g !== void 0 ? _g : [];
1440
1778
  this.logger.info('deleting staging folders', stagingDirs);
1441
1779
  for (let stagingDir of stagingDirs) {
1442
1780
  try {
@@ -1454,7 +1792,7 @@ class BrightScriptDebugSession extends debugadapter_1.DebugSession {
1454
1792
  this.showPopupMessage(errorMessage, 'error', modal);
1455
1793
  }
1456
1794
  this.logger.log('Destroy rokuAdapter');
1457
- await ((_g = (_f = this.rokuAdapter) === null || _f === void 0 ? void 0 : _f.destroy) === null || _g === void 0 ? void 0 : _g.call(_f));
1795
+ await ((_j = (_h = this.rokuAdapter) === null || _h === void 0 ? void 0 : _h.destroy) === null || _j === void 0 ? void 0 : _j.call(_h));
1458
1796
  //press the home button to return to the home screen
1459
1797
  try {
1460
1798
  this.logger.log('Press home button');