Skip to content

Commit 1cc897a

Browse files
fix: Run and debug fail for iOS in Sidekick
When CLI is used as a library (in NativeScript Sidekick for example), calling methods for run and debug currently fails. The problem is with the parsing of the iOS logs, which was introduced several days ago. The logic uses `$projectData` from the `$injector`. However, when CLI is used as a library, the `$projectData` is never initialized. Instead of using `$projectData` pass the project directory and construct new project data (from `$projectDataService`) where required.
1 parent b1953f2 commit 1cc897a

14 files changed

+73
-63
lines changed

lib/definitions/debug.d.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Describes information for starting debug process.
33
*/
4-
interface IDebugData extends Mobile.IDeviceIdentifier {
4+
interface IDebugData extends Mobile.IDeviceIdentifier, IProjectDir {
55
/**
66
* Application identifier of the app that it will be debugged.
77
*/
@@ -16,11 +16,6 @@ interface IDebugData extends Mobile.IDeviceIdentifier {
1616
* The name of the application, for example `MyProject`.
1717
*/
1818
projectName?: string;
19-
20-
/**
21-
* Path to project.
22-
*/
23-
projectDir?: string;
2419
}
2520

2621
/**

lib/definitions/ios-debugger-port-service.d.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
interface IIOSDebuggerPortInputData {
1+
interface IIOSDebuggerPortInputData extends IProjectDir {
22
deviceId: string;
33
appId: string;
44
}
@@ -21,8 +21,10 @@ interface IIOSDebuggerPortService {
2121
/**
2222
* Attaches on DEBUGGER_PORT_FOUND event and STARTING_IOS_APPLICATION events
2323
* In case when DEBUGGER_PORT_FOUND event is emitted, stores the port and clears the timeout if such.
24-
* In case when STARTING_IOS_APPLICATION event is emiited, sets the port to null and add timeout for 5000 miliseconds which checks if port is null and prints a warning.
25-
* @param {Mobile.IDevice} device - Describes the device which logs should be parsed.
24+
* In case when STARTING_IOS_APPLICATION event is emitted, sets the port to null and add timeout for 5000 miliseconds which checks if port is null and prints a warning.
25+
* @param {Mobile.IDevice} device - Describes the device which logs should be parsed.
26+
* @param {IProjectDir} data - Object that has a projectDir property.
27+
* @returns {void}
2628
*/
27-
attachToDebuggerPortFoundEvent(device: Mobile.IDevice): void;
29+
attachToDebuggerPortFoundEvent(device: Mobile.IDevice, data: IProjectDir): void;
2830
}

lib/definitions/ios-log-parser-service.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ interface IIOSLogParserService extends NodeJS.EventEmitter {
33
* Starts looking for debugger port. Attaches on device logs and processes them. In case when port is found, DEBUGGER_PORT_FOUND event is emitted.
44
* @param {Mobile.IDevice} device - Describes the device which logs will be processed.
55
*/
6-
startParsingLog(device: Mobile.IDevice): void;
6+
startParsingLog(device: Mobile.IDevice, data: IProjectName): void;
77
}

lib/definitions/project.d.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
interface IProjectName {
2-
projectName: string;
3-
}
4-
5-
interface IProjectSettingsBase extends IProjectName {
62
/**
73
* Name of the newly created application.
84
*/
95
projectName: string;
6+
}
107

8+
interface IProjectSettingsBase extends IProjectName {
119
/**
1210
* Defines whether the `npm install` command should be executed with `--ignore-scripts` option.
1311
* When it is passed, all scripts (postinstall for example) will not be executed.

lib/services/ios-debug-service.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS
143143

144144
private async emulatorStart(debugData: IDebugData, debugOptions: IDebugOptions): Promise<string> {
145145
const device = await this.$devicesService.getDevice(debugData.deviceIdentifier);
146-
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device);
146+
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, debugData);
147147
const result = await this.wireDebuggerClient(debugData, debugOptions);
148148

149149
const attachRequestMessage = this.$iOSNotification.getAttachRequest(debugData.applicationIdentifier, debugData.deviceIdentifier);
@@ -192,7 +192,7 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS
192192
}
193193

194194
private async deviceStartCore(device: Mobile.IiOSDevice, debugData: IDebugData, debugOptions: IDebugOptions): Promise<string> {
195-
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device);
195+
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, debugData);
196196
await this.$iOSSocketRequestExecutor.executeAttachRequest(device, AWAIT_NOTIFICATION_TIMEOUT_SECONDS, debugData.applicationIdentifier);
197197
return this.wireDebuggerClient(debugData, debugOptions, device);
198198
}
@@ -231,7 +231,7 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS
231231

232232
private getSocketFactory(debugData: IDebugData, device?: Mobile.IiOSDevice): () => Promise<net.Socket> {
233233
const factory = async () => {
234-
const port = await this.$iOSDebuggerPortService.getPort({ deviceId: debugData.deviceIdentifier, appId: debugData.applicationIdentifier });
234+
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: debugData.projectDir, deviceId: debugData.deviceIdentifier, appId: debugData.applicationIdentifier });
235235
if (!port) {
236236
this.$errors.fail("NativeScript debugger was not able to get inspector socket port.");
237237
}

lib/services/ios-debugger-port-service.ts

+10-8
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService {
1010
constructor(private $iOSLogParserService: IIOSLogParserService,
1111
private $iOSProjectService: IPlatformProjectService,
1212
private $iOSNotification: IiOSNotification,
13-
private $logger: ILogger,
14-
private $projectData: IProjectData) { }
13+
private $projectDataService: IProjectDataService,
14+
private $logger: ILogger) { }
1515

1616
public getPort(data: IIOSDebuggerPortInputData): Promise<number> {
1717
return new Promise((resolve, reject) => {
18-
if (!this.canStartLookingForDebuggerPort()) {
18+
if (!this.canStartLookingForDebuggerPort(data)) {
1919
resolve(IOSDebuggerPortService.DEFAULT_PORT);
2020
return;
2121
}
@@ -36,19 +36,21 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService {
3636
});
3737
}
3838

39-
public attachToDebuggerPortFoundEvent(device: Mobile.IDevice): void {
40-
if (!this.canStartLookingForDebuggerPort()) {
39+
public attachToDebuggerPortFoundEvent(device: Mobile.IDevice, data: IProjectDir): void {
40+
const projectData = this.$projectDataService.getProjectData(data && data.projectDir);
41+
if (!this.canStartLookingForDebuggerPort(projectData)) {
4142
return;
4243
}
4344

4445
this.attachToDebuggerPortFoundEventCore();
4546
this.attachToAttachRequestEvent(device);
4647

47-
this.$iOSLogParserService.startParsingLog(device);
48+
this.$iOSLogParserService.startParsingLog(device, projectData);
4849
}
4950

50-
private canStartLookingForDebuggerPort(): boolean {
51-
const frameworkVersion = this.$iOSProjectService.getFrameworkVersion(this.$projectData);
51+
private canStartLookingForDebuggerPort(data: IProjectDir): boolean {
52+
const projectData = this.$projectDataService.getProjectData(data && data.projectDir);
53+
const frameworkVersion = this.$iOSProjectService.getFrameworkVersion(projectData);
5254
return semver.gt(frameworkVersion, IOSDebuggerPortService.MIN_REQUIRED_FRAMEWORK_VERSION);
5355
}
5456

lib/services/ios-log-parser-service.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ export class IOSLogParserService extends EventEmitter implements IIOSLogParserSe
99
constructor(private $deviceLogProvider: Mobile.IDeviceLogProvider,
1010
private $iosDeviceOperations: IIOSDeviceOperations,
1111
private $iOSSimulatorLogProvider: Mobile.IiOSSimulatorLogProvider,
12-
private $logger: ILogger,
13-
private $projectData: IProjectData) {
12+
private $logger: ILogger) {
1413
super();
1514
}
1615

17-
public startParsingLog(device: Mobile.IDevice): void {
18-
this.$deviceLogProvider.setProjectNameForDevice(device.deviceInfo.identifier, this.$projectData.projectName);
16+
public startParsingLog(device: Mobile.IDevice, data: IProjectName): void {
17+
this.$deviceLogProvider.setProjectNameForDevice(device.deviceInfo.identifier, data.projectName);
1918

2019
if (!this.startedDeviceLogInstances[device.deviceInfo.identifier]) {
2120
this.startParsingLogCore(device);

lib/services/livesync/android-device-livesync-service.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export class AndroidDeviceLiveSyncService extends DeviceLiveSyncServiceBase impl
1212
private port: number;
1313

1414
constructor(_device: Mobile.IDevice,
15+
data: IProjectDir,
1516
private $mobileHelper: Mobile.IMobileHelper,
1617
private $devicePathProvider: IDevicePathProvider,
1718
private $injector: IInjector,

lib/services/livesync/android-livesync-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export class AndroidLiveSyncService extends PlatformLiveSyncServiceBase implemen
1313
super($fs, $logger, $platformsData, $projectFilesManager, $devicePathProvider, $projectFilesProvider);
1414
}
1515

16-
protected _getDeviceLiveSyncService(device: Mobile.IDevice): INativeScriptDeviceLiveSyncService {
17-
const service = this.$injector.resolve<INativeScriptDeviceLiveSyncService>(AndroidDeviceLiveSyncService, { _device: device });
16+
protected _getDeviceLiveSyncService(device: Mobile.IDevice, data: IProjectDir): INativeScriptDeviceLiveSyncService {
17+
const service = this.$injector.resolve<INativeScriptDeviceLiveSyncService>(AndroidDeviceLiveSyncService, { _device: device, data });
1818
return service;
1919
}
2020
}

lib/services/livesync/ios-device-livesync-service.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen
1010
private device: Mobile.IiOSDevice;
1111

1212
constructor(_device: Mobile.IiOSDevice,
13+
data: IProjectDir,
1314
private $iOSSocketRequestExecutor: IiOSSocketRequestExecutor,
1415
private $iOSNotification: IiOSNotification,
1516
private $iOSEmulatorServices: Mobile.IiOSSimulatorService,
@@ -19,25 +20,25 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen
1920
private $processService: IProcessService,
2021
protected $platformsData: IPlatformsData) {
2122
super($platformsData);
22-
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(_device);
23+
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(_device, data);
2324
this.device = _device;
2425
}
2526

26-
private async setupSocketIfNeeded(appId: string): Promise<boolean> {
27+
private async setupSocketIfNeeded(projectData: IProjectData): Promise<boolean> {
2728
if (this.socket) {
2829
return true;
2930
}
3031

3132
if (this.device.isEmulator) {
32-
await this.$iOSEmulatorServices.postDarwinNotification(this.$iOSNotification.getAttachRequest(appId, this.device.deviceInfo.identifier), this.device.deviceInfo.identifier);
33-
const port = await this.$iOSDebuggerPortService.getPort({ deviceId: this.device.deviceInfo.identifier, appId });
33+
await this.$iOSEmulatorServices.postDarwinNotification(this.$iOSNotification.getAttachRequest(projectData.projectId, this.device.deviceInfo.identifier), this.device.deviceInfo.identifier);
34+
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId: projectData.projectId });
3435
this.socket = await this.$iOSEmulatorServices.connectToPort({ port });
3536
if (!this.socket) {
3637
return false;
3738
}
3839
} else {
39-
await this.$iOSSocketRequestExecutor.executeAttachRequest(this.device, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, appId);
40-
const port = await this.$iOSDebuggerPortService.getPort({ deviceId: this.device.deviceInfo.identifier, appId });
40+
await this.$iOSSocketRequestExecutor.executeAttachRequest(this.device, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, projectData.projectId);
41+
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId: projectData.projectId });
4142
this.socket = await this.device.connectToPort(port);
4243
}
4344

@@ -70,7 +71,7 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen
7071
return;
7172
}
7273

73-
if (await this.setupSocketIfNeeded(projectData.projectId)) {
74+
if (await this.setupSocketIfNeeded(projectData)) {
7475
await this.liveEdit(scriptFiles);
7576
await this.reloadPage(deviceAppData, otherFiles);
7677
} else {

lib/services/livesync/ios-livesync-service.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class IOSLiveSyncService extends PlatformLiveSyncServiceBase implements I
2525
return super.fullSync(syncInfo);
2626
}
2727

28-
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device);
28+
this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, syncInfo.projectData);
2929

3030
const projectData = syncInfo.projectData;
3131
const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
@@ -70,8 +70,8 @@ export class IOSLiveSyncService extends PlatformLiveSyncServiceBase implements I
7070
}
7171
}
7272

73-
protected _getDeviceLiveSyncService(device: Mobile.IDevice): INativeScriptDeviceLiveSyncService {
74-
const service = this.$injector.resolve<INativeScriptDeviceLiveSyncService>(IOSDeviceLiveSyncService, { _device: device });
73+
protected _getDeviceLiveSyncService(device: Mobile.IDevice, data: IProjectDir): INativeScriptDeviceLiveSyncService {
74+
const service = this.$injector.resolve<INativeScriptDeviceLiveSyncService>(IOSDeviceLiveSyncService, { _device: device, data });
7575
return service;
7676
}
7777
}

lib/services/livesync/platform-livesync-service-base.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ export abstract class PlatformLiveSyncServiceBase {
1212
private $devicePathProvider: IDevicePathProvider,
1313
private $projectFilesProvider: IProjectFilesProvider) { }
1414

15-
public getDeviceLiveSyncService(device: Mobile.IDevice, applicationIdentifier: string): INativeScriptDeviceLiveSyncService {
16-
const key = device.deviceInfo.identifier + applicationIdentifier;
15+
public getDeviceLiveSyncService(device: Mobile.IDevice, projectData: IProjectData): INativeScriptDeviceLiveSyncService {
16+
const key = device.deviceInfo.identifier + projectData.projectId;
1717
if (!this._deviceLiveSyncServicesCache[key]) {
18-
this._deviceLiveSyncServicesCache[key] = this._getDeviceLiveSyncService(device);
18+
this._deviceLiveSyncServicesCache[key] = this._getDeviceLiveSyncService(device, projectData);
1919
}
2020

2121
return this._deviceLiveSyncServicesCache[key];
2222
}
2323

24-
protected abstract _getDeviceLiveSyncService(device: Mobile.IDevice): INativeScriptDeviceLiveSyncService;
24+
protected abstract _getDeviceLiveSyncService(device: Mobile.IDevice, data: IProjectDir): INativeScriptDeviceLiveSyncService;
2525

2626
public async refreshApplication(projectData: IProjectData, liveSyncInfo: ILiveSyncResultInfo): Promise<void> {
2727
if (liveSyncInfo.isFullSync || liveSyncInfo.modifiedFilesData.length) {
28-
const deviceLiveSyncService = this.getDeviceLiveSyncService(liveSyncInfo.deviceAppData.device, projectData.projectId);
28+
const deviceLiveSyncService = this.getDeviceLiveSyncService(liveSyncInfo.deviceAppData.device, projectData);
2929
this.$logger.info("Refreshing application...");
3030
await deviceLiveSyncService.refreshApplication(projectData, liveSyncInfo);
3131
}
@@ -34,7 +34,7 @@ export abstract class PlatformLiveSyncServiceBase {
3434
public async fullSync(syncInfo: IFullSyncInfo): Promise<ILiveSyncResultInfo> {
3535
const projectData = syncInfo.projectData;
3636
const device = syncInfo.device;
37-
const deviceLiveSyncService = this.getDeviceLiveSyncService(device, syncInfo.projectData.projectId);
37+
const deviceLiveSyncService = this.getDeviceLiveSyncService(device, syncInfo.projectData);
3838
const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
3939
const deviceAppData = await this.getAppData(syncInfo);
4040

@@ -93,7 +93,7 @@ export abstract class PlatformLiveSyncServiceBase {
9393
const localToDevicePaths = await this.$projectFilesManager.createLocalToDevicePaths(deviceAppData, projectFilesPath, mappedFiles, []);
9494
modifiedLocalToDevicePaths.push(...localToDevicePaths);
9595

96-
const deviceLiveSyncService = this.getDeviceLiveSyncService(device, projectData.projectId);
96+
const deviceLiveSyncService = this.getDeviceLiveSyncService(device, projectData);
9797
await deviceLiveSyncService.removeFiles(deviceAppData, localToDevicePaths);
9898
}
9999

test/services/ios-debugger-port-service.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ function createTestInjector() {
4747
injector.register("processService", {
4848
attachToProcessExitSignals: () => ({})
4949
});
50-
injector.register("projectData", {
51-
projectName: "test",
52-
projectId: appId
50+
injector.register("projectDataService", {
51+
getProjectData: (projectDir: string) => ({
52+
projectName: "test",
53+
projectId: appId
54+
})
5355
});
5456
injector.register("iOSNotification", DeviceApplicationManagerMock);
5557

@@ -140,31 +142,35 @@ describe("iOSDebuggerPortService", () => {
140142
}
141143
];
142144

145+
const mockProjectDirObj = {
146+
projectDir: "/Users/username/projectdir"
147+
};
148+
143149
_.each(testCases, testCase => {
144150
it(testCase.name, async () => {
145-
iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device);
151+
iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, mockProjectDirObj);
146152
if (testCase.emitStartingIOSApplicationEvent) {
147153
emitStartingIOSApplicationEvent();
148154
}
149155
if (testCase.emittedPort) {
150156
emitDeviceLog(getDebuggerPortMessage(testCase.emittedPort));
151157
}
152158

153-
const promise = iOSDebuggerPortService.getPort({ deviceId: deviceId, appId: appId });
159+
const promise = iOSDebuggerPortService.getPort({ deviceId: deviceId, appId: appId, projectDir: mockProjectDirObj.projectDir });
154160
clock.tick(10000);
155161
const port = await promise;
156162
assert.deepEqual(port, testCase.emittedPort);
157163
});
158164
it(`${testCase.name} for multiline debugger port message.`, async () => {
159-
iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device);
165+
iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, mockProjectDirObj);
160166
if (testCase.emitStartingIOSApplicationEvent) {
161167
emitStartingIOSApplicationEvent();
162168
}
163169
if (testCase.emittedPort) {
164170
emitDeviceLog(getMultilineDebuggerPortMessage(testCase.emittedPort));
165171
}
166172

167-
const promise = iOSDebuggerPortService.getPort({ deviceId: deviceId, appId: appId });
173+
const promise = iOSDebuggerPortService.getPort({ deviceId: deviceId, appId: appId, projectDir: mockProjectDirObj.projectDir });
168174
clock.tick(10000);
169175
const port = await promise;
170176
assert.deepEqual(port, testCase.emittedPort);

test/services/ios-log-parser-service.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ function createTestInjector() {
3535
injector.register("processService", {
3636
attachToProcessExitSignals: () => ({})
3737
});
38-
injector.register("projectData", {
39-
projectName: "test",
40-
projectId: appId
38+
injector.register("projectDataService", {
39+
getProjectData: (projectDir: string) => ({
40+
projectName: "test",
41+
projectId: appId
42+
})
4143
});
4244

4345
return injector;
@@ -77,12 +79,16 @@ describe("iOSLogParserService", () => {
7779
});
7880
}
7981

82+
const mockProjectNameObj: IProjectName = {
83+
projectName: "projectName"
84+
};
85+
8086
describe("startLookingForDebuggerPort", () => {
8187
it(`should emit ${DEBUGGER_PORT_FOUND_EVENT_NAME} event`, async () => {
8288
const emittedMessagesCount = 1;
8389
const promise = attachOnDebuggerFoundEvent(emittedMessagesCount);
8490

85-
iOSLogParserService.startParsingLog(device);
91+
iOSLogParserService.startParsingLog(device, mockProjectNameObj);
8692
emitDeviceLog("test message");
8793
emitDeviceLog(getDebuggerPortMessage(18181));
8894

@@ -95,7 +101,7 @@ describe("iOSLogParserService", () => {
95101
const emittedMessagesCount = 5;
96102
const promise = attachOnDebuggerFoundEvent(emittedMessagesCount);
97103

98-
iOSLogParserService.startParsingLog(device);
104+
iOSLogParserService.startParsingLog(device, mockProjectNameObj);
99105
emitDeviceLog(getDebuggerPortMessage(18181));
100106
emitDeviceLog(getDebuggerPortMessage(18181));
101107
emitDeviceLog(getDebuggerPortMessage(18181));
@@ -115,7 +121,7 @@ describe("iOSLogParserService", () => {
115121
const emittedMessagesCount = 5;
116122
const promise = attachOnDebuggerFoundEvent(emittedMessagesCount);
117123

118-
iOSLogParserService.startParsingLog(device);
124+
iOSLogParserService.startParsingLog(device, mockProjectNameObj);
119125
emitDeviceLog(getDebuggerPortMessage(45898));
120126
emitDeviceLog(getDebuggerPortMessage(1809));
121127
emitDeviceLog(getDebuggerPortMessage(65072));
@@ -136,7 +142,7 @@ describe("iOSLogParserService", () => {
136142

137143
iOSLogParserService.on(DEBUGGER_PORT_FOUND_EVENT_NAME, (data: IIOSDebuggerPortData) => isDebuggedPortFound = true);
138144

139-
iOSLogParserService.startParsingLog(device);
145+
iOSLogParserService.startParsingLog(device, mockProjectNameObj);
140146
emitDeviceLog("some test message");
141147
emitDeviceLog("another test message");
142148

0 commit comments

Comments
 (0)