Skip to content

Commit bd9bc87

Browse files
Merge pull request #3848 from NativeScript/vladimirov/merge-rel-master
chore: merge release in master
2 parents 9dd6f20 + be85c3f commit bd9bc87

14 files changed

+403
-43
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
NativeScript CLI Changelog
22
================
33

4+
4.2.3 (2018, August 27)
5+
==
6+
7+
### Fixed
8+
* [Fixed #3840](https://github.com/NativeScript/nativescript-cli/issues/3840): Unable to reconnect to iOS Simulator when debugging
9+
* [Fixed #3824](https://github.com/NativeScript/nativescript-cli/issues/3824): `tns create` command not using proxy set with `tns proxy set`
10+
11+
12+
4.2.2 (2018, August 17)
13+
==
14+
15+
### Fixed
16+
* [Fixed #3818](https://github.com/NativeScript/nativescript-cli/issues/3818): Unable to start application on Android device with a custom activity containing capital letters
17+
* [Fixed #3820](https://github.com/NativeScript/nativescript-cli/issues/3820): A command help is shown on native build error
18+
* [Fixed #3821](https://github.com/NativeScript/nativescript-cli/issues/3821): [Sporadic] Unable to start iOS debugger from VSCode extension
19+
20+
421
4.2.1 (2018, August 10)
522
==
623

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface IIOSDebuggerPortService {
1717
* Gets iOS debugger port for specified deviceId and appId
1818
* @param {IIOSDebuggerPortInputData} data - Describes deviceId and appId
1919
*/
20-
getPort(data: IIOSDebuggerPortInputData): Promise<number>;
20+
getPort(data: IIOSDebuggerPortInputData, debugOptions?: IDebugOptions): Promise<number>;
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.

lib/definitions/pacote-service.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ declare global {
1818
extractPackage(packageName: string, destinationDirectory: string, options?: IPacoteExtractOptions): Promise<void>;
1919
}
2020

21-
interface IPacoteBaseOptions {
21+
interface IPacoteBaseOptions extends IProxySettingsBase {
2222
/**
2323
* The path to npm cache
2424
*/

lib/device-sockets/ios/socket-proxy-factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class SocketProxyFactory extends EventEmitter implements ISocketProxyFact
9090
this.$logger.info("Frontend client connected.");
9191
let _socket;
9292
try {
93-
_socket = await factory();
93+
_socket = await helpers.connectEventuallyUntilTimeout(factory, 10000);
9494
} catch (err) {
9595
err.deviceIdentifier = deviceIdentifier;
9696
this.$logger.trace(err);

lib/services/android-project-service.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,11 +701,17 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
701701
const childProcessOpts = opts.childProcessOpts || {};
702702
childProcessOpts.cwd = childProcessOpts.cwd || projectRoot;
703703
childProcessOpts.stdio = childProcessOpts.stdio || "inherit";
704+
let commandResult;
705+
try {
706+
commandResult = await this.spawn(gradlew,
707+
gradleArgs,
708+
childProcessOpts,
709+
spawnFromEventOptions);
710+
} catch (err) {
711+
this.$errors.failWithoutHelp(err.message);
712+
}
704713

705-
return await this.spawn(gradlew,
706-
gradleArgs,
707-
childProcessOpts,
708-
spawnFromEventOptions);
714+
return commandResult;
709715
}
710716
}
711717

lib/services/ios-debug-service.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS
202202
// the VSCode Ext starts `tns debug ios --no-client` to start/attach to debug sessions
203203
// check if --no-client is passed - default to opening a tcp socket (versus Chrome DevTools (websocket))
204204
if ((debugOptions.inspector || !debugOptions.client) && this.$hostInfo.isDarwin) {
205-
this._socketProxy = await this.$socketProxyFactory.createTCPSocketProxy(this.getSocketFactory(debugData, device));
205+
this._socketProxy = await this.$socketProxyFactory.createTCPSocketProxy(this.getSocketFactory(device, debugData, debugOptions));
206206
await this.openAppInspector(this._socketProxy.address(), debugData, debugOptions);
207207
return null;
208208
} else {
@@ -211,7 +211,7 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS
211211
}
212212

213213
const deviceIdentifier = device ? device.deviceInfo.identifier : debugData.deviceIdentifier;
214-
this._socketProxy = await this.$socketProxyFactory.createWebSocketProxy(this.getSocketFactory(debugData, device), deviceIdentifier);
214+
this._socketProxy = await this.$socketProxyFactory.createWebSocketProxy(this.getSocketFactory(device, debugData, debugOptions), deviceIdentifier);
215215
return this.getChromeDebugUrl(debugOptions, this._socketProxy.options.port);
216216
}
217217
}
@@ -230,15 +230,24 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS
230230
}
231231
}
232232

233-
private getSocketFactory(debugData: IDebugData, device?: Mobile.IiOSDevice): () => Promise<net.Socket> {
233+
private getSocketFactory(device: Mobile.IiOSDevice, debugData: IDebugData, debugOptions: IDebugOptions): () => Promise<net.Socket> {
234+
let pendingExecution: Promise<net.Socket> = null;
234235
const factory = async () => {
235-
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: debugData.projectDir, deviceId: debugData.deviceIdentifier, appId: debugData.applicationIdentifier });
236-
if (!port) {
237-
this.$errors.fail("NativeScript debugger was not able to get inspector socket port.");
236+
if (!pendingExecution) {
237+
const func = async () => {
238+
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: debugData.projectDir, deviceId: debugData.deviceIdentifier, appId: debugData.applicationIdentifier }, debugOptions);
239+
if (!port) {
240+
this.$errors.fail("NativeScript debugger was not able to get inspector socket port.");
241+
}
242+
const socket = device ? await device.connectToPort(port) : net.connect(port);
243+
this._sockets.push(socket);
244+
pendingExecution = null;
245+
return socket;
246+
};
247+
pendingExecution = func();
238248
}
239-
const socket = device ? await device.connectToPort(port) : net.connect(port);
240-
this._sockets.push(socket);
241-
return socket;
249+
250+
return pendingExecution;
242251
};
243252

244253
factory.bind(this);

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService {
1414
private $projectDataService: IProjectDataService,
1515
private $logger: ILogger) { }
1616

17-
public getPort(data: IIOSDebuggerPortInputData): Promise<number> {
17+
public getPort(data: IIOSDebuggerPortInputData, debugOptions?: IDebugOptions): Promise<number> {
1818
return new Promise((resolve, reject) => {
1919
if (!this.canStartLookingForDebuggerPort(data)) {
2020
resolve(IOSDebuggerPortService.DEFAULT_PORT);
2121
return;
2222
}
2323

2424
const key = `${data.deviceId}${data.appId}`;
25-
let retryCount: number = 10;
25+
const timeout = this.getTimeout(debugOptions);
26+
let retryCount = Math.max(timeout * 1000 / 500, 10);
2627

2728
const interval = setInterval(() => {
2829
let port = this.getPortByKey(key);

lib/services/ios-project-service.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
5757
private $plistParser: IPlistParser,
5858
private $sysInfo: ISysInfo,
5959
private $xCConfigService: XCConfigService) {
60-
super($fs, $projectDataService);
60+
super($fs, $projectDataService);
6161
}
6262

6363
private _platformsDirCache: string = null;
@@ -442,11 +442,19 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
442442
localArgs.push("-quiet");
443443
this.$logger.info("Xcode build...");
444444
}
445-
return this.$childProcess.spawnFromEvent("xcodebuild",
446-
localArgs,
447-
"exit",
448-
{ stdio: stdio || "inherit", cwd },
449-
{ emitOptions: { eventName: constants.BUILD_OUTPUT_EVENT_NAME }, throwError: true });
445+
446+
let commandResult;
447+
try {
448+
commandResult = await this.$childProcess.spawnFromEvent("xcodebuild",
449+
localArgs,
450+
"exit",
451+
{ stdio: stdio || "inherit", cwd },
452+
{ emitOptions: { eventName: constants.BUILD_OUTPUT_EVENT_NAME }, throwError: true });
453+
} catch (err) {
454+
this.$errors.failWithoutHelp(err.message);
455+
}
456+
457+
return commandResult;
450458
}
451459

452460
private async setupSigningFromTeam(projectRoot: string, projectData: IProjectData, teamId: string) {
@@ -1112,7 +1120,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
11121120
private async prepareNativeSourceCode(pluginName: string, pluginPlatformsFolderPath: string, projectData: IProjectData): Promise<void> {
11131121
const project = this.createPbxProj(projectData);
11141122
const group = this.getRootGroup(pluginName, pluginPlatformsFolderPath);
1115-
project.addPbxGroup(group.files, group.name, group.path, null, {isMain:true});
1123+
project.addPbxGroup(group.files, group.name, group.path, null, { isMain: true });
11161124
project.addToHeaderSearchPaths(group.path);
11171125
this.savePbxProj(project, projectData);
11181126
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,10 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
313313
const connectionTimer = setTimeout(() => {
314314
if (!isConnected) {
315315
isConnected = true;
316+
if (this.pendingConnectionData && this.pendingConnectionData.socketTimer) {
317+
clearTimeout(this.pendingConnectionData.socketTimer);
318+
}
319+
316320
reject(lastKnownError || new Error("Socket connection timeouted."));
317321
this.pendingConnectionData = null;
318322
}

lib/services/pacote-service.ts

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,78 @@ import * as path from "path";
44

55
export class PacoteService implements IPacoteService {
66
constructor(private $fs: IFileSystem,
7-
private $npm: INodePackageManager) { }
7+
private $npm: INodePackageManager,
8+
private $proxyService: IProxyService,
9+
private $logger: ILogger) { }
810

911
public async manifest(packageName: string, options?: IPacoteManifestOptions): Promise<any> {
10-
// In case `tns create myapp --template https://github.com/NativeScript/template-hello-world.git` command is executed, pacote module throws an error if cache option is not provided.
11-
const cache = await this.$npm.getCachePath();
12-
const manifestOptions = { cache };
12+
this.$logger.trace(`Calling pacoteService.manifest for packageName: '${packageName}' and options: ${options}`);
13+
const manifestOptions: IPacoteBaseOptions = await this.getPacoteBaseOptions();
1314
if (options) {
1415
_.extend(manifestOptions, options);
1516
}
1617

17-
if (this.$fs.exists(packageName)) {
18-
packageName = path.resolve(packageName);
19-
}
20-
18+
packageName = this.getRealPackageName(packageName);
19+
this.$logger.trace(`Calling pacote.manifest for packageName: ${packageName} and options: ${JSON.stringify(manifestOptions, null, 2)}`);
2120
return pacote.manifest(packageName, manifestOptions);
2221
}
2322

2423
public async extractPackage(packageName: string, destinationDirectory: string, options?: IPacoteExtractOptions): Promise<void> {
2524
// strip: Remove the specified number of leading path elements. Pathnames with fewer elements will be silently skipped. More info: https://github.com/npm/node-tar/blob/e89c4d37519b1c20133a9f49d5f6b85fa34c203b/README.md
2625
// C: Create an archive
26+
this.$logger.trace(`Calling pacoteService.extractPackage for packageName: '${packageName}', destinationDir: '${destinationDirectory}' and options: ${options}`);
2727
const extractOptions = { strip: 1, C: destinationDirectory };
2828
if (options) {
2929
_.extend(extractOptions, options);
3030
}
3131

32-
if (this.$fs.exists(packageName)) {
33-
packageName = path.resolve(packageName);
34-
}
32+
packageName = this.getRealPackageName(packageName);
33+
const pacoteOptions = await this.getPacoteBaseOptions();
3534

36-
const cache = await this.$npm.getCachePath();
3735
return new Promise<void>((resolve, reject) => {
38-
const source = pacote.tarball.stream(packageName, { cache });
36+
this.$logger.trace(`Calling pacoteService.extractPackage for packageName: '${packageName}', destinationDir: '${destinationDirectory}' and options: ${options}`);
37+
38+
const source = pacote.tarball.stream(packageName, pacoteOptions);
3939
source.on("error", (err: Error) => {
40+
this.$logger.trace(`Error in source while trying to extract stream from ${packageName}. Error is ${err}`);
4041
reject(err);
4142
});
4243

44+
this.$logger.trace(`Creating extract tar stream with options: ${JSON.stringify(extractOptions, null, 2)}`);
4345
const destination = tar.x(extractOptions);
4446
source.pipe(destination);
4547

46-
destination.on("error", (err: Error) => reject(err));
47-
destination.on("finish", () => resolve());
48+
destination.on("error", (err: Error) => {
49+
this.$logger.trace(`Error in destination while trying to extract stream from ${packageName}. Error is ${err}`);
50+
reject(err);
51+
});
52+
53+
destination.on("finish", () => {
54+
this.$logger.trace(`Successfully extracted '${packageName}' to ${destinationDirectory}`);
55+
resolve();
56+
});
4857
});
4958
}
59+
60+
private async getPacoteBaseOptions(): Promise<IPacoteBaseOptions> {
61+
// In case `tns create myapp --template https://github.com/NativeScript/template-hello-world.git` command is executed, pacote module throws an error if cache option is not provided.
62+
const cache = await this.$npm.getCachePath();
63+
const pacoteOptions = { cache };
64+
const proxySettings = await this.$proxyService.getCache();
65+
if (proxySettings) {
66+
_.extend(pacoteOptions, proxySettings);
67+
}
68+
69+
return pacoteOptions;
70+
}
71+
72+
private getRealPackageName(packageName: string): string {
73+
if (this.$fs.exists(packageName)) {
74+
this.$logger.trace(`Will resolve the full path to package ${packageName}.`);
75+
packageName = path.resolve(packageName);
76+
}
77+
78+
return packageName;
79+
}
5080
}
5181
$injector.register("pacoteService", PacoteService);

test/project-service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ class ProjectIntegrationTest {
152152
executeAfterHooks: async (commandName: string, hookArguments?: IDictionary<any>): Promise<void> => undefined
153153
});
154154
this.testInjector.register("pacoteService", PacoteService);
155+
this.testInjector.register("proxyService", {
156+
getCache: async (): Promise<IProxySettings> => null
157+
});
155158
}
156159
}
157160

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ describe("iOSDebuggerPortService", () => {
157157
}
158158

159159
const promise = iOSDebuggerPortService.getPort({ deviceId: deviceId, appId: appId, projectDir: mockProjectDirObj.projectDir });
160-
clock.tick(10000);
160+
clock.tick(20000);
161161
const port = await promise;
162162
assert.deepEqual(port, testCase.emittedPort);
163163
});
@@ -171,7 +171,7 @@ describe("iOSDebuggerPortService", () => {
171171
}
172172

173173
const promise = iOSDebuggerPortService.getPort({ deviceId: deviceId, appId: appId, projectDir: mockProjectDirObj.projectDir });
174-
clock.tick(10000);
174+
clock.tick(20000);
175175
const port = await promise;
176176
assert.deepEqual(port, testCase.emittedPort);
177177
});

0 commit comments

Comments
 (0)