From d6c552d799e5797fa8bffba8493f39bed9fed132 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Wed, 17 Jan 2024 23:18:40 -0500 Subject: [PATCH 01/17] Add new custom event to trigger tasks --- src/LaunchConfiguration.ts | 26 +++++++++++++ src/debugSession/BrightScriptDebugSession.ts | 41 +++++++++++++++++--- src/debugSession/Events.ts | 24 ++++++++++++ 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/LaunchConfiguration.ts b/src/LaunchConfiguration.ts index 14209221..a41eb213 100644 --- a/src/LaunchConfiguration.ts +++ b/src/LaunchConfiguration.ts @@ -285,6 +285,32 @@ export interface LaunchConfiguration extends DebugProtocol.LaunchRequestArgument * @default false */ deleteDevChannelBeforeInstall: boolean; + + /** + * Task to run instead of roku-deploy to produce the .zip file that will be uploaded to the Roku. + */ + packageTask: string; + + /** + * Path to the .zip that will be uploaded to the Roku + */ + packagePath: string; + + /** + * Overrides for values used during the roku-deploy zip upload process, like the route and various form data. You probably don't need to change these.. + */ + packageUploadOverrides: { + /** + * The route to use for uploading to the Roku device. Defaults to 'plugin_install' + * @default 'plugin_install' + */ + route: string; + + /** + * A dictionary of form fields to be included in the package upload request. Set a value to null to delete from the form + */ + formData: Record; + }; } export interface ComponentLibraryConfiguration { diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index e7abae1b..208709be 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -39,7 +39,9 @@ import { ChanperfEvent, DebugServerLogOutputEvent, ChannelPublishedEvent, - PopupMessageEvent + PopupMessageEvent, + CustomRequestEvent, + ClientToServerCustomEventName } from './Events'; import type { LaunchConfiguration, ComponentLibraryConfiguration } from '../LaunchConfiguration'; import { FileManager } from '../managers/FileManager'; @@ -208,6 +210,31 @@ export class BrightScriptDebugSession extends BaseDebugSession { this.logger.trace('[showPopupMessage]', severity, message); this.sendEvent(new PopupMessageEvent(message, severity, modal)); } + + private static requestIdSequence = 0; + + private async sendCustomRequest(name: string, data: T) { + const requestId = BrightScriptDebugSession.requestIdSequence++; + const responsePromise = new Promise((resolve, reject) => { + this.on(ClientToServerCustomEventName.customRequestEventResponse, (response) => { + if (response.requestId === requestId) { + if (response.error) { + throw response.error; + } else { + resolve(response); + } + } + }); + }); + this.sendEvent( + new CustomRequestEvent({ + requestId: requestId, + name: name, + ...data ?? {} + })); + await responsePromise; + } + /** * Get the cwd from the launchConfiguration, or default to process.cwd() */ @@ -233,7 +260,6 @@ export class BrightScriptDebugSession extends BaseDebugSession { } public async launchRequest(response: DebugProtocol.LaunchResponse, config: LaunchConfiguration) { - this.logger.log('[launchRequest] begin'); //send the response right away so the UI immediately shows the debugger toolbar this.sendResponse(response); @@ -245,6 +271,8 @@ export class BrightScriptDebugSession extends BaseDebugSession { logger.logLevel = this.launchConfiguration.logLevel; } + await this.sendCustomRequest('executeTask', { task: config.packageTask }); + //do a DNS lookup for the host to fix issues with roku rejecting ECP try { this.launchConfiguration.host = await util.dnsLookup(this.launchConfiguration.host); @@ -655,14 +683,17 @@ export class BrightScriptDebugSession extends BaseDebugSession { * Accepts custom events and requests from the extension * @param command name of the command to execute */ - protected customRequest(command: string) { + protected customRequest(command: string, response: DebugProtocol.Response, args: any) { if (command === 'rendezvous.clearHistory') { this.rokuAdapter.clearRendezvousHistory(); - } - if (command === 'chanperf.clearHistory') { + } else if (command === 'chanperf.clearHistory') { this.rokuAdapter.clearChanperfHistory(); + + } else if (command === 'customRequestEventResponse') { + this.emit('customRequestEventResponse', args); } + this.sendResponse(response); } /** diff --git a/src/debugSession/Events.ts b/src/debugSession/Events.ts index be29bacf..66813d8f 100644 --- a/src/debugSession/Events.ts +++ b/src/debugSession/Events.ts @@ -158,6 +158,30 @@ export function isChannelPublishedEvent(event: any): event is ChannelPublishedEv return !!event && event.event === ChannelPublishedEvent.name; } +/** + * Event that asks the client to execute a command. + */ +export class CustomRequestEvent extends CustomEvent { + constructor(body: R) { + super(body); + } +} + +/** + * Is the object a `CustomRequestEvent` + */ +export function isCustomRequestEvent(event: any): event is CustomRequestEvent { + return !!event && event.event === CustomRequestEvent.name; +} + +export function isExecuteTaskCustomRequest(event: any): event is CustomRequestEvent<{ task: string }> { + return !!event && event.event === CustomRequestEvent.name && event.body.name === 'executeTask'; +} + +export enum ClientToServerCustomEventName { + customRequestEventResponse = 'customRequestEventResponse' +} + export enum StoppedEventReason { step = 'step', breakpoint = 'breakpoint', From 862ee269c737aa2f4bb4067281bce677b1b7213d Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Wed, 17 Jan 2024 23:31:57 -0500 Subject: [PATCH 02/17] support packagePath --- src/debugSession/BrightScriptDebugSession.ts | 20 ++++++++++++++------ src/managers/ProjectManager.ts | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 208709be..cbd740f9 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -271,8 +271,6 @@ export class BrightScriptDebugSession extends BaseDebugSession { logger.logLevel = this.launchConfiguration.logLevel; } - await this.sendCustomRequest('executeTask', { task: config.packageTask }); - //do a DNS lookup for the host to fix issues with roku rejecting ECP try { this.launchConfiguration.host = await util.dnsLookup(this.launchConfiguration.host); @@ -537,9 +535,13 @@ export class BrightScriptDebugSession extends BaseDebugSession { this.logger.warn('Failed to delete the dev channel...probably not a big deal', e); } + //publish the package to the target Roku const publishPromise = this.rokuDeploy.publish({ ...this.launchConfiguration, + //supply the outDir and outFile based on `packagePath` if provided, otherwise use the defaults + outDir: this.launchConfiguration.packagePath ? path.dirname(this.launchConfiguration.packagePath) : this.launchConfiguration.outDir, + outFile: this.launchConfiguration.packagePath ? path.basename(this.launchConfiguration.packagePath) : undefined, //typing fix logLevel: LogLevelPriority[this.logger.logLevel], // enable the debug protocol if true @@ -656,7 +658,8 @@ export class BrightScriptDebugSession extends BaseDebugSession { raleTrackerTaskFileLocation: this.launchConfiguration.raleTrackerTaskFileLocation, injectRdbOnDeviceComponent: this.launchConfiguration.injectRdbOnDeviceComponent, rdbFilesBasePath: this.launchConfiguration.rdbFilesBasePath, - stagingFolderPath: this.launchConfiguration.stagingFolderPath + stagingFolderPath: this.launchConfiguration.stagingFolderPath, + packagePath: this.launchConfiguration.packagePath }); util.log('Moving selected files to staging area'); @@ -674,9 +677,14 @@ export class BrightScriptDebugSession extends BaseDebugSession { await this.breakpointManager.writeBreakpointsForProject(this.projectManager.mainProject); } - //create zip package from staging folder - util.log('Creating zip archive from project sources'); - await this.projectManager.mainProject.zipPackage({ retainStagingFolder: true }); + if (this.launchConfiguration.packageTask) { + util.log(`Executing task '${this.launchConfiguration.packageTask}' to build the zip for us`); + await this.sendCustomRequest('executeTask', { task: this.launchConfiguration.packageTask }); + } else { + //create zip package from staging folder + util.log('Creating zip archive from project sources'); + await this.projectManager.mainProject.zipPackage({ retainStagingFolder: true }); + } } /** diff --git a/src/managers/ProjectManager.ts b/src/managers/ProjectManager.ts index a16d7156..3a367f29 100644 --- a/src/managers/ProjectManager.ts +++ b/src/managers/ProjectManager.ts @@ -37,6 +37,7 @@ export class ProjectManager { public launchConfiguration: { enableSourceMaps?: boolean; enableDebugProtocol?: boolean; + packagePath: string; }; public logger = logger.createLogger('[ProjectManager]'); @@ -227,6 +228,7 @@ export interface AddProjectParams { rdbFilesBasePath?: string; bsConst?: Record; stagingFolderPath?: string; + packagePath?: string; } export class Project { From 1d79a2d82e14e5203bcee30ebfcc9985a3bc6d1f Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 19 Jan 2024 11:04:19 -0500 Subject: [PATCH 03/17] Support using `packagePath` when supplied --- src/managers/ProjectManager.spec.ts | 11 +++++++++++ src/managers/ProjectManager.ts | 19 ++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/managers/ProjectManager.spec.ts b/src/managers/ProjectManager.spec.ts index e86b92ee..448e9a60 100644 --- a/src/managers/ProjectManager.spec.ts +++ b/src/managers/ProjectManager.spec.ts @@ -666,6 +666,17 @@ describe('Project', () => { expect(fsExtra.pathExistsSync(`${tempPath}/extracted/source/main.brs`)).to.be.true; expect(fsExtra.pathExistsSync(`${tempPath}/extracted/source/main.brs.map`)).to.be.false; }); + + it('uses "packagePath" when specified', async () => { + fsExtra.outputFileSync(`${project.stagingFolderPath}/manifest`, '#stuff'); + fsExtra.outputFileSync(`${project.stagingFolderPath}/source/main.brs`, 'sub main() : end sub'); + project.packagePath = s`${tempPath}/package/path.zip`; + await project.zipPackage({ retainStagingFolder: true }); + + await decompress(project.packagePath, `${tempPath}/extracted`); + expect(fsExtra.pathExistsSync(`${tempPath}/extracted/manifest`)).to.be.true; + expect(fsExtra.pathExistsSync(`${tempPath}/extracted/source/main.brs`)).to.be.true; + }); }); }); diff --git a/src/managers/ProjectManager.ts b/src/managers/ProjectManager.ts index 3a367f29..f478e88d 100644 --- a/src/managers/ProjectManager.ts +++ b/src/managers/ProjectManager.ts @@ -220,6 +220,7 @@ export class ProjectManager { export interface AddProjectParams { rootDir: string; outDir: string; + packagePath?: string; sourceDirs?: string[]; files: Array; injectRaleTrackerTask?: boolean; @@ -228,7 +229,6 @@ export interface AddProjectParams { rdbFilesBasePath?: string; bsConst?: Record; stagingFolderPath?: string; - packagePath?: string; } export class Project { @@ -239,7 +239,7 @@ export class Project { assert(params?.outDir, 'outDir is required'); this.outDir = fileUtils.standardizePath(params.outDir); - this.stagingFolderPath = params.stagingFolderPath ?? rokuDeploy.getOptions(this).stagingFolderPath; + this.stagingFolderPath = params.stagingDir ?? rokuDeploy.getOptions(this).stagingFolderPath; this.bsConst = params.bsConst; this.sourceDirs = (params.sourceDirs ?? []) //standardize every sourcedir @@ -249,9 +249,11 @@ export class Project { this.injectRdbOnDeviceComponent = params.injectRdbOnDeviceComponent ?? false; this.rdbFilesBasePath = params.rdbFilesBasePath; this.files = params.files ?? []; + this.packagePath = params.packagePath; } public rootDir: string; public outDir: string; + public packagePath: string; public sourceDirs: string[]; public files: Array; public stagingFolderPath: string; @@ -474,16 +476,19 @@ export class Project { * * @param stagingPath */ - public async zipPackage(params: { retainStagingFolder: true }) { + public async zipPackage(params: { retainStagingFolder: boolean }) { const options = rokuDeploy.getOptions({ ...this, ...params }); - //make sure the output folder exists - await fsExtra.ensureDir(options.outDir); + let packagePath = this.packagePath; + if (!this.packagePath) { + //make sure the output folder exists + await fsExtra.ensureDir(options.outDir); - let zipFilePath = rokuDeploy.getOutputZipFilePath(options); + packagePath = rokuDeploy.getOutputZipFilePath(options); + } //ensure the manifest file exists in the staging folder if (!await rokuDeployUtil.fileExistsCaseInsensitive(`${options.stagingDir}/manifest`)) { @@ -491,7 +496,7 @@ export class Project { } // create a zip of the staging folder - await rokuDeploy.zipFolder(options.stagingDir, zipFilePath, undefined, [ + await rokuDeploy.zipFolder(options.stagingDir, packagePath, undefined, [ '**/*', //exclude sourcemap files (they're large and can't be parsed on-device anyway...) '!**/*.map' From d1a99af2d34e1cd5e1b3ca4bd94f6282b27016fc Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 19 Jan 2024 11:37:33 -0500 Subject: [PATCH 04/17] doesHostSupportEcpRendezvousTracking better null handling --- src/RendezvousTracker.spec.ts | 14 ++++++++++++++ src/RendezvousTracker.ts | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/RendezvousTracker.spec.ts b/src/RendezvousTracker.spec.ts index ff2b58db..997b21ff 100644 --- a/src/RendezvousTracker.spec.ts +++ b/src/RendezvousTracker.spec.ts @@ -291,6 +291,20 @@ describe('BrightScriptFileUtils ', () => { rendezvousTracker['deviceInfo'].softwareVersion = '12.0.1'; expect(rendezvousTracker.doesHostSupportEcpRendezvousTracking).to.be.true; }); + + it('does not crash when softwareVersion is corrupt or missing', () => { + rendezvousTracker['deviceInfo'].softwareVersion = ''; + expect(rendezvousTracker.doesHostSupportEcpRendezvousTracking).to.be.false; + + rendezvousTracker['deviceInfo'].softwareVersion = 'notAVersion'; + expect(rendezvousTracker.doesHostSupportEcpRendezvousTracking).to.be.false; + + rendezvousTracker['deviceInfo'].softwareVersion = undefined; + expect(rendezvousTracker.doesHostSupportEcpRendezvousTracking).to.be.false; + + rendezvousTracker['deviceInfo'] = undefined; + expect(rendezvousTracker.doesHostSupportEcpRendezvousTracking).to.be.false; + }); }); describe('on', () => { diff --git a/src/RendezvousTracker.ts b/src/RendezvousTracker.ts index dba1b442..e1dd210f 100644 --- a/src/RendezvousTracker.ts +++ b/src/RendezvousTracker.ts @@ -38,7 +38,11 @@ export class RendezvousTracker { * Determine if the current Roku device supports the ECP rendezvous tracking feature */ public get doesHostSupportEcpRendezvousTracking() { - return semver.gte(this.deviceInfo.softwareVersion, '11.5.0'); + let softwareVersion = this.deviceInfo?.softwareVersion; + if (!semver.valid(softwareVersion)) { + softwareVersion = '0.0.0'; + } + return semver.gte(softwareVersion, '11.5.0'); } public logger = logger.createLogger(`[${RendezvousTracker.name}]`); From 3d3ba8ef0544290a47a153d2f5862aaf3fb21d3f Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 19 Jan 2024 11:37:55 -0500 Subject: [PATCH 05/17] Better launchConfig sanitization --- src/debugSession/BrightScriptDebugSession.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 8ab327db..c58a2179 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -250,6 +250,9 @@ export class BrightScriptDebugSession extends BaseDebugSession { * @returns */ private normalizeLaunchConfig(config: LaunchConfiguration) { + config.cwd ??= process.cwd(); + config.outDir ??= s`${config.cwd}/out`; + config.stagingDir ??= s`${config.outDir}/.roku-deploy-staging`; config.componentLibrariesPort ??= 8080; config.packagePort ??= 80; config.remotePort ??= 8060; From 51f5604e1ae01451832d595399004f6e48f9a62f Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 19 Jan 2024 15:57:28 -0500 Subject: [PATCH 06/17] Pass through packageUploadOverrides to roku-deploy --- src/LaunchConfiguration.ts | 2 +- .../BrightScriptDebugSession.spec.ts | 86 ++++++++++++++++++- src/debugSession/BrightScriptDebugSession.ts | 4 +- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/LaunchConfiguration.ts b/src/LaunchConfiguration.ts index bff9fa04..bf39e271 100644 --- a/src/LaunchConfiguration.ts +++ b/src/LaunchConfiguration.ts @@ -306,7 +306,7 @@ export interface LaunchConfiguration extends DebugProtocol.LaunchRequestArgument /** * Overrides for values used during the roku-deploy zip upload process, like the route and various form data. You probably don't need to change these.. */ - packageUploadOverrides: { + packageUploadOverrides?: { /** * The route to use for uploading to the Roku device. Defaults to 'plugin_install' * @default 'plugin_install' diff --git a/src/debugSession/BrightScriptDebugSession.spec.ts b/src/debugSession/BrightScriptDebugSession.spec.ts index 395b0a3a..29ae3836 100644 --- a/src/debugSession/BrightScriptDebugSession.spec.ts +++ b/src/debugSession/BrightScriptDebugSession.spec.ts @@ -9,15 +9,16 @@ import { BrightScriptDebugSession } from './BrightScriptDebugSession'; import { fileUtils } from '../FileUtils'; import type { EvaluateContainer, StackFrame, TelnetAdapter } from '../adapters/TelnetAdapter'; import { PrimativeType } from '../adapters/TelnetAdapter'; -import { defer } from '../util'; +import { defer, util } from '../util'; import { HighLevelType } from '../interfaces'; import type { LaunchConfiguration } from '../LaunchConfiguration'; import type { SinonStub } from 'sinon'; import { DiagnosticSeverity, util as bscUtil, standardizePath as s } from 'brighterscript'; -import { DefaultFiles } from 'roku-deploy'; +import { DefaultFiles, rokuDeploy } from 'roku-deploy'; import type { AddProjectParams, ComponentLibraryConstructorParams } from '../managers/ProjectManager'; import { ComponentLibraryProject, Project } from '../managers/ProjectManager'; import { RendezvousTracker } from '../RendezvousTracker'; +import { ClientToServerCustomEventName, isCustomRequestEvent } from './Events'; const sinon = sinonActual.createSandbox(); const tempDir = s`${__dirname}/../../.tmp`; @@ -148,6 +149,87 @@ describe('BrightScriptDebugSession', () => { sinon.restore(); }); + it('supports external zipping process', async () => { + //write some project files + fsExtra.outputFileSync(`${rootDir}/source/main.brs`, ` + sub main() + print "hello" + end sub + `); + fsExtra.outputFileSync(`${rootDir}/manifest`, ''); + + const packagePath = s`${tempDir}/custom/app.zip`; + + //init the session + session.initializeRequest({} as any, {} as any); + + //set a breakpoint in main + await session.setBreakPointsRequest({} as any, { + source: { + path: s`${rootDir}/source/main.brs` + }, + breakpoints: [{ + line: 2 + }] + }); + + sinon.stub(rokuDeploy, 'getDeviceInfo').returns(Promise.resolve({ + developerEnabled: true + })); + sinon.stub(util, 'dnsLookup').callsFake((host) => Promise.resolve(host)); + + let sendEvent = session.sendEvent.bind(session); + sinon.stub(session, 'sendEvent').callsFake((event) => { + if (isCustomRequestEvent(event)) { + void rokuDeploy.zipFolder(session['launchConfiguration'].stagingDir, packagePath).then(() => { + //pretend we are the client and send a response back + session.emit(ClientToServerCustomEventName.customRequestEventResponse, { + requestId: event.body.requestId + }); + }); + } else { + //call through + return sendEvent(event); + } + }); + sinon.stub(session as any, 'connectRokuAdapter').callsFake(() => { + sinon.stub(session['rokuAdapter'], 'connect').returns(Promise.resolve()); + session['rokuAdapter'].connected = true; + return Promise.resolve(session['rokuAdapter']); + }); + + const publishStub = sinon.stub(session.rokuDeploy, 'publish').returns(Promise.resolve() as any); + + await session.launchRequest({} as any, { + cwd: tempDir, + //where the source files reside + rootDir: rootDir, + //where roku-debug should put the staged files (and inject breakpoints) + stagingDir: `${stagingDir}/staging`, + //the name of the task that should be run to create the zip (doesn't matter for this test...we're going to intercept it anyway) + packageTask: 'custom-build', + //where the packageTask will be placing the compiled zip + packagePath: packagePath, + packageUploadOverrides: { + route: '1234', + formData: { + one: 'two', + three: null + } + } + } as Partial as LaunchConfiguration); + + expect(publishStub.getCall(0).args[0]).to.include({ + packageUploadOverrides: { + route: '1234', + formData: { + one: 'two', + three: null + } + } + }); + }); + describe('evaluateRequest', () => { it('resets local var counter on suspend', async () => { const stub = sinon.stub(session['rokuAdapter'], 'evaluate').callsFake(x => { diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index c58a2179..579b4999 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -553,7 +553,9 @@ export class BrightScriptDebugSession extends BaseDebugSession { //necessary for capturing compile errors from the protocol (has no effect on telnet) remoteDebugConnectEarly: false, //we don't want to fail if there were compile errors...we'll let our compile error processor handle that - failOnCompileError: true + failOnCompileError: true, + //pass any upload form overrides the client may have configured + packageUploadOverrides: this.launchConfiguration.packageUploadOverrides }).then(() => { packageIsPublished = true; }).catch(async (e) => { From bf76a691514fc9461aaecaac3746ac9da1176e11 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 19 Jan 2024 16:05:00 -0500 Subject: [PATCH 07/17] Fix stagingFolderPath reference --- src/managers/ProjectManager.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/ProjectManager.spec.ts b/src/managers/ProjectManager.spec.ts index fb50ea47..ab9579fc 100644 --- a/src/managers/ProjectManager.spec.ts +++ b/src/managers/ProjectManager.spec.ts @@ -668,8 +668,8 @@ describe('Project', () => { }); it('uses "packagePath" when specified', async () => { - fsExtra.outputFileSync(`${project.stagingFolderPath}/manifest`, '#stuff'); - fsExtra.outputFileSync(`${project.stagingFolderPath}/source/main.brs`, 'sub main() : end sub'); + fsExtra.outputFileSync(`${project.stagingDir}/manifest`, '#stuff'); + fsExtra.outputFileSync(`${project.stagingDir}/source/main.brs`, 'sub main() : end sub'); project.packagePath = s`${tempPath}/package/path.zip`; await project.zipPackage({ retainStagingFolder: true }); From 1fba681e85d1421f7d5ef440859266b0e115f475 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Tue, 23 Jan 2024 09:07:13 -0500 Subject: [PATCH 08/17] Fix crash related to outDir and outFile --- src/debugSession/BrightScriptDebugSession.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 579b4999..032ffc0c 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -539,13 +539,8 @@ export class BrightScriptDebugSession extends BaseDebugSession { this.logger.warn('Failed to delete the dev channel...probably not a big deal', e); } - - //publish the package to the target Roku - const publishPromise = this.rokuDeploy.publish({ + const options: RokuDeployOptions = { ...this.launchConfiguration, - //supply the outDir and outFile based on `packagePath` if provided, otherwise use the defaults - outDir: this.launchConfiguration.packagePath ? path.dirname(this.launchConfiguration.packagePath) : this.launchConfiguration.outDir, - outFile: this.launchConfiguration.packagePath ? path.basename(this.launchConfiguration.packagePath) : undefined, //typing fix logLevel: LogLevelPriority[this.logger.logLevel], // enable the debug protocol if true @@ -556,7 +551,15 @@ export class BrightScriptDebugSession extends BaseDebugSession { failOnCompileError: true, //pass any upload form overrides the client may have configured packageUploadOverrides: this.launchConfiguration.packageUploadOverrides - }).then(() => { + }; + //if packagePath is specified, use that info instead of outDir and outFile + if (this.launchConfiguration.packagePath) { + options.outDir = path.dirname(this.launchConfiguration.packagePath); + options.outFile = path.basename(this.launchConfiguration.packagePath); + } + + //publish the package to the target Roku + const publishPromise = this.rokuDeploy.publish(options).then(() => { packageIsPublished = true; }).catch(async (e) => { const statusCode = e?.results?.response?.statusCode; From fe0cd0c230fd36c7a9e91f7eb53a1f9bfdbb8abe Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Mon, 29 Jan 2024 13:27:58 -0500 Subject: [PATCH 09/17] Fix bug in `getFileScheme` --- src/debugSession/BrightScriptDebugSession.spec.ts | 12 +++++------- src/util.spec.ts | 4 ++++ src/util.ts | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/debugSession/BrightScriptDebugSession.spec.ts b/src/debugSession/BrightScriptDebugSession.spec.ts index 29ae3836..3795ae35 100644 --- a/src/debugSession/BrightScriptDebugSession.spec.ts +++ b/src/debugSession/BrightScriptDebugSession.spec.ts @@ -219,13 +219,11 @@ describe('BrightScriptDebugSession', () => { } } as Partial as LaunchConfiguration); - expect(publishStub.getCall(0).args[0]).to.include({ - packageUploadOverrides: { - route: '1234', - formData: { - one: 'two', - three: null - } + expect(publishStub.getCall(0).args[0].packageUploadOverrides).to.eql({ + route: '1234', + formData: { + one: 'two', + three: null } }); }); diff --git a/src/util.spec.ts b/src/util.spec.ts index f0e5b2c7..15263dc5 100644 --- a/src/util.spec.ts +++ b/src/util.spec.ts @@ -121,6 +121,10 @@ describe('Util', () => { assert.equal(util.getFileScheme('/images/channel-poster_hd.png'), null); assert.equal(util.getFileScheme('ages/channel-poster_hd.png'), null); }); + + it('should support file schemes with underscores', () => { + assert.equal(util.getFileScheme('thing_with_underscores:/source/lib.brs'), 'thing_with_underscores:'); + }); }); describe('convertManifestToObject', () => { diff --git a/src/util.ts b/src/util.ts index ad8be3d4..e5b797c9 100644 --- a/src/util.ts +++ b/src/util.ts @@ -68,7 +68,7 @@ class Util { * @param filePath */ public getFileScheme(filePath: string): string | null { - return url.parse(filePath).protocol; + return /^([\w_-]+:)/.exec(filePath)?.[1]?.toLowerCase(); } /** From 381ccfe3c52384cb2d37407dbcb6b798e2801b1f Mon Sep 17 00:00:00 2001 From: George Cook Date: Fri, 16 Feb 2024 17:31:39 +0000 Subject: [PATCH 10/17] clears cache when manually controlling telnet session --- src/debugSession/BrightScriptDebugSession.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 2609c302..171e32e5 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -1127,6 +1127,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { let deferred = defer(); if (args.context === 'repl' && !this.enableDebugProtocol && args.expression.trim().startsWith('>')) { this.clearState(); + this.rokuAdapter.clearCache(); const expression = args.expression.replace(/^\s*>\s*/, ''); this.logger.log('Sending raw telnet command...I sure hope you know what you\'re doing', { expression }); (this.rokuAdapter as TelnetAdapter).requestPipeline.client.write(`${expression}\r\n`); From c7819398fa311e19183bd01d5af2db4ce7d6cc68 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Wed, 21 Feb 2024 14:23:29 -0500 Subject: [PATCH 11/17] Support `packageTask` --- src/LaunchConfiguration.ts | 5 +++++ src/debugSession/BrightScriptDebugSession.ts | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/LaunchConfiguration.ts b/src/LaunchConfiguration.ts index bf39e271..38c9fad1 100644 --- a/src/LaunchConfiguration.ts +++ b/src/LaunchConfiguration.ts @@ -298,6 +298,11 @@ export interface LaunchConfiguration extends DebugProtocol.LaunchRequestArgument */ packageTask: string; + /** + * Task to run to upload the package instead of having roku-deploy do it + */ + publishTask: string; + /** * Path to the .zip that will be uploaded to the Roku */ diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 171e32e5..c7768361 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -507,6 +507,12 @@ export class BrightScriptDebugSession extends BaseDebugSession { } private async publish() { + if (this.launchConfiguration.publishTask) { + util.log(`Executing task '${this.launchConfiguration.publishTask}' to upload the zip instead of having roku-deploy do it`); + await this.sendCustomRequest('executeTask', { task: this.launchConfiguration.publishTask }); + return; + } + this.logger.log('Uploading zip'); const start = Date.now(); let packageIsPublished = false; From 00b0a63c7646afeabbf310f0838a51cd844c239e Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Wed, 21 Feb 2024 16:48:36 -0500 Subject: [PATCH 12/17] Sill fixes. --- src/debugSession/BrightScriptDebugSession.ts | 32 +++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index c7768361..eb885098 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -265,6 +265,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { public async launchRequest(response: DebugProtocol.LaunchResponse, config: LaunchConfiguration) { this.logger.log('[launchRequest] begin'); + //send the response right away so the UI immediately shows the debugger toolbar this.sendResponse(response); @@ -318,15 +319,15 @@ export class BrightScriptDebugSession extends BaseDebugSession { util.log(`Connecting to Roku via telnet at ${this.launchConfiguration.host}:${this.launchConfiguration.brightScriptConsolePort}`); } - await this.initRendezvousTracking(); + // await this.initRendezvousTracking(); this.createRokuAdapter(this.rendezvousTracker); await this.connectRokuAdapter(); - await this.runAutomaticSceneGraphCommands(this.launchConfiguration.autoRunSgDebugCommands); + // await this.runAutomaticSceneGraphCommands(this.launchConfiguration.autoRunSgDebugCommands); //press the home button to ensure we're at the home screen - await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); //pass the log level down thought the adapter to the RendezvousTracker and ChanperfTracker this.rokuAdapter.setConsoleOutput(this.launchConfiguration.consoleOutput); @@ -381,7 +382,8 @@ export class BrightScriptDebugSession extends BaseDebugSession { } }); - await this.publish(); + this.logger.log('[launchRequest]', 'DISABLING PUBLISH'); + // await this.publish(); this.sendEvent(new ChannelPublishedEvent( this.launchConfiguration @@ -426,7 +428,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { //if we are at a breakpoint, continue await this.rokuAdapter.continue(); //kill the app on the roku - await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); //convert a hostname to an ip address const deepLinkUrl = await util.resolveUrl(this.launchConfiguration.deepLinkUrl); //send the deep link http request @@ -507,23 +509,17 @@ export class BrightScriptDebugSession extends BaseDebugSession { } private async publish() { - if (this.launchConfiguration.publishTask) { - util.log(`Executing task '${this.launchConfiguration.publishTask}' to upload the zip instead of having roku-deploy do it`); - await this.sendCustomRequest('executeTask', { task: this.launchConfiguration.publishTask }); - return; - } - this.logger.log('Uploading zip'); const start = Date.now(); let packageIsPublished = false; //delete any currently installed dev channel (if enabled to do so) try { - if (this.launchConfiguration.deleteDevChannelBeforeInstall === true) { - await this.rokuDeploy.deleteInstalledChannel({ - ...this.launchConfiguration - } as any as RokuDeployOptions); - } + // if (this.launchConfiguration.deleteDevChannelBeforeInstall === true) { + // await this.rokuDeploy.deleteInstalledChannel({ + // ...this.launchConfiguration + // } as any as RokuDeployOptions); + // } } catch (e) { const statusCode = e?.results?.response?.statusCode; const message = e.message as string; @@ -1256,7 +1252,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { protected async disconnectRequest(response: DebugProtocol.DisconnectResponse, args: DebugProtocol.DisconnectArguments, request?: DebugProtocol.Request) { //return to the home screen if (!this.enableDebugProtocol) { - await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); } this.sendResponse(response); await this.shutdown(); @@ -1537,7 +1533,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { //press the home button to return to the home screen try { this.logger.log('Press home button'); - await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); } catch (e) { this.logger.error(e); } From 66c7a9a9f2ec911d658505b308f6d6c76fb6231c Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Mon, 26 Feb 2024 08:34:56 -0500 Subject: [PATCH 13/17] restore some actions that were disabled during testing --- src/LaunchConfiguration.ts | 5 ----- src/debugSession/BrightScriptDebugSession.ts | 22 ++++++++++---------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/LaunchConfiguration.ts b/src/LaunchConfiguration.ts index 38c9fad1..bf39e271 100644 --- a/src/LaunchConfiguration.ts +++ b/src/LaunchConfiguration.ts @@ -298,11 +298,6 @@ export interface LaunchConfiguration extends DebugProtocol.LaunchRequestArgument */ packageTask: string; - /** - * Task to run to upload the package instead of having roku-deploy do it - */ - publishTask: string; - /** * Path to the .zip that will be uploaded to the Roku */ diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index eb885098..3b14588c 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -324,10 +324,10 @@ export class BrightScriptDebugSession extends BaseDebugSession { this.createRokuAdapter(this.rendezvousTracker); await this.connectRokuAdapter(); - // await this.runAutomaticSceneGraphCommands(this.launchConfiguration.autoRunSgDebugCommands); + await this.runAutomaticSceneGraphCommands(this.launchConfiguration.autoRunSgDebugCommands); //press the home button to ensure we're at the home screen - // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); //pass the log level down thought the adapter to the RendezvousTracker and ChanperfTracker this.rokuAdapter.setConsoleOutput(this.launchConfiguration.consoleOutput); @@ -383,7 +383,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { }); this.logger.log('[launchRequest]', 'DISABLING PUBLISH'); - // await this.publish(); + await this.publish(); this.sendEvent(new ChannelPublishedEvent( this.launchConfiguration @@ -515,11 +515,11 @@ export class BrightScriptDebugSession extends BaseDebugSession { //delete any currently installed dev channel (if enabled to do so) try { - // if (this.launchConfiguration.deleteDevChannelBeforeInstall === true) { - // await this.rokuDeploy.deleteInstalledChannel({ - // ...this.launchConfiguration - // } as any as RokuDeployOptions); - // } + if (this.launchConfiguration.deleteDevChannelBeforeInstall === true) { + await this.rokuDeploy.deleteInstalledChannel({ + ...this.launchConfiguration + } as any as RokuDeployOptions); + } } catch (e) { const statusCode = e?.results?.response?.statusCode; const message = e.message as string; @@ -680,7 +680,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { } if (this.launchConfiguration.packageTask) { - util.log(`Executing task '${this.launchConfiguration.packageTask}' to build the zip for us`); + util.log(`Executing task '${this.launchConfiguration.packageTask}' to assemble the app`); await this.sendCustomRequest('executeTask', { task: this.launchConfiguration.packageTask }); } else { //create zip package from staging folder @@ -1252,7 +1252,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { protected async disconnectRequest(response: DebugProtocol.DisconnectResponse, args: DebugProtocol.DisconnectArguments, request?: DebugProtocol.Request) { //return to the home screen if (!this.enableDebugProtocol) { - // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); } this.sendResponse(response); await this.shutdown(); @@ -1533,7 +1533,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { //press the home button to return to the home screen try { this.logger.log('Press home button'); - // await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); + await this.rokuDeploy.pressHomeButton(this.launchConfiguration.host, this.launchConfiguration.remotePort); } catch (e) { this.logger.error(e); } From 50f9bca35198ebc579e46a10682b68b9574cfae9 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Mon, 26 Feb 2024 09:20:45 -0500 Subject: [PATCH 14/17] reenable rendezvous tracker --- src/adapters/TelnetAdapter.ts | 2 +- src/debugSession/BrightScriptDebugSession.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/TelnetAdapter.ts b/src/adapters/TelnetAdapter.ts index 2619d23d..b740b67a 100644 --- a/src/adapters/TelnetAdapter.ts +++ b/src/adapters/TelnetAdapter.ts @@ -5,7 +5,7 @@ import { rokuDeploy } from 'roku-deploy'; import { PrintedObjectParser } from '../PrintedObjectParser'; import type { BSDebugDiagnostic } from '../CompileErrorProcessor'; import { CompileErrorProcessor } from '../CompileErrorProcessor'; -import type { RendezvousHistory, RendezvousTracker } from '../RendezvousTracker'; +import type { RendezvousTracker } from '../RendezvousTracker'; import type { ChanperfData } from '../ChanperfTracker'; import { ChanperfTracker } from '../ChanperfTracker'; import type { SourceLocation } from '../managers/LocationManager'; diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 3b14588c..ca77b6d8 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -319,7 +319,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { util.log(`Connecting to Roku via telnet at ${this.launchConfiguration.host}:${this.launchConfiguration.brightScriptConsolePort}`); } - // await this.initRendezvousTracking(); + await this.initRendezvousTracking(); this.createRokuAdapter(this.rendezvousTracker); await this.connectRokuAdapter(); From 7a503fa4e1ea073139cbdfaf38798a7729d70cd6 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Mon, 26 Feb 2024 10:47:08 -0500 Subject: [PATCH 15/17] Better detection of missing custom package --- src/debugSession/BrightScriptDebugSession.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index ca77b6d8..1b89e16c 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -682,6 +682,20 @@ export class BrightScriptDebugSession extends BaseDebugSession { if (this.launchConfiguration.packageTask) { util.log(`Executing task '${this.launchConfiguration.packageTask}' to assemble the app`); await this.sendCustomRequest('executeTask', { task: this.launchConfiguration.packageTask }); + + const options = { + ...this.launchConfiguration + } as any as RokuDeployOptions; + //if packagePath is specified, use that info instead of outDir and outFile + if (this.launchConfiguration.packagePath) { + options.outDir = path.dirname(this.launchConfiguration.packagePath); + options.outFile = path.basename(this.launchConfiguration.packagePath); + } + const packagePath = this.launchConfiguration.packagePath ?? rokuDeploy.getOutputZipFilePath(options); + + if (!fsExtra.pathExistsSync(packagePath)) { + return this.shutdown(`Cancelling debug session. Package does not exist at '${packagePath}'`); + } } else { //create zip package from staging folder util.log('Creating zip archive from project sources'); From 4c1e1af6bb18bff328ca162ea7927880ca83c4d8 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Tue, 27 Feb 2024 14:46:13 -0500 Subject: [PATCH 16/17] Add `emitChannelPublishedEvent` launch option --- src/LaunchConfiguration.ts | 7 +++++++ src/debugSession/BrightScriptDebugSession.ts | 11 +++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/LaunchConfiguration.ts b/src/LaunchConfiguration.ts index bf39e271..839154a7 100644 --- a/src/LaunchConfiguration.ts +++ b/src/LaunchConfiguration.ts @@ -318,6 +318,13 @@ export interface LaunchConfiguration extends DebugProtocol.LaunchRequestArgument */ formData: Record; }; + + /** + * Should the ChannelPublishedEvent be emitted. This is a hack for when certain roku devices become locked up as a result of this event + * being emitted. You probably don't need to set this + * @default true + */ + emitChannelPublishedEvent?: boolean; } export interface ComponentLibraryConfiguration { diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 1b89e16c..51b22ab7 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -260,6 +260,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { config.controlPort ??= 8081; config.brightScriptConsolePort ??= 8085; config.stagingDir ??= config.stagingFolderPath; + config.emitChannelPublishedEvent ??= true; return config; } @@ -382,12 +383,14 @@ export class BrightScriptDebugSession extends BaseDebugSession { } }); - this.logger.log('[launchRequest]', 'DISABLING PUBLISH'); await this.publish(); - this.sendEvent(new ChannelPublishedEvent( - this.launchConfiguration - )); + //hack for certain roku devices that lock up when this event is emitted (no idea why!). + if (this.launchConfiguration.emitChannelPublishedEvent) { + this.sendEvent(new ChannelPublishedEvent( + this.launchConfiguration + )); + } //tell the adapter adapter that the channel has been launched. await this.rokuAdapter.activate(); From ae576e2b4e34505aa904bd5e70eda3ddbba3c52d Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 1 Mar 2024 14:41:16 -0500 Subject: [PATCH 17/17] roku-deploy@3.12.0 and fix failing test --- package-lock.json | 14 +++++------ package.json | 2 +- .../BrightScriptDebugSession.spec.ts | 23 +++++++++++++------ src/debugSession/BrightScriptDebugSession.ts | 2 +- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index b405fb21..b043b85a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "postman-request": "^2.88.1-postman.32", "replace-in-file": "^6.3.2", "replace-last": "^1.2.6", - "roku-deploy": "^3.11.2", + "roku-deploy": "^3.12.0", "semver": "^7.5.4", "serialize-error": "^8.1.0", "smart-buffer": "^4.2.0", @@ -4893,9 +4893,9 @@ } }, "node_modules/roku-deploy": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.11.2.tgz", - "integrity": "sha512-3JDlnbTxv6Xk5GVolQoA3+d34MLZXXwZWMySprHwazZoWLP3LvulYHP92YvFOJAo/aI4IZp/TFA8kR82IrmHKA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.12.0.tgz", + "integrity": "sha512-YiCZeQ+sEmFW9ZfXtMNH+/CBSHQ5deNZYWONM+s6gCEQsrz7kCMFPj5YEdgfqW+d2b8G1ve9GELHcSt2FsfM8g==", "dependencies": { "chalk": "^2.4.2", "dateformat": "^3.0.3", @@ -9598,9 +9598,9 @@ } }, "roku-deploy": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.11.2.tgz", - "integrity": "sha512-3JDlnbTxv6Xk5GVolQoA3+d34MLZXXwZWMySprHwazZoWLP3LvulYHP92YvFOJAo/aI4IZp/TFA8kR82IrmHKA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.12.0.tgz", + "integrity": "sha512-YiCZeQ+sEmFW9ZfXtMNH+/CBSHQ5deNZYWONM+s6gCEQsrz7kCMFPj5YEdgfqW+d2b8G1ve9GELHcSt2FsfM8g==", "requires": { "chalk": "^2.4.2", "dateformat": "^3.0.3", diff --git a/package.json b/package.json index fcb9879c..de262703 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "postman-request": "^2.88.1-postman.32", "replace-in-file": "^6.3.2", "replace-last": "^1.2.6", - "roku-deploy": "^3.11.2", + "roku-deploy": "^3.12.0", "semver": "^7.5.4", "serialize-error": "^8.1.0", "smart-buffer": "^4.2.0", diff --git a/src/debugSession/BrightScriptDebugSession.spec.ts b/src/debugSession/BrightScriptDebugSession.spec.ts index 3795ae35..e4df696c 100644 --- a/src/debugSession/BrightScriptDebugSession.spec.ts +++ b/src/debugSession/BrightScriptDebugSession.spec.ts @@ -7,8 +7,8 @@ import type { DebugProtocol } from 'vscode-debugprotocol/lib/debugProtocol'; import { DebugSession } from 'vscode-debugadapter'; import { BrightScriptDebugSession } from './BrightScriptDebugSession'; import { fileUtils } from '../FileUtils'; -import type { EvaluateContainer, StackFrame, TelnetAdapter } from '../adapters/TelnetAdapter'; -import { PrimativeType } from '../adapters/TelnetAdapter'; +import type { EvaluateContainer, StackFrame } from '../adapters/TelnetAdapter'; +import { PrimativeType, TelnetAdapter } from '../adapters/TelnetAdapter'; import { defer, util } from '../util'; import { HighLevelType } from '../interfaces'; import type { LaunchConfiguration } from '../LaunchConfiguration'; @@ -19,6 +19,7 @@ import type { AddProjectParams, ComponentLibraryConstructorParams } from '../man import { ComponentLibraryProject, Project } from '../managers/ProjectManager'; import { RendezvousTracker } from '../RendezvousTracker'; import { ClientToServerCustomEventName, isCustomRequestEvent } from './Events'; +import { EventEmitter } from 'eventemitter3'; const sinon = sinonActual.createSandbox(); const tempDir = s`${__dirname}/../../.tmp`; @@ -100,10 +101,10 @@ describe('BrightScriptDebugSession', () => { } }; rokuAdapter = { - on: () => { - return () => { - }; - }, + emitter: new EventEmitter(), + on: TelnetAdapter.prototype.on, + once: TelnetAdapter.prototype.once, + emit: TelnetAdapter.prototype['emit'], activate: () => Promise.resolve(), registerSourceLocator: (a, b) => { }, setConsoleOutput: (a) => { }, @@ -198,7 +199,15 @@ describe('BrightScriptDebugSession', () => { return Promise.resolve(session['rokuAdapter']); }); - const publishStub = sinon.stub(session.rokuDeploy, 'publish').returns(Promise.resolve() as any); + const publishStub = sinon.stub(session.rokuDeploy, 'publish').callsFake(() => { + //emit the app-ready event + (session['rokuAdapter'] as TelnetAdapter)['emit']('app-ready'); + + return Promise.resolve({ + message: 'success', + results: [] + }); + }); await session.launchRequest({} as any, { cwd: tempDir, diff --git a/src/debugSession/BrightScriptDebugSession.ts b/src/debugSession/BrightScriptDebugSession.ts index 51b22ab7..90c7cbbc 100644 --- a/src/debugSession/BrightScriptDebugSession.ts +++ b/src/debugSession/BrightScriptDebugSession.ts @@ -576,7 +576,7 @@ export class BrightScriptDebugSession extends BaseDebugSession { //if it hasn't connected after 5 seconds, it probably will never connect. await Promise.race([ isConnected, - util.sleep(10000) + util.sleep(10_000) ]); this.logger.log('Finished racing promises'); //if the adapter is still not connected, then it will probably never connect. Abort.