Skip to content

Commit

Permalink
Use an expando property instead of a WeakSet
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Aug 13, 2018
1 parent 977ae18 commit c433932
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 54 deletions.
5 changes: 2 additions & 3 deletions fixtures/dom/src/components/fixtures/error-handling/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,8 @@ export default class ErrorHandlingTestCases extends React.Component {
<li>Uncheck the "Silence errors" checkbox</li>
</TestCase.Steps>
<TestCase.ExpectedResult>
Open the console. "Uncaught Error: Caught error" should have been
logged by React. You should also see our addendum ("The above
error...").
Open the console. "Error: Caught error" should have been logged by
React. You should also see our addendum ("The above error...").
</TestCase.ExpectedResult>
<TrySilenceFatalError />
</TestCase>
Expand Down
5 changes: 2 additions & 3 deletions packages/react-reconciler/src/ReactFiberErrorLogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

import type {CapturedError} from './ReactCapturedValue';

import ReactErrorUtils from 'shared/ReactErrorUtils';

import {showErrorDialog} from './ReactFiberErrorDialog';

export function logCapturedError(capturedError: CapturedError): void {
Expand Down Expand Up @@ -39,7 +37,8 @@ export function logCapturedError(capturedError: CapturedError): void {

// Browsers support silencing uncaught errors by calling
// `preventDefault()` in window `error` handler.
if ((ReactErrorUtils: any).isErrorSuppressedInDEV(error)) {
// We record this information as an expando on the error.
if (error != null && error._suppressLogging) {
if (errorBoundaryFound && willRetry) {
// The error is recoverable and was silenced.
// Ignore it and print the stack addendum.
Expand Down
26 changes: 14 additions & 12 deletions packages/react-reconciler/src/ReactFiberScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,21 +301,23 @@ if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
// Replay the begin phase.
isReplayingFailedUnitOfWork = true;
originalReplayError = thrownValue;
const didSuppressError = invokeGuardedCallback(
null,
workLoop,
null,
isYieldy,
);
if (didSuppressError) {
// If logging of the replayed error was suppressed,
// we'll also remember that for the original error.
(ReactErrorUtils: any).markErrorAsSuppressedInDEV(thrownValue);
}
invokeGuardedCallback(null, workLoop, null, isYieldy);
isReplayingFailedUnitOfWork = false;
originalReplayError = null;
if (hasCaughtError()) {
clearCaughtError();
const replayError = clearCaughtError();
if (
replayError != null &&
thrownValue != null &&
replayError._suppressLogging
) {
// Also suppress logging for the original error.
try {
(thrownValue: any)._suppressLogging = true;
} catch (inner) {
// Ignore.
}
}
} else {
// If the begin phase did not fail the second time, set this pointer
// back to the original value.
Expand Down
30 changes: 2 additions & 28 deletions packages/shared/ReactErrorUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ const ReactErrorUtils = {
d: D,
e: E,
f: F,
): boolean | void {
return invokeGuardedCallback.apply(ReactErrorUtils, arguments);
): void {
invokeGuardedCallback.apply(ReactErrorUtils, arguments);
},

/**
Expand Down Expand Up @@ -105,32 +105,6 @@ const ReactErrorUtils = {
},
};

if (__DEV__) {
(ReactErrorUtils: any)._suppressedErrorsInDEV =
typeof WeakSet === 'function' ? new WeakSet() : null;

(ReactErrorUtils: any).markErrorAsSuppressedInDEV = function(error: any) {
const suppressedErrors = (ReactErrorUtils: any)._suppressedErrorsInDEV;
if (
suppressedErrors != null &&
error != null &&
typeof error === 'object'
) {
suppressedErrors.add(error);
}
};

(ReactErrorUtils: any).isErrorSuppressedInDEV = function(
error: any,
): boolean {
const suppressedErrors = (ReactErrorUtils: any)._suppressedErrorsInDEV;
if (suppressedErrors != null) {
return suppressedErrors.has(error);
}
return false;
};
}

let rethrowCaughtError = function() {
if (ReactErrorUtils._hasRethrowError) {
const error = ReactErrorUtils._rethrowError;
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/__tests__/ReactErrorUtils-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('ReactErrorUtils', () => {
'arg1',
'arg2',
);
expect(returnValue).toBe(true);
expect(returnValue).toBe(undefined);
expect(ReactErrorUtils.hasCaughtError()).toBe(true);
expect(ReactErrorUtils.clearCaughtError()).toBe(error);
});
Expand Down
16 changes: 9 additions & 7 deletions packages/shared/invokeGuardedCallback.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,9 @@ if (__DEV__) {
let error;
// Use this to track whether the error event is ever called.
let didSetError = false;
let didSuppressError = false;
let isCrossOriginError = false;

const onError = event => {
function onError(event) {
error = event.error;
didSetError = true;
if (error === null && event.colno === 0 && event.lineno === 0) {
Expand All @@ -137,10 +136,15 @@ if (__DEV__) {
// Some other error handler has prevented default.
// Browsers silence the error report if this happens.
// We'll remember this to later decide whether to log it or not.
this.markErrorAsSuppressedInDEV(error);
didSuppressError = true;
if (error != null && typeof error === 'object') {
try {
error._suppressLogging = true;
} catch (inner) {
// Ignore.
}
}
}
};
}

// Create a fake event type.
const evtType = `react-${name ? name : 'invokeguardedcallback'}`;
Expand Down Expand Up @@ -183,8 +187,6 @@ if (__DEV__) {

// Remove our event listeners
window.removeEventListener('error', onError);

return didSuppressError;
};

invokeGuardedCallback = invokeGuardedCallbackDev;
Expand Down

0 comments on commit c433932

Please sign in to comment.