14
14
module Node.ChildProcess
15
15
( Handle
16
16
, ChildProcess
17
+ , toEventEmitter
18
+ , closeH
19
+ , disconnectH
20
+ , errorH
21
+ , exitH
22
+ , messageH
23
+ , spawnH
17
24
, stdin
18
25
, stdout
19
26
, stderr
@@ -25,11 +32,6 @@ module Node.ChildProcess
25
32
, Error
26
33
, toStandardError
27
34
, Exit (..)
28
- , onExit
29
- , onClose
30
- , onDisconnect
31
- , onMessage
32
- , onError
33
35
, spawn
34
36
, SpawnOptions
35
37
, defaultSpawnOptions
@@ -51,31 +53,64 @@ module Node.ChildProcess
51
53
52
54
import Prelude
53
55
54
- import Control.Alt ((<|>))
55
56
import Data.Function.Uncurried (Fn2 , runFn2 )
56
57
import Data.Maybe (Maybe (..), fromMaybe , maybe )
57
- import Data.Nullable (Nullable , toNullable , toMaybe )
58
+ import Data.Nullable (Nullable , toMaybe , toNullable )
58
59
import Data.Posix (Pid , Gid , Uid )
59
60
import Data.Posix.Signal (Signal )
60
61
import Data.Posix.Signal as Signal
61
62
import Effect (Effect )
62
63
import Effect.Exception as Exception
63
- import Effect.Exception.Unsafe ( unsafeThrow )
64
+ import Effect.Uncurried ( EffectFn2 , mkEffectFn1 , mkEffectFn2 )
64
65
import Foreign (Foreign )
65
66
import Foreign.Object (Object )
66
67
import Node.Buffer (Buffer )
67
68
import Node.Encoding (Encoding , encodingToNode )
69
+ import Node.EventEmitter (EventEmitter , EventHandle (..))
70
+ import Node.EventEmitter.UtilTypes (EventHandle0 , EventHandle1 )
68
71
import Node.FS as FS
69
- import Node.Stream (Readable , Writable , Stream )
72
+ import Node.Stream (Readable , Stream , Writable )
73
+ import Partial.Unsafe (unsafeCrashWith )
70
74
import Unsafe.Coerce (unsafeCoerce )
71
75
72
76
-- | A handle for inter-process communication (IPC).
73
77
foreign import data Handle :: Type
74
78
75
79
-- | Opaque type returned by `spawn`, `fork` and `exec`.
76
80
-- | Needed as input for most methods in this module.
81
+ -- |
82
+ -- | `ChildProcess` extends `EventEmitter`
77
83
newtype ChildProcess = ChildProcess ChildProcessRec
78
84
85
+ toEventEmitter :: ChildProcess -> EventEmitter
86
+ toEventEmitter = unsafeCoerce
87
+
88
+ closeH :: EventHandle ChildProcess (Exit -> Effect Unit ) (EffectFn2 (Nullable Int ) (Nullable String ) Unit )
89
+ closeH = EventHandle " close" \cb -> mkEffectFn2 \code signal ->
90
+ case toMaybe code, toMaybe signal >>= Signal .fromString of
91
+ Just c, _ -> cb $ Normally c
92
+ _, Just s -> cb $ BySignal s
93
+ _, _ -> unsafeCrashWith $ " Impossible. 'close' event did not get an exit code or kill signal: " <> show code <> " ; " <> show signal
94
+
95
+ disconnectH :: EventHandle0 ChildProcess
96
+ disconnectH = EventHandle " disconnect" identity
97
+
98
+ errorH :: EventHandle1 ChildProcess Error
99
+ errorH = EventHandle " error" mkEffectFn1
100
+
101
+ exitH :: EventHandle ChildProcess (Exit -> Effect Unit ) (EffectFn2 (Nullable Int ) (Nullable String ) Unit )
102
+ exitH = EventHandle " exitH" \cb -> mkEffectFn2 \code signal ->
103
+ case toMaybe code, toMaybe signal >>= Signal .fromString of
104
+ Just c, _ -> cb $ Normally c
105
+ _, Just s -> cb $ BySignal s
106
+ _, _ -> unsafeCrashWith $ " Impossible. 'exit' event did not get an exit code or kill signal: " <> show code <> " ; " <> show signal
107
+
108
+ messageH :: EventHandle ChildProcess (Foreign -> Maybe Handle -> Effect Unit ) (EffectFn2 Foreign (Nullable Handle ) Unit )
109
+ messageH = EventHandle " message" \cb -> mkEffectFn2 \a b -> cb a $ toMaybe b
110
+
111
+ spawnH :: EventHandle0 ChildProcess
112
+ spawnH = EventHandle " spawn" identity
113
+
79
114
runChildProcess :: ChildProcess -> ChildProcessRec
80
115
runChildProcess (ChildProcess r) = r
81
116
@@ -165,68 +200,6 @@ instance showExit :: Show Exit where
165
200
show (Normally x) = " Normally " <> show x
166
201
show (BySignal sig) = " BySignal " <> show sig
167
202
168
- mkExit :: Nullable Int -> Nullable String -> Exit
169
- mkExit code signal =
170
- case fromCode code <|> fromSignal signal of
171
- Just e -> e
172
- Nothing -> unsafeThrow " Node.ChildProcess.mkExit: Invalid arguments"
173
- where
174
- fromCode = toMaybe >>> map Normally
175
- fromSignal = toMaybe >=> Signal .fromString >>> map BySignal
176
-
177
- -- | Handle the `"exit"` signal.
178
- onExit
179
- :: ChildProcess
180
- -> (Exit -> Effect Unit )
181
- -> Effect Unit
182
- onExit = mkOnExit mkExit
183
-
184
- foreign import mkOnExit
185
- :: (Nullable Int -> Nullable String -> Exit )
186
- -> ChildProcess
187
- -> (Exit -> Effect Unit )
188
- -> Effect Unit
189
-
190
- -- | Handle the `"close"` signal.
191
- onClose
192
- :: ChildProcess
193
- -> (Exit -> Effect Unit )
194
- -> Effect Unit
195
- onClose = mkOnClose mkExit
196
-
197
- foreign import mkOnClose
198
- :: (Nullable Int -> Nullable String -> Exit )
199
- -> ChildProcess
200
- -> (Exit -> Effect Unit )
201
- -> Effect Unit
202
-
203
- -- | Handle the `"message"` signal.
204
- onMessage
205
- :: ChildProcess
206
- -> (Foreign -> Maybe Handle -> Effect Unit )
207
- -> Effect Unit
208
- onMessage = mkOnMessage Nothing Just
209
-
210
- foreign import mkOnMessage
211
- :: forall a
212
- . Maybe a
213
- -> (a -> Maybe a )
214
- -> ChildProcess
215
- -> (Foreign -> Maybe Handle -> Effect Unit )
216
- -> Effect Unit
217
-
218
- -- | Handle the `"disconnect"` signal.
219
- foreign import onDisconnect
220
- :: ChildProcess
221
- -> Effect Unit
222
- -> Effect Unit
223
-
224
- -- | Handle the `"error"` signal.
225
- foreign import onError
226
- :: ChildProcess
227
- -> (Error -> Effect Unit )
228
- -> Effect Unit
229
-
230
203
-- | Spawn a child process. Note that, in the event that a child process could
231
204
-- | not be spawned (for example, if the executable was not found) this will
232
205
-- | not throw an error. Instead, the `ChildProcess` will be created anyway,
0 commit comments