1
1
///<reference path="./.d.ts"/>
2
2
"use strict" ;
3
3
4
- import child_process = require ( "child_process" ) ;
5
- import errors = require ( "./errors" ) ;
6
- import fs = require ( "fs" ) ;
4
+ import * as child_process from "child_process" ;
5
+ import * as errors from "./errors" ;
6
+ import * as fs from "fs" ;
7
7
import Future = require( "fibers/future" ) ;
8
- import options = require( "./options" ) ;
9
- import os = require( "os" ) ;
10
- import path = require( "path" ) ;
11
- import util = require( "util" ) ;
12
- import utils = require( "./utils" ) ;
13
-
14
- var $ = require ( "NodObjC" ) ;
8
+ import * as options from "./options" ;
9
+ import * as os from "os" ;
10
+ import * as path from "path" ;
11
+ import * as util from "util" ;
12
+ import * as utils from "./utils" ;
13
+ let $ = require ( "nodobjc" ) ;
15
14
16
15
export class IPhoneInteropSimulatorBase {
17
16
constructor ( private simulator : IInteropSimulator ) { }
@@ -30,9 +29,9 @@ export class IPhoneInteropSimulatorBase {
30
29
public run ( appPath : string ) : IFuture < void > {
31
30
return this . execute ( this . launch , { canRunMainLoop : true , appPath : appPath } ) ;
32
31
}
33
-
34
- private launch ( appPath : string ) : void {
35
- var sessionDelegate = $ . NSObject . extend ( "DTiPhoneSimulatorSessionDelegate" ) ;
32
+
33
+ private setupSessionDelegate ( appPath : string ) : any {
34
+ let sessionDelegate = $ . NSObject . extend ( "DTiPhoneSimulatorSessionDelegate" ) ;
36
35
sessionDelegate . addMethod ( "session:didEndWithError:" , "v@:@@" , function ( self : any , sel : any , sess : any , error : any ) {
37
36
IPhoneInteropSimulatorBase . logSessionInfo ( error , "Session ended without errors." , "Session ended with error " ) ;
38
37
process . exit ( 0 ) ;
@@ -41,73 +40,87 @@ export class IPhoneInteropSimulatorBase {
41
40
IPhoneInteropSimulatorBase . logSessionInfo ( error , "Session started without errors." , "Session started with error " ) ;
42
41
43
42
console . log ( `${ appPath } : ${ session ( "simulatedApplicationPID" ) } ` ) ;
44
- if ( options . exit ) {
43
+ if ( options . exit ) {
45
44
process . exit ( 0 ) ;
46
45
}
47
46
} ) ;
48
47
sessionDelegate . register ( ) ;
48
+
49
+ return sessionDelegate ;
50
+ }
51
+
52
+ private getTimeout ( ) : number {
53
+ let timeoutParam = IPhoneInteropSimulatorBase . DEFAULT_TIMEOUT_IN_SECONDS ;
54
+ if ( options . timeout || options . timeout === 0 ) {
55
+ let parsedValue = parseInt ( options . timeout ) ;
56
+ if ( ! isNaN ( parsedValue ) && parsedValue > 0 ) {
57
+ timeoutParam = parsedValue ;
58
+ }
59
+ else {
60
+ console . log ( `Specify the timeout in number of seconds to wait. It should be greater than 0. Default value ${ IPhoneInteropSimulatorBase . DEFAULT_TIMEOUT_IN_SECONDS } seconds will be used.` ) ;
61
+ }
62
+ }
63
+ return timeoutParam ;
64
+ }
65
+
66
+ private validateDevice ( ) {
67
+ if ( options . device ) {
68
+ let devices = this . simulator . getDevices ( ) . wait ( ) ;
69
+ let validDeviceIdentifiers = _ . map ( devices , device => device . id ) ;
70
+ if ( ! _ . contains ( validDeviceIdentifiers , options . device ) ) {
71
+ errors . fail ( "Invalid device identifier %s. Valid device identifiers are %s." , options . device , utils . stringify ( validDeviceIdentifiers ) ) ;
72
+ }
73
+ }
74
+ }
49
75
50
- var appSpec = this . getClassByName ( "DTiPhoneSimulatorApplicationSpecifier" ) ( "specifierWithApplicationPath" , $ ( appPath ) ) ;
51
- var config = this . getClassByName ( "DTiPhoneSimulatorSessionConfig" ) ( "alloc" ) ( "init" ) ( "autorelease" ) ;
76
+ private launch ( appPath : string ) : void {
77
+ let sessionDelegate = this . setupSessionDelegate ( appPath ) ;
78
+
79
+ let appSpec = this . getClassByName ( "DTiPhoneSimulatorApplicationSpecifier" ) ( "specifierWithApplicationPath" , $ ( appPath ) ) ;
80
+ let config = this . getClassByName ( "DTiPhoneSimulatorSessionConfig" ) ( "alloc" ) ( "init" ) ( "autorelease" ) ;
52
81
config ( "setApplicationToSimulateOnStart" , appSpec ) ;
53
82
config ( "setSimulatedApplicationShouldWaitForDebugger" , options . waitForDebugger ) ;
54
83
55
- var sdkRoot = options . sdkVersion ? $ ( this . getSdkRootPathByVersion ( options . sdkVersion ) ) : this . getClassByName ( "DTiPhoneSimulatorSystemRoot" ) ( "defaultRoot" ) ;
84
+ let sdkRoot = options . sdkVersion ? $ ( this . getSdkRootPathByVersion ( options . sdkVersion ) ) : this . getClassByName ( "DTiPhoneSimulatorSystemRoot" ) ( "defaultRoot" ) ;
56
85
config ( "setSimulatedSystemRoot" , sdkRoot ) ;
57
86
58
- var simulator = this . simulator ;
59
- if ( options . device ) {
60
- let devices = simulator . getDevices ( ) . wait ( ) ;
61
- var validDeviceIdentifiers = _ . map ( devices , device => device . id ) ;
62
- if ( ! _ . contains ( validDeviceIdentifiers , options . device ) ) {
63
- errors . fail ( "Invalid device identifier %s. Valid device identifiers are %s." , options . device , utils . stringify ( validDeviceIdentifiers ) ) ;
64
- }
65
- }
66
- simulator . setSimulatedDevice ( config ) ;
87
+ this . validateDevice ( ) ;
88
+ this . simulator . setSimulatedDevice ( config ) ;
67
89
68
- if ( options . logging ) {
69
- var logPath = this . createLogPipe ( appPath ) . wait ( ) ;
90
+ if ( options . logging ) {
91
+ let logPath = this . createLogPipe ( appPath ) . wait ( ) ;
70
92
fs . createReadStream ( logPath , { encoding : "utf8" } ) . pipe ( process . stdout ) ;
71
93
config ( "setSimulatedApplicationStdErrPath" , $ ( logPath ) ) ;
72
94
config ( "setSimulatedApplicationStdOutPath" , $ ( logPath ) ) ;
73
95
} else {
74
- if ( options . stderr ) {
96
+ if ( options . stderr ) {
75
97
config ( "setSimulatedApplicationStdErrPath" , $ ( options . stderr ) ) ;
76
98
}
77
- if ( options . stdout ) {
99
+ if ( options . stdout ) {
78
100
config ( "setSimulatedApplicationStdOutPath" , $ ( options . stdout ) ) ;
79
101
}
80
102
}
81
103
82
104
if ( options . args ) {
83
- var args = options . args . trim ( ) . split ( / \s + / ) ;
84
- var nsArgs = $ . NSMutableArray ( "array" ) ;
105
+ let args = options . args . trim ( ) . split ( / \s + / ) ;
106
+ let nsArgs = $ . NSMutableArray ( "array" ) ;
85
107
args . forEach ( ( x : string ) => nsArgs ( "addObject" , $ ( x ) ) ) ;
86
108
config ( "setSimulatedApplicationLaunchArgs" , nsArgs ) ;
87
109
}
88
110
89
111
config ( "setLocalizedClientName" , $ ( "ios-sim-portable" ) ) ;
90
112
91
- var sessionError : any = new Buffer ( "" ) ;
92
- var timeoutParam = IPhoneInteropSimulatorBase . DEFAULT_TIMEOUT_IN_SECONDS ;
93
- if ( options . timeout || options . timeout === 0 ) {
94
- var parsedValue = parseInt ( options . timeout ) ;
95
- if ( ! isNaN ( parsedValue ) && parsedValue > 0 ) {
96
- timeoutParam = parsedValue ;
97
- }
98
- else {
99
- console . log ( util . format ( "Specify the timeout in number of seconds to wait. It should be greater than 0. Default value %s seconds will be used." , IPhoneInteropSimulatorBase . DEFAULT_TIMEOUT_IN_SECONDS . toString ( ) ) ) ;
100
- }
101
- }
113
+ let sessionError : any = new Buffer ( "" ) ;
114
+ let timeoutParam = this . getTimeout ( ) ;
102
115
103
- var time = $ . NSNumber ( "numberWithDouble" , timeoutParam ) ;
104
- var timeout = time ( "doubleValue" ) ;
116
+ let time = $ . NSNumber ( "numberWithDouble" , timeoutParam ) ;
117
+ let timeout = time ( "doubleValue" ) ;
105
118
106
- var session = this . getClassByName ( "DTiPhoneSimulatorSession" ) ( "alloc" ) ( "init" ) ( "autorelease" ) ;
107
- var delegate = sessionDelegate ( "alloc" ) ( "init" ) ;
119
+ let session = this . getClassByName ( "DTiPhoneSimulatorSession" ) ( "alloc" ) ( "init" ) ( "autorelease" ) ;
120
+ let delegate = sessionDelegate ( "alloc" ) ( "init" ) ;
108
121
session ( "setDelegate" , delegate ) ;
109
122
110
- if ( ! session ( "requestStartWithConfig" , config , "timeout" , timeout , "error" , sessionError ) ) {
123
+ if ( ! session ( "requestStartWithConfig" , config , "timeout" , timeout , "error" , sessionError ) ) {
111
124
errors . fail ( "Could not start simulator session " , sessionError ) ;
112
125
}
113
126
}
@@ -116,19 +129,22 @@ export class IPhoneInteropSimulatorBase {
116
129
$ . importFramework ( IPhoneInteropSimulatorBase . FOUNDATION_FRAMEWORK_NAME ) ;
117
130
$ . importFramework ( IPhoneInteropSimulatorBase . APPKIT_FRAMEWORK_NAME ) ;
118
131
119
- var pool = $ . NSAutoreleasePool ( "alloc" ) ( "init" ) ;
120
-
121
- var developerDirectoryPath = this . findDeveloperDirectory ( ) . wait ( ) ;
132
+ let developerDirectoryPath = this . findDeveloperDirectory ( ) . wait ( ) ;
122
133
if ( ! developerDirectoryPath ) {
123
134
errors . fail ( "Unable to find developer directory" ) ;
124
135
}
125
136
126
137
this . loadFrameworks ( developerDirectoryPath ) ;
127
138
128
139
let result = action . apply ( this , [ opts . appPath ] ) ;
129
-
130
- var future = new Future < any > ( ) ;
131
- if ( opts . canRunMainLoop ) {
140
+ return this . runCFLoop ( opts . canRunMainLoop , result ) ;
141
+ }
142
+
143
+ private runCFLoop ( canRunMainLoop : boolean , result : any ) : IFuture < any > {
144
+ let pool = $ . NSAutoreleasePool ( "alloc" ) ( "init" ) ;
145
+ let future = new Future < any > ( ) ;
146
+
147
+ if ( canRunMainLoop ) {
132
148
// Keeps the Node loop running
133
149
( function runLoop ( ) {
134
150
if ( $ . CFRunLoopRunInMode ( $ . kCFRunLoopDefaultMode , 0.1 , false ) ) {
@@ -141,6 +157,7 @@ export class IPhoneInteropSimulatorBase {
141
157
} else {
142
158
future . return ( result ) ;
143
159
}
160
+
144
161
return future ;
145
162
}
146
163
@@ -152,48 +169,48 @@ export class IPhoneInteropSimulatorBase {
152
169
this . loadFramework ( path . join ( developerDirectoryPath , IPhoneInteropSimulatorBase . CORE_SIMULATOR_RELATIVE_PATH ) ) ;
153
170
}
154
171
155
- var platformsError : string = null ;
156
- var dvtPlatformClass = this . getClassByName ( "DVTPlatform" ) ;
172
+ let platformsError : string = null ;
173
+ let dvtPlatformClass = this . getClassByName ( "DVTPlatform" ) ;
157
174
if ( ! dvtPlatformClass ( "loadAllPlatformsReturningError" , platformsError ) ) {
158
175
errors . fail ( "Unable to loadAllPlatformsReturningError " , platformsError ) ;
159
176
}
160
177
161
- var simulatorFrameworkPath = path . join ( developerDirectoryPath , IPhoneInteropSimulatorBase . SIMULATOR_FRAMEWORK_RELATIVE_PATH_LEGACY ) ;
178
+ let simulatorFrameworkPath = path . join ( developerDirectoryPath , IPhoneInteropSimulatorBase . SIMULATOR_FRAMEWORK_RELATIVE_PATH_LEGACY ) ;
162
179
if ( ! fs . existsSync ( simulatorFrameworkPath ) ) {
163
180
simulatorFrameworkPath = path . join ( developerDirectoryPath , IPhoneInteropSimulatorBase . SIMULATOR_FRAMEWORK_RELATIVE_PATH ) ;
164
181
}
165
182
this . loadFramework ( simulatorFrameworkPath ) ;
166
183
}
167
184
168
185
private loadFramework ( frameworkPath : string ) {
169
- var bundle = $ . NSBundle ( "bundleWithPath" , $ ( frameworkPath ) ) ;
186
+ let bundle = $ . NSBundle ( "bundleWithPath" , $ ( frameworkPath ) ) ;
170
187
if ( ! bundle ( "load" ) ) {
171
188
errors . fail ( "Unable to load " , frameworkPath ) ;
172
189
}
173
190
}
174
191
175
192
private findDeveloperDirectory ( ) : IFuture < string > {
176
- var future = new Future < string > ( ) ;
177
- var capturedOut = "" ;
178
- var capturedErr = "" ;
193
+ let future = new Future < string > ( ) ;
194
+ let capturedOut = "" ;
195
+ let capturedErr = "" ;
179
196
180
- var childProcess = child_process . spawn ( "xcode-select" , [ "-print-path" ] ) ;
197
+ let childProcess = child_process . spawn ( "xcode-select" , [ "-print-path" ] ) ;
181
198
182
- if ( childProcess . stdout ) {
199
+ if ( childProcess . stdout ) {
183
200
childProcess . stdout . on ( "data" , ( data : string ) => {
184
201
capturedOut += data ;
185
202
} ) ;
186
203
}
187
204
188
- if ( childProcess . stderr ) {
205
+ if ( childProcess . stderr ) {
189
206
childProcess . stderr . on ( "data" , ( data : string ) => {
190
207
capturedErr += data ;
191
208
} ) ;
192
209
}
193
210
194
211
childProcess . on ( "close" , ( arg : any ) => {
195
- var exitCode = typeof arg == 'number' ? arg : arg && arg . code ;
196
- if ( exitCode === 0 ) {
212
+ let exitCode = typeof arg == 'number' ? arg : arg && arg . code ;
213
+ if ( exitCode === 0 ) {
197
214
future . return ( capturedOut ? capturedOut . trim ( ) : null ) ;
198
215
} else {
199
216
future . throw ( util . format ( "Command xcode-select -print-path failed with exit code %s. Error output: \n %s" , exitCode , capturedErr ) ) ;
@@ -217,27 +234,27 @@ export class IPhoneInteropSimulatorBase {
217
234
}
218
235
219
236
private getSdkRootPathByVersion ( version : string ) : string {
220
- var sdks = this . getInstalledSdks ( ) ;
221
- var sdk = _ . find ( sdks , sdk => sdk . version === version ) ;
222
- if ( ! sdk ) {
237
+ let sdks = this . getInstalledSdks ( ) ;
238
+ let sdk = _ . find ( sdks , sdk => sdk . version === version ) ;
239
+ if ( ! sdk ) {
223
240
errors . fail ( "Unable to find installed sdk with version %s. Verify that you have specified correct version and the sdk with that version is installed." , version ) ;
224
241
}
225
242
226
243
return sdk . rootPath ;
227
244
}
228
245
229
246
private getInstalledSdks ( ) : ISdk [ ] {
230
- var systemRootClass = this . getClassByName ( "DTiPhoneSimulatorSystemRoot" ) ;
231
- var roots = systemRootClass ( "knownRoots" ) ;
232
- var count = roots ( "count" ) ;
247
+ let systemRootClass = this . getClassByName ( "DTiPhoneSimulatorSystemRoot" ) ;
248
+ let roots = systemRootClass ( "knownRoots" ) ;
249
+ let count = roots ( "count" ) ;
233
250
234
- var sdks : ISdk [ ] = [ ] ;
235
- for ( var index = 0 ; index < count ; index ++ ) {
236
- var root = roots ( "objectAtIndex" , index ) ;
251
+ let sdks : ISdk [ ] = [ ] ;
252
+ for ( let index = 0 ; index < count ; index ++ ) {
253
+ let root = roots ( "objectAtIndex" , index ) ;
237
254
238
- var displayName = root ( "sdkDisplayName" ) . toString ( ) ;
239
- var version = root ( "sdkVersion" ) . toString ( ) ;
240
- var rootPath = root ( "sdkRootPath" ) . toString ( ) ;
255
+ let displayName = root ( "sdkDisplayName" ) . toString ( ) ;
256
+ let version = root ( "sdkVersion" ) . toString ( ) ;
257
+ let rootPath = root ( "sdkRootPath" ) . toString ( ) ;
241
258
242
259
sdks . push ( new Sdk ( displayName , version , rootPath ) ) ;
243
260
}
@@ -246,10 +263,10 @@ export class IPhoneInteropSimulatorBase {
246
263
}
247
264
248
265
private createLogPipe ( appPath : string ) : IFuture < string > {
249
- var future = new Future < string > ( ) ;
250
- var logPath = path . join ( path . dirname ( appPath ) , "." + path . basename ( appPath , ".app" ) + ".log" ) ;
266
+ let future = new Future < string > ( ) ;
267
+ let logPath = path . join ( path . dirname ( appPath ) , "." + path . basename ( appPath , ".app" ) + ".log" ) ;
251
268
252
- var command = util . format ( "rm -f \"%s\" && mkfifo \"%s\"" , logPath , logPath ) ;
269
+ let command = util . format ( "rm -f \"%s\" && mkfifo \"%s\"" , logPath , logPath ) ;
253
270
child_process . exec ( command , ( error : Error , stdout : NodeBuffer , stderr : NodeBuffer ) => {
254
271
if ( error ) {
255
272
future . throw ( error ) ;
@@ -272,4 +289,4 @@ class Sdk implements ISdk {
272
289
util . format ( " Version: %s" , this . version ) ,
273
290
util . format ( " Root path: %s" , this . rootPath ) ] . join ( os . EOL ) ;
274
291
}
275
- }
292
+ }
0 commit comments