1
- import { DeviceLiveSyncServiceBase } from "./device-livesync-service-base" ;
2
1
import * as helpers from "../../common/helpers" ;
3
2
import * as net from "net" ;
4
3
5
4
let currentPageReloadId = 0 ;
6
5
7
- class IOSLiveSyncService extends DeviceLiveSyncServiceBase < Mobile . IiOSDevice > implements IDeviceLiveSyncService {
6
+ class IOSLiveSyncService implements IDeviceLiveSyncService {
8
7
private static BACKEND_PORT = 18181 ;
9
8
private socket : net . Socket ;
9
+ private device : Mobile . IiOSDevice ;
10
10
11
11
constructor ( _device : Mobile . IDevice ,
12
12
private $iOSSocketRequestExecutor : IiOSSocketRequestExecutor ,
@@ -17,8 +17,9 @@ class IOSLiveSyncService extends DeviceLiveSyncServiceBase<Mobile.IiOSDevice> im
17
17
private $options : IOptions ,
18
18
private $iOSDebugService : IDebugService ,
19
19
private $childProcess : IChildProcess ,
20
- $liveSyncProvider : ILiveSyncProvider ) {
21
- super ( _device , $liveSyncProvider ) ;
20
+ private $fs : IFileSystem ,
21
+ private $liveSyncProvider : ILiveSyncProvider ) {
22
+ this . device = < Mobile . IiOSDevice > ( _device ) ;
22
23
}
23
24
24
25
public get debugService ( ) : IDebugService {
@@ -31,78 +32,140 @@ class IOSLiveSyncService extends DeviceLiveSyncServiceBase<Mobile.IiOSDevice> im
31
32
} ) . future < boolean > ( ) ( ) ;
32
33
}
33
34
35
+ private setupSocketIfNeeded ( ) : IFuture < boolean > {
36
+ return ( ( ) => {
37
+ if ( this . socket ) {
38
+ return true ;
39
+ }
40
+
41
+ let enableDebuggerMessage = `{ "method":"Debugger.enable","id":${ ++ currentPageReloadId } }` ;
42
+ if ( this . device . isEmulator ) {
43
+ this . $iOSEmulatorServices . postDarwinNotification ( this . $iOSNotification . attachRequest ) . wait ( ) ;
44
+ try {
45
+ this . socket = helpers . connectEventuallyUntilTimeout ( ( ) => net . connect ( IOSLiveSyncService . BACKEND_PORT ) , 5000 ) . wait ( ) ;
46
+ } catch ( e ) {
47
+ this . $logger . warn ( e ) ;
48
+
49
+ return false ;
50
+ }
51
+ } else {
52
+ let timeout = 9000 ;
53
+ this . $iOSSocketRequestExecutor . executeAttachRequest ( this . device , timeout ) . wait ( ) ;
54
+ this . socket = this . device . connectToPort ( IOSLiveSyncService . BACKEND_PORT ) ;
55
+ }
56
+
57
+ this . attachEventHandlers ( ) ;
58
+ this . sendMessage ( enableDebuggerMessage ) ;
59
+
60
+ return true ;
61
+ } ) . future < boolean > ( ) ( ) ;
62
+ }
63
+
34
64
public removeFiles ( appIdentifier : string , localToDevicePaths : Mobile . ILocalToDevicePathData [ ] ) : IFuture < void > {
35
65
return ( ( ) => {
36
66
_ . each ( localToDevicePaths , localToDevicePathData => this . device . fileSystem . deleteFile ( localToDevicePathData . getDevicePath ( ) , appIdentifier ) ) ;
37
67
} ) . future < void > ( ) ( ) ;
38
68
}
39
69
40
- protected restartApplication ( deviceAppData : Mobile . IDeviceAppData ) : IFuture < void > {
70
+ public refreshApplication ( deviceAppData : Mobile . IDeviceAppData , localToDevicePaths : Mobile . ILocalToDevicePathData [ ] , forceExecuteFullSync : boolean ) : IFuture < void > {
71
+ return ( ( ) => {
72
+ if ( forceExecuteFullSync ) {
73
+ this . restartApplication ( deviceAppData ) . wait ( ) ;
74
+ return ;
75
+ }
76
+ let scriptFiles = _ . filter ( localToDevicePaths , localToDevicePath => _ . endsWith ( localToDevicePath . getDevicePath ( ) , ".js" ) ) ;
77
+ let otherFiles = _ . difference ( localToDevicePaths , scriptFiles ) ;
78
+ let shouldRestart = _ . some ( otherFiles , ( localToDevicePath : Mobile . ILocalToDevicePathData ) => ! this . $liveSyncProvider . canExecuteFastSync ( localToDevicePath . getLocalPath ( ) , deviceAppData . platform ) ) ;
79
+
80
+ if ( shouldRestart ) {
81
+ this . restartApplication ( deviceAppData ) . wait ( ) ;
82
+
83
+ return ;
84
+ }
85
+
86
+ if ( ! this . $options . liveEdit && scriptFiles . length ) {
87
+ this . restartApplication ( deviceAppData ) . wait ( ) ;
88
+
89
+ return ;
90
+ }
91
+
92
+ if ( this . setupSocketIfNeeded ( ) . wait ( ) ) {
93
+ this . liveEdit ( scriptFiles ) ;
94
+ this . reloadPage ( deviceAppData , otherFiles ) . wait ( ) ;
95
+ }
96
+ } ) . future < void > ( ) ( ) ;
97
+ }
98
+
99
+ private restartApplication ( deviceAppData : Mobile . IDeviceAppData ) : IFuture < void > {
41
100
let projectData : IProjectData = this . $injector . resolve ( "projectData" ) ;
42
101
return this . device . applicationManager . restartApplication ( deviceAppData . appIdentifier , projectData . projectName ) ;
43
102
}
44
103
45
- protected reloadPage ( deviceAppData : Mobile . IDeviceAppData ) : IFuture < void > {
104
+ private reloadPage ( deviceAppData : Mobile . IDeviceAppData , localToDevicePaths : Mobile . ILocalToDevicePathData [ ] ) : IFuture < void > {
46
105
return ( ( ) => {
47
- let timeout = 9000 ;
48
- if ( this . device . isEmulator ) {
49
- if ( ! this . socket ) {
50
- helpers . connectEventually ( ( ) => net . connect ( IOSLiveSyncService . BACKEND_PORT ) , ( socket : net . Socket ) => {
51
- this . socket = socket ;
52
- this . attachEventHandlersIfNecessary ( ) ;
53
- this . sendPageReloadMessage ( ) ;
54
- } ) ;
55
- } else {
56
- this . sendPageReloadMessage ( ) ;
57
- }
58
- this . $iOSEmulatorServices . postDarwinNotification ( this . $iOSNotification . attachRequest ) . wait ( ) ;
59
- } else {
60
- if ( ! this . socket ) {
61
- this . $iOSSocketRequestExecutor . executeAttachRequest ( this . device , timeout ) . wait ( ) ;
62
- this . socket = this . device . connectToPort ( IOSLiveSyncService . BACKEND_PORT ) ;
63
- this . attachEventHandlersIfNecessary ( ) ;
64
- }
65
- this . sendPageReloadMessage ( ) ;
106
+ if ( localToDevicePaths . length ) {
107
+ let message = JSON . stringify ( {
108
+ method : "Page.reload" ,
109
+ params : {
110
+ ignoreCache : false
111
+ } ,
112
+ id : ++ currentPageReloadId
113
+ } ) ;
114
+
115
+ this . sendMessage ( message ) ;
66
116
}
67
117
} ) . future < void > ( ) ( ) ;
68
118
}
69
119
70
- private attachEventHandlersIfNecessary ( ) : void {
71
- if ( this . $options . watch ) {
72
- this . attachProcessExitHandlers ( ) ;
73
- this . attachSocketCloseEvent ( ) ;
74
- }
120
+ private liveEdit ( localToDevicePaths : Mobile . ILocalToDevicePathData [ ] ) {
121
+ return ( ( ) => {
122
+ _ . each ( localToDevicePaths , localToDevicePath => {
123
+ let content = this . $fs . readFile ( localToDevicePath . getLocalPath ( ) ) . wait ( ) . toString ( ) ;
124
+ let message = JSON . stringify ( {
125
+ method : "Debugger.setScriptSource" ,
126
+ params : {
127
+ scriptUrl : localToDevicePath . getDevicePath ( ) ,
128
+ scriptSource : content
129
+ } ,
130
+ id : ++ currentPageReloadId
131
+ } ) ;
132
+
133
+ this . sendMessage ( message ) ;
134
+ } ) ;
135
+ } ) . future < void > ( ) ( ) ;
75
136
}
76
137
77
- private attachSocketCloseEvent ( ) : void {
138
+ private attachEventHandlers ( ) : void {
139
+ this . attachProcessExitHandlers ( ) ;
140
+
78
141
this . socket . on ( "close" , ( hadError : boolean ) => {
79
142
this . $logger . trace ( `Socket closed, hadError is ${ hadError } .` ) ;
80
143
this . socket = null ;
81
144
} ) ;
145
+
146
+ this . socket . on ( "error" , ( error : any ) => {
147
+ this . $logger . trace ( `Socket error received: ${ error } ` ) ;
148
+ } ) ;
149
+
150
+ this . socket . on ( "data" , ( data : NodeBuffer | string ) => {
151
+ this . $logger . trace ( `Socket sent data: ${ data . toString ( ) } ` ) ;
152
+ } ) ;
82
153
}
83
154
84
- private sendPageReloadMessage ( ) : void {
155
+ private sendMessage ( message : string ) : void {
85
156
try {
86
- this . sendPageReloadMessageCore ( ) ;
87
- this . socket . on ( "data" , ( data : NodeBuffer | string ) => {
88
- this . $logger . trace ( `Socket sent data: ${ data . toString ( ) } ` ) ;
89
- this . destroySocketIfNecessary ( ) ;
90
- } ) ;
157
+ let length = Buffer . byteLength ( message , "utf16le" ) ;
158
+ let payload = new Buffer ( length + 4 ) ;
159
+ payload . writeInt32BE ( length , 0 ) ;
160
+ payload . write ( message , 4 , length , "utf16le" ) ;
161
+
162
+ this . socket . write ( payload ) ;
91
163
} catch ( err ) {
92
164
this . $logger . trace ( "Error while sending page reload:" , err ) ;
93
- this . destroySocketIfNecessary ( ) ;
165
+ this . destroySocket ( ) ;
94
166
}
95
167
}
96
168
97
- private sendPageReloadMessageCore ( ) : void {
98
- let message = `{ "method":"Page.reload","params":{"ignoreCache":false},"id":${ ++ currentPageReloadId } }` ;
99
- let length = Buffer . byteLength ( message , "utf16le" ) ;
100
- let payload = new Buffer ( length + 4 ) ;
101
- payload . writeInt32BE ( length , 0 ) ;
102
- payload . write ( message , 4 , length , "utf16le" ) ;
103
- this . socket . write ( payload ) ;
104
- }
105
-
106
169
private attachProcessExitHandlers ( ) : void {
107
170
process . on ( "exit" , ( exitCode : number ) => {
108
171
this . destroySocket ( ) ;
@@ -118,12 +181,6 @@ class IOSLiveSyncService extends DeviceLiveSyncServiceBase<Mobile.IiOSDevice> im
118
181
} ) ;
119
182
}
120
183
121
- private destroySocketIfNecessary ( ) : void {
122
- if ( ! this . $options . watch ) {
123
- this . destroySocket ( ) ;
124
- }
125
- }
126
-
127
184
private destroySocket ( ) : void {
128
185
if ( this . socket ) {
129
186
this . socket . destroy ( ) ;
0 commit comments