@@ -14,25 +14,69 @@ See the License for the specific language governing permissions and
1414limitations under the License.
1515*/
1616
17- import { ObservableValue , BaseObservableValue } from "../observable/ObservableValue" ;
17+ export const ErrorValue = Symbol ( "ErrorBoundary:Error" ) ;
1818
1919export class ErrorBoundary {
20+ private _error ?: Error ;
21+
2022 constructor ( private readonly errorCallback : ( Error ) => void ) { }
2123
22- try < T > ( callback : ( ) => T ) : T | undefined ;
23- try < T > ( callback : ( ) => Promise < T > ) : Promise < T | undefined > | undefined {
24+ /**
25+ * Executes callback() and then runs errorCallback() on error.
26+ * This will never throw but instead return `errorValue` if an error occured.
27+ */
28+ try < T > ( callback : ( ) => T ) : T | typeof ErrorValue ;
29+ try < T > ( callback : ( ) => Promise < T > ) : Promise < T | typeof ErrorValue > | typeof ErrorValue {
2430 try {
25- let result : T | Promise < T | undefined > = callback ( ) ;
31+ let result : T | Promise < T | typeof ErrorValue > = callback ( ) ;
2632 if ( result instanceof Promise ) {
2733 result = result . catch ( err => {
34+ this . _error = err ;
2835 this . errorCallback ( err ) ;
29- return undefined ;
36+ return ErrorValue ;
3037 } ) ;
3138 }
3239 return result ;
3340 } catch ( err ) {
41+ this . _error = err ;
3442 this . errorCallback ( err ) ;
35- return undefined ;
43+ return ErrorValue ;
3644 }
3745 }
46+
47+ get error ( ) : Error | undefined {
48+ return this . _error ;
49+ }
3850}
51+
52+ export function tests ( ) {
53+ return {
54+ "catches sync error" : assert => {
55+ let emitted = false ;
56+ const boundary = new ErrorBoundary ( ( ) => emitted = true ) ;
57+ const result = boundary . try ( ( ) => {
58+ throw new Error ( "fail!" ) ;
59+ } ) ;
60+ assert ( emitted ) ;
61+ assert . strictEqual ( result , ErrorValue ) ;
62+ } ,
63+ "return value of callback is forwarded" : assert => {
64+ let emitted = false ;
65+ const boundary = new ErrorBoundary ( ( ) => emitted = true ) ;
66+ const result = boundary . try ( ( ) => {
67+ return "hello" ;
68+ } ) ;
69+ assert ( ! emitted ) ;
70+ assert . strictEqual ( result , "hello" ) ;
71+ } ,
72+ "catches async error" : async assert => {
73+ let emitted = false ;
74+ const boundary = new ErrorBoundary ( ( ) => emitted = true ) ;
75+ const result = await boundary . try ( async ( ) => {
76+ throw new Error ( "fail!" ) ;
77+ } ) ;
78+ assert ( emitted ) ;
79+ assert . strictEqual ( result , ErrorValue ) ;
80+ }
81+ }
82+ }
0 commit comments