@@ -81,7 +81,7 @@ export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements I
81
81
}
82
82
}
83
83
84
- public uninstallApplication ( deviceId : string , appIdentifier : string ) : Promise < void > {
84
+ public uninstallApplication ( deviceId : string , appIdentifier : string ) : Promise < void > {
85
85
return this . simctl . uninstall ( deviceId , appIdentifier , { skipError : true } ) ;
86
86
}
87
87
@@ -122,22 +122,63 @@ export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements I
122
122
}
123
123
124
124
public async getDeviceLogProcess ( deviceId : string , predicate ?: string ) : Promise < child_process . ChildProcess > {
125
- if ( ! this . isDeviceLogOperationStarted ) {
126
- const device = await this . getDeviceFromIdentifier ( deviceId ) ;
127
- const deviceVersion = device ? device . runtimeVersion : "" ;
128
- const majorVersion = deviceVersion . split ( "." ) [ 0 ] ;
125
+ const device = await this . getDeviceFromIdentifier ( deviceId ) ;
126
+ return new Promise < child_process . ChildProcess > ( ( resolve , reject ) => {
127
+ let timer : NodeJS . Timer ;
128
+ let isFulfilled = false ;
129
+
130
+ const fulfillSafe = ( data ?: Error | string ) => {
131
+ if ( ! isFulfilled ) {
132
+ isFulfilled = true ;
133
+ if ( data instanceof Error ) {
134
+ reject ( data ) ;
135
+ } else {
136
+ resolve ( this . deviceLogChildProcess ) ;
137
+ }
138
+ }
129
139
130
- if ( majorVersion && parseInt ( majorVersion ) >= 11 ) {
131
- this . deviceLogChildProcess = this . simctl . getLog ( deviceId , predicate ) ;
132
- } else {
133
- const logFilePath = path . join ( osenv . home ( ) , "Library" , "Logs" , "CoreSimulator" , deviceId , "system.log" ) ;
134
- this . deviceLogChildProcess = require ( "child_process" ) . spawn ( "tail" , [ '-f' , '-n' , '1' , logFilePath ] ) ;
135
- }
140
+ if ( timer ) {
141
+ clearTimeout ( timer ) ;
142
+ timer = null ;
143
+ }
136
144
137
- this . isDeviceLogOperationStarted = true ;
138
- }
145
+ if ( this . deviceLogChildProcess ) {
146
+ if ( this . deviceLogChildProcess . stdout ) {
147
+ this . deviceLogChildProcess . stdout . removeListener ( "data" , fulfillSafe ) ;
148
+ }
139
149
140
- return this . deviceLogChildProcess ;
150
+ this . deviceLogChildProcess . removeListener ( "error" , fulfillSafe ) ;
151
+ }
152
+ } ;
153
+
154
+ if ( ! this . isDeviceLogOperationStarted ) {
155
+ const deviceVersion = device ? device . runtimeVersion : "" ;
156
+ const majorVersion = deviceVersion . split ( "." ) [ 0 ] ;
157
+
158
+ if ( majorVersion && parseInt ( majorVersion ) >= 11 ) {
159
+ timer = setTimeout ( ( ) => {
160
+ fulfillSafe ( ) ;
161
+ } , 3000 ) ;
162
+
163
+ // For some reason starting the process takes a lot of time. So wait for the first message on stdout and resolve the promise at this point.
164
+ this . deviceLogChildProcess = this . simctl . getLog ( deviceId , predicate ) ;
165
+ if ( this . deviceLogChildProcess . stdout ) {
166
+ this . deviceLogChildProcess . stdout . once ( "data" , fulfillSafe ) ;
167
+ this . deviceLogChildProcess . once ( "error" , fulfillSafe ) ;
168
+ } else {
169
+ fulfillSafe ( ) ;
170
+ }
171
+ } else {
172
+ const logFilePath = path . join ( osenv . home ( ) , "Library" , "Logs" , "CoreSimulator" , deviceId , "system.log" ) ;
173
+ this . deviceLogChildProcess = childProcess . spawn ( "tail" , [ '-f' , '-n' , '1' , logFilePath ] ) ;
174
+ fulfillSafe ( ) ;
175
+ }
176
+
177
+ this . isDeviceLogOperationStarted = true ;
178
+ } else {
179
+ fulfillSafe ( ) ;
180
+ }
181
+ } ) ;
141
182
}
142
183
143
184
private async getDeviceToRun ( options : IOptions , device ?: any ) : Promise < IDevice > {
0 commit comments