Skip to content

Commit 9f85f1e

Browse files
motiz88facebook-github-bot
authored andcommitted
Type ErrorUtils (error-guard.js)
Summary: * Adds Flow types to `error-guard.js` and propagates them via the `ErrorUtils` module. * Fixes some call sites to account for the stricter (correct) types. Differential Revision: D16619538 fbshipit-source-id: c006ff2736ec380763956c4b89702cf44dd4deb0
1 parent 32c7e3a commit 9f85f1e

5 files changed

Lines changed: 59 additions & 34 deletions

File tree

.flowconfig

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111
; Ignore "BUCK" generated dirs
1212
<PROJECT_ROOT>/\.buckd/
1313

14-
; Ignore polyfills
15-
.*/Libraries/polyfills/.*
16-
1714
; These should not be required directly
1815
; require from fbjs/lib instead: require('fbjs/lib/warning')
1916
.*/node_modules/warning/.*

.flowconfig.android

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111
; Ignore "BUCK" generated dirs
1212
<PROJECT_ROOT>/\.buckd/
1313

14-
; Ignore polyfills
15-
.*/Libraries/polyfills/.*
16-
1714
; These should not be required directly
1815
; require from fbjs/lib instead: require('fbjs/lib/warning')
1916
.*/node_modules/warning/.*

Libraries/Core/ExceptionsManager.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,18 @@ declare var console: typeof console & {
9999
/**
100100
* Logs exceptions to the (native) console and displays them
101101
*/
102-
function handleException(e: Error, isFatal: boolean) {
103-
// Workaround for reporting errors caused by `throw 'some string'`
104-
// Unfortunately there is no way to figure out the stacktrace in this
105-
// case, so if you ended up here trying to trace an error, look for
106-
// `throw '<error message>'` somewhere in your codebase.
107-
if (!e.message) {
108-
// $FlowFixMe - cannot reassign constant, explanation above
109-
e = new SyntheticError(e);
102+
function handleException(e: mixed, isFatal: boolean) {
103+
let error: Error;
104+
if (e instanceof Error) {
105+
error = e;
106+
} else {
107+
// Workaround for reporting errors caused by `throw 'some string'`
108+
// Unfortunately there is no way to figure out the stacktrace in this
109+
// case, so if you ended up here trying to trace an error, look for
110+
// `throw '<error message>'` somewhere in your codebase.
111+
error = new SyntheticError(e);
110112
}
111-
reportException(e, isFatal);
113+
reportException(error, isFatal);
112114
}
113115

114116
function reactConsoleErrorHandler() {

Libraries/polyfills/error-guard.js

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,24 @@
55
* LICENSE file in the root directory of this source tree.
66
*
77
* @format
8+
* @flow strict
89
* @polyfill
9-
* @nolint
1010
*/
1111

1212
let _inGuard = 0;
1313

14+
type ErrorHandler = (error: mixed, isFatal: boolean) => void;
15+
type Fn<Args, Return> = (...Args) => Return;
16+
1417
/**
1518
* This is the error handler that is called when we encounter an exception
1619
* when loading a module. This will report any errors encountered before
1720
* ExceptionsManager is configured.
1821
*/
19-
let _globalHandler = function onError(e) {
22+
let _globalHandler: ErrorHandler = function onError(
23+
e: mixed,
24+
isFatal: boolean,
25+
) {
2026
throw e;
2127
};
2228

@@ -29,21 +35,31 @@ let _globalHandler = function onError(e) {
2935
* set) globally before requiring anything.
3036
*/
3137
const ErrorUtils = {
32-
setGlobalHandler(fun) {
38+
setGlobalHandler(fun: ErrorHandler): void {
3339
_globalHandler = fun;
3440
},
35-
getGlobalHandler() {
41+
getGlobalHandler(): ErrorHandler {
3642
return _globalHandler;
3743
},
38-
reportError(error) {
39-
_globalHandler && _globalHandler(error);
44+
reportError(error: mixed): void {
45+
_globalHandler && _globalHandler(error, false);
4046
},
41-
reportFatalError(error) {
47+
reportFatalError(error: mixed): void {
48+
// NOTE: This has an untyped call site in Metro.
4249
_globalHandler && _globalHandler(error, true);
4350
},
44-
applyWithGuard(fun, context, args) {
51+
applyWithGuard<TArgs: $ReadOnlyArray<mixed>, TOut>(
52+
fun: Fn<TArgs, TOut>,
53+
context?: ?mixed,
54+
args?: ?TArgs,
55+
// Unused, but some code synced from www sets it to null.
56+
unused_onError?: null,
57+
// Some callers pass a name here, which we ignore.
58+
unused_name?: ?string,
59+
): ?TOut {
4560
try {
4661
_inGuard++;
62+
// $FlowFixMe: TODO T48204745 (1) apply(context, null) is fine. (2) array -> rest array should work
4763
return fun.apply(context, args);
4864
} catch (e) {
4965
ErrorUtils.reportError(e);
@@ -52,30 +68,41 @@ const ErrorUtils = {
5268
}
5369
return null;
5470
},
55-
applyWithGuardIfNeeded(fun, context, args) {
71+
applyWithGuardIfNeeded<TArgs: $ReadOnlyArray<mixed>, TOut>(
72+
fun: Fn<TArgs, TOut>,
73+
context?: ?mixed,
74+
args?: ?TArgs,
75+
): ?TOut {
5676
if (ErrorUtils.inGuard()) {
77+
// $FlowFixMe: TODO T48204745 (1) apply(context, null) is fine. (2) array -> rest array should work
5778
return fun.apply(context, args);
5879
} else {
5980
ErrorUtils.applyWithGuard(fun, context, args);
6081
}
6182
return null;
6283
},
63-
inGuard() {
64-
return _inGuard;
84+
inGuard(): boolean {
85+
return !!_inGuard;
6586
},
66-
guard(fun, name, context) {
87+
guard<TArgs: $ReadOnlyArray<mixed>, TOut>(
88+
fun: Fn<TArgs, TOut>,
89+
name?: ?string,
90+
context?: ?mixed,
91+
): ?(...TArgs) => ?TOut {
92+
// TODO: (moti) T48204753 Make sure this warning is never hit and remove it - types
93+
// should be sufficient.
6794
if (typeof fun !== 'function') {
6895
console.warn('A function must be passed to ErrorUtils.guard, got ', fun);
6996
return null;
7097
}
71-
name = name || fun.name || '<generated guard>';
72-
function guarded() {
98+
const guardName = name ?? fun.name ?? '<generated guard>';
99+
function guarded(...args: TArgs): ?TOut {
73100
return ErrorUtils.applyWithGuard(
74101
fun,
75-
context || this,
76-
arguments,
102+
context ?? this,
103+
args,
77104
null,
78-
name,
105+
guardName,
79106
);
80107
}
81108

@@ -84,3 +111,5 @@ const ErrorUtils = {
84111
};
85112

86113
global.ErrorUtils = ErrorUtils;
114+
115+
export type ErrorUtilsT = typeof ErrorUtils;

Libraries/vendor/core/ErrorUtils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* @flow strict
99
*/
1010

11-
/* eslint-disable strict */
11+
import type {ErrorUtilsT} from '../../polyfills/error-guard.js';
1212

1313
/**
1414
* The particular require runtime that we are using looks for a global
@@ -22,4 +22,4 @@
2222
* that use it aren't just using a global variable, so simply export the global
2323
* variable here. ErrorUtils is originally defined in a file named error-guard.js.
2424
*/
25-
module.exports = global.ErrorUtils;
25+
module.exports = (global.ErrorUtils: ErrorUtilsT);

0 commit comments

Comments
 (0)