Skip to content

Commit 1dd099e

Browse files
committed
Merge pull request #53 from spicydonuts/catch-exceptions
Initial pass on catch rewriting; needs review!
2 parents 088ef5f + 09f6c37 commit 1dd099e

File tree

4 files changed

+83
-90
lines changed

4 files changed

+83
-90
lines changed

bower.json

+3
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@
2121
"purescript-exceptions": "^1.0.0",
2222
"purescript-functions": "^1.0.0",
2323
"purescript-transformers": "^1.0.0"
24+
},
25+
"devDependencies": {
26+
"purescript-partial": "^1.1.2"
2427
}
2528
}

src/Control/Monad/Aff.js

+53-85
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,13 @@ exports._cancelWith = function (nonCanceler, aff, canceler1) {
1616
result = result || bool;
1717

1818
if (cancellations === 2 && !errored) {
19-
try {
20-
success(result);
21-
} catch (err) {
22-
error(err);
23-
}
19+
success(result);
2420
}
2521
};
2622

2723
var f = function(err) {
2824
if (!errored) {
2925
errored = true;
30-
3126
error(err);
3227
}
3328
};
@@ -60,13 +55,7 @@ exports._setTimeout = function (nonCanceler, millis, aff) {
6055
return canceler(e)(s, f);
6156
} else {
6257
clear(timeout);
63-
64-
try {
65-
s(true);
66-
} catch (err) {
67-
f(err);
68-
}
69-
58+
s(true);
7059
return nonCanceler;
7160
}
7261
};
@@ -83,13 +72,7 @@ exports._forkAff = function (nonCanceler, aff) {
8372

8473
return function(success, error) {
8574
var canceler = aff(voidF, voidF);
86-
87-
try {
88-
success(canceler);
89-
} catch (err) {
90-
error(err);
91-
}
92-
75+
success(canceler);
9376
return nonCanceler;
9477
};
9578
}
@@ -98,12 +81,16 @@ exports._forkAll = function (nonCanceler, foldl, affs) {
9881
var voidF = function(){};
9982

10083
return function(success, error) {
101-
var cancelers = foldl(function(acc) {
102-
return function(aff) {
103-
acc.push(aff(voidF, voidF));
104-
return acc;
105-
}
106-
})([])(affs);
84+
try {
85+
var cancelers = foldl(function(acc) {
86+
return function(aff) {
87+
acc.push(aff(voidF, voidF));
88+
return acc;
89+
}
90+
})([])(affs);
91+
} catch (err) {
92+
error(err)
93+
}
10794

10895
var canceler = function(e) {
10996
return function(success, error) {
@@ -116,11 +103,7 @@ exports._forkAll = function (nonCanceler, foldl, affs) {
116103
result = result || bool;
117104

118105
if (cancellations === cancelers.length && !errored) {
119-
try {
120-
success(result);
121-
} catch (err) {
122-
error(err);
123-
}
106+
success(result);
124107
}
125108
};
126109

@@ -139,63 +122,57 @@ exports._forkAll = function (nonCanceler, foldl, affs) {
139122
};
140123
};
141124

142-
try {
143-
success(canceler);
144-
} catch (err) {
145-
error(err);
146-
}
147-
125+
success(canceler);
148126
return nonCanceler;
149127
};
150128
}
151129

152130
exports._makeAff = function (cb) {
153131
return function(success, error) {
154-
return cb(function(e) {
155-
return function() {
156-
error(e);
157-
};
158-
})(function(v) {
159-
return function() {
160-
try {
132+
try {
133+
return cb(function(e) {
134+
return function() {
135+
error(e);
136+
};
137+
})(function(v) {
138+
return function() {
161139
success(v);
162-
} catch (err) {
163-
error(err);
164-
}
165-
};
166-
})();
140+
};
141+
})();
142+
} catch (err) {
143+
error(err);
144+
}
167145
}
168146
}
169147

170148
exports._pure = function (nonCanceler, v) {
171149
return function(success, error) {
172-
try {
173-
success(v);
174-
} catch (err) {
175-
error(err);
176-
}
177-
150+
success(v);
178151
return nonCanceler;
179152
};
180153
}
181154

182155
exports._throwError = function (nonCanceler, e) {
183156
return function(success, error) {
184157
error(e);
185-
186158
return nonCanceler;
187159
};
188160
}
189161

190162
exports._fmap = function (f, aff) {
191163
return function(success, error) {
192-
return aff(function(v) {
193-
try {
194-
success(f(v));
195-
} catch (err) {
196-
error(err);
197-
}
198-
}, error);
164+
try {
165+
return aff(function(v) {
166+
try {
167+
var v2 = f(v);
168+
} catch (err) {
169+
error(err)
170+
}
171+
success(v2);
172+
}, error);
173+
} catch (err) {
174+
error(err);
175+
}
199176
};
200177
}
201178

@@ -231,11 +208,7 @@ exports._bind = function (alwaysCanceler, aff, f) {
231208
} else {
232209
return canceler1(e)(function(bool) {
233210
if (bool || isCanceled) {
234-
try {
235-
s(true);
236-
} catch (err) {
237-
f(err);
238-
}
211+
s(true);
239212
} else {
240213
onCanceler = function(canceler) {
241214
canceler(e)(s, f);
@@ -250,30 +223,22 @@ exports._bind = function (alwaysCanceler, aff, f) {
250223

251224
exports._attempt = function (Left, Right, aff) {
252225
return function(success, error) {
253-
return aff(function(v) {
254-
try {
226+
try {
227+
return aff(function(v) {
255228
success(Right(v));
256-
} catch (err) {
257-
error(err);
258-
}
259-
}, function(e) {
260-
try {
229+
}, function(e) {
261230
success(Left(e));
262-
} catch (err) {
263-
error(err);
264-
}
265-
});
231+
});
232+
} catch (err) {
233+
success(Left(err));
234+
}
266235
};
267236
}
268237

269238
exports._runAff = function (errorT, successT, aff) {
270239
return function() {
271240
return aff(function(v) {
272-
try {
273-
successT(v)();
274-
} catch (err) {
275-
errorT(err)();
276-
}
241+
successT(v)();
277242
}, function(e) {
278243
errorT(e)();
279244
});
@@ -282,12 +247,15 @@ exports._runAff = function (errorT, successT, aff) {
282247

283248
exports._liftEff = function (nonCanceler, e) {
284249
return function(success, error) {
250+
var result;
285251
try {
286-
success(e());
252+
result = e();
287253
} catch (err) {
288254
error(err);
255+
return nonCanceler;
289256
}
290257

258+
success(result);
291259
return nonCanceler;
292260
};
293261
}

test/Test/Main.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"use strict";
2+
3+
exports.synchronousUnexpectedThrowError = function() {
4+
throw new Error("ok");
5+
};

test/Test/Main.purs

+22-5
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@ import Prelude
44

55
import Control.Alt ((<|>))
66
import Control.Apply ((*>))
7-
import Control.Monad.Aff (Aff, runAff, later, later', forkAff, forkAll, Canceler(..), cancel, attempt, finally, apathize)
7+
import Control.Monad.Aff (Aff, runAff, makeAff, later, later', forkAff, forkAll, Canceler(..), cancel, attempt, finally, apathize)
88
import Control.Monad.Aff.AVar (AVAR, makeVar, makeVar', putVar, modifyVar, takeVar, killVar)
99
import Control.Monad.Aff.Console (log)
1010
import Control.Monad.Aff.Par (Par(..), runPar)
1111
import Control.Monad.Cont.Class (callCC)
1212
import Control.Monad.Eff (Eff)
1313
import Control.Monad.Eff.Console (CONSOLE)
14-
import Control.Monad.Eff.Exception (EXCEPTION, throwException, error)
14+
import Control.Monad.Eff.Exception (EXCEPTION, throwException, error, message)
1515
import Control.Monad.Error.Class (throwError)
1616
import Control.Monad.Rec.Class (tailRecM)
17-
18-
import Data.Either (Either(..), either)
17+
import Data.Either (Either(..), either, fromLeft, fromRight)
1918
import Data.Unfoldable (replicate)
19+
import Partial.Unsafe (unsafePartial)
2020

2121
type Test a = forall e. Aff (console :: CONSOLE | e) a
2222
type TestAVar a = forall e. Aff (console :: CONSOLE, avar :: AVAR | e) a
@@ -30,6 +30,21 @@ test_sequencing n = do
3030
later' 100 (log (show (n / 10) <> " seconds left"))
3131
test_sequencing (n - 1)
3232

33+
foreign import synchronousUnexpectedThrowError :: forall e. Eff e Unit
34+
35+
test_makeAff :: Test Unit
36+
test_makeAff = unsafePartial do
37+
s <- attempt $ makeAff \reject resolve -> resolve "ok"
38+
log $ "makeAff success is " <> fromRight s
39+
40+
asyncF <- attempt $ makeAff \reject resolve -> reject (error "ok")
41+
log $ "makeAff asynchronous failure is " <> message (fromLeft asyncF)
42+
43+
asyncF <- attempt $ makeAff \reject resolve -> synchronousUnexpectedThrowError
44+
log $ "makeAff synchronous failure is " <> message (fromLeft asyncF)
45+
46+
log "Success: makeAff is ok"
47+
3348
test_pure :: Test Unit
3449
test_pure = do
3550
pure unit
@@ -60,7 +75,6 @@ test_killFirstForked = do
6075
b <- c `cancel` (error "Just die")
6176
log (if b then "Success: Killed first forked" else "Failure: Couldn't kill first forked")
6277

63-
6478
test_killVar :: TestAVar Unit
6579
test_killVar = do
6680
v <- makeVar
@@ -180,6 +194,9 @@ main = runAff throwException (const (pure unit)) $ do
180194
log "Testing pure"
181195
test_pure
182196

197+
log "Testing makeAff"
198+
test_makeAff
199+
183200
log "Testing attempt"
184201
test_attempt
185202

0 commit comments

Comments
 (0)