Compare commits
7 Commits
eslint-plu
...
user_error
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1703c68ab9 | ||
|
|
f09f0685eb | ||
|
|
1ad075c3dc | ||
|
|
566e046716 | ||
|
|
a1bec0709f | ||
|
|
12ecbea744 | ||
|
|
60cb32bf93 |
@@ -356,6 +356,23 @@ const Dispatcher: DispatcherType = {
|
|||||||
useId,
|
useId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// create a proxy to throw a custom error
|
||||||
|
// in case future versions of React adds more hooks
|
||||||
|
const DispatcherProxyHandler = {
|
||||||
|
get(target, prop, _receiver) {
|
||||||
|
if (target.hasOwnProperty(prop)) {
|
||||||
|
return target[prop];
|
||||||
|
}
|
||||||
|
const error = new Error('Missing method in Dispatcher: ' + prop);
|
||||||
|
// Note: This error name needs to stay in sync with react-devtools-shared
|
||||||
|
// TODO: refactor this if we ever combine the devtools and debug tools packages
|
||||||
|
error.name = 'UnsupportedFeatureError';
|
||||||
|
throw error;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const DispatcherProxy = new Proxy(Dispatcher, DispatcherProxyHandler);
|
||||||
|
|
||||||
// Inspect
|
// Inspect
|
||||||
|
|
||||||
export type HookSource = {
|
export type HookSource = {
|
||||||
@@ -650,6 +667,28 @@ function processDebugValues(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleRenderFunctionError(error: any): void {
|
||||||
|
// original error might be any type.
|
||||||
|
const isError = error instanceof Error;
|
||||||
|
if (isError && error.name === 'UnsupportedFeatureError') {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
// If the error is not caused by an unsupported feature, it means
|
||||||
|
// that the error is caused by user's code in renderFunction.
|
||||||
|
// In this case, we should wrap the original error inside a custom error
|
||||||
|
// so that devtools can show a clear message for it.
|
||||||
|
const messgae: string =
|
||||||
|
isError && error.message
|
||||||
|
? error.message
|
||||||
|
: 'Error rendering inspected component'
|
||||||
|
// $FlowFixMe: Flow doesn't know about 2nd argument of Error constructor
|
||||||
|
const wrapperError = new Error(messgae, {cause: error});
|
||||||
|
// Note: This error name needs to stay in sync with react-devtools-shared
|
||||||
|
// TODO: refactor this if we ever combine the devtools and debug tools packages
|
||||||
|
wrapperError.name = 'RenderFunctionError';
|
||||||
|
throw wrapperError;
|
||||||
|
}
|
||||||
|
|
||||||
export function inspectHooks<Props>(
|
export function inspectHooks<Props>(
|
||||||
renderFunction: Props => React$Node,
|
renderFunction: Props => React$Node,
|
||||||
props: Props,
|
props: Props,
|
||||||
@@ -664,11 +703,13 @@ export function inspectHooks<Props>(
|
|||||||
|
|
||||||
const previousDispatcher = currentDispatcher.current;
|
const previousDispatcher = currentDispatcher.current;
|
||||||
let readHookLog;
|
let readHookLog;
|
||||||
currentDispatcher.current = Dispatcher;
|
currentDispatcher.current = DispatcherProxy;
|
||||||
let ancestorStackError;
|
let ancestorStackError;
|
||||||
try {
|
try {
|
||||||
ancestorStackError = new Error();
|
ancestorStackError = new Error();
|
||||||
renderFunction(props);
|
renderFunction(props);
|
||||||
|
} catch (error) {
|
||||||
|
handleRenderFunctionError(error);
|
||||||
} finally {
|
} finally {
|
||||||
readHookLog = hookLog;
|
readHookLog = hookLog;
|
||||||
hookLog = [];
|
hookLog = [];
|
||||||
@@ -708,11 +749,13 @@ function inspectHooksOfForwardRef<Props, Ref>(
|
|||||||
): HooksTree {
|
): HooksTree {
|
||||||
const previousDispatcher = currentDispatcher.current;
|
const previousDispatcher = currentDispatcher.current;
|
||||||
let readHookLog;
|
let readHookLog;
|
||||||
currentDispatcher.current = Dispatcher;
|
currentDispatcher.current = DispatcherProxy;
|
||||||
let ancestorStackError;
|
let ancestorStackError;
|
||||||
try {
|
try {
|
||||||
ancestorStackError = new Error();
|
ancestorStackError = new Error();
|
||||||
renderFunction(props, ref);
|
renderFunction(props, ref);
|
||||||
|
} catch (error) {
|
||||||
|
handleRenderFunctionError(error);
|
||||||
} finally {
|
} finally {
|
||||||
readHookLog = hookLog;
|
readHookLog = hookLog;
|
||||||
hookLog = [];
|
hookLog = [];
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ import {
|
|||||||
TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,
|
TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,
|
||||||
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
|
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import {inspectHooksOfFiber} from 'react-debug-tools';
|
import {
|
||||||
|
inspectHooksOfFiber,
|
||||||
|
ErrorsNames as DebugToolsErrors,
|
||||||
|
} from 'react-debug-tools';
|
||||||
import {
|
import {
|
||||||
patch as patchConsole,
|
patch as patchConsole,
|
||||||
registerRenderer as registerRendererWithConsole,
|
registerRenderer as registerRendererWithConsole,
|
||||||
@@ -3616,6 +3619,41 @@ export function attach(
|
|||||||
try {
|
try {
|
||||||
mostRecentlyInspectedElement = inspectElementRaw(id);
|
mostRecentlyInspectedElement = inspectElementRaw(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error.name === DebugToolsErrors.RENDER_FUNCTION_ERROR) {
|
||||||
|
let message = 'Error rendering inspected element.';
|
||||||
|
let stack;
|
||||||
|
// Log error & cause for user to debug
|
||||||
|
console.error(message + '\n\n', error);
|
||||||
|
if (error.cause != null) {
|
||||||
|
console.error(
|
||||||
|
'Original error causing above error: \n\n',
|
||||||
|
error.cause,
|
||||||
|
);
|
||||||
|
if (error.cause instanceof Error) {
|
||||||
|
message = error.cause.message || message;
|
||||||
|
stack = error.cause.stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'user-error',
|
||||||
|
id,
|
||||||
|
responseID: requestID,
|
||||||
|
message,
|
||||||
|
stack,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.name === DebugToolsErrors.UNSUPPORTTED_FEATURE_ERROR) {
|
||||||
|
return {
|
||||||
|
type: 'unsupported-feature',
|
||||||
|
id,
|
||||||
|
responseID: requestID,
|
||||||
|
message: 'Unsupported feature: ' + error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log Uncaught Error
|
||||||
console.error('Error inspecting element.\n\n', error);
|
console.error('Error inspecting element.\n\n', error);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -281,6 +281,8 @@ export type InspectedElement = {|
|
|||||||
|};
|
|};
|
||||||
|
|
||||||
export const InspectElementErrorType = 'error';
|
export const InspectElementErrorType = 'error';
|
||||||
|
export const InspectElementUserErrorType = 'user-error';
|
||||||
|
export const InspectElementUnsupportedFeatureErrorType = 'unsupported-feature';
|
||||||
export const InspectElementFullDataType = 'full-data';
|
export const InspectElementFullDataType = 'full-data';
|
||||||
export const InspectElementNoChangeType = 'no-change';
|
export const InspectElementNoChangeType = 'no-change';
|
||||||
export const InspectElementNotFoundType = 'not-found';
|
export const InspectElementNotFoundType = 'not-found';
|
||||||
@@ -293,6 +295,21 @@ export type InspectElementError = {|
|
|||||||
stack: string,
|
stack: string,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
|
export type InspectElementUserError = {|
|
||||||
|
id: number,
|
||||||
|
responseID: number,
|
||||||
|
type: 'user-error',
|
||||||
|
message: string,
|
||||||
|
stack: ?string,
|
||||||
|
|};
|
||||||
|
|
||||||
|
export type InspectElementUnsupportedFeatureError = {|
|
||||||
|
id: number,
|
||||||
|
responseID: number,
|
||||||
|
type: 'unsupported-feature',
|
||||||
|
message: string,
|
||||||
|
|};
|
||||||
|
|
||||||
export type InspectElementFullData = {|
|
export type InspectElementFullData = {|
|
||||||
id: number,
|
id: number,
|
||||||
responseID: number,
|
responseID: number,
|
||||||
@@ -322,6 +339,8 @@ export type InspectElementNotFound = {|
|
|||||||
|
|
||||||
export type InspectedElementPayload =
|
export type InspectedElementPayload =
|
||||||
| InspectElementError
|
| InspectElementError
|
||||||
|
| InspectElementUserError
|
||||||
|
| InspectElementUnsupportedFeatureError
|
||||||
| InspectElementFullData
|
| InspectElementFullData
|
||||||
| InspectElementHydratedPath
|
| InspectElementHydratedPath
|
||||||
| InspectElementNoChange
|
| InspectElementNoChange
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import {hydrate, fillInPath} from 'react-devtools-shared/src/hydration';
|
import {hydrate, fillInPath} from 'react-devtools-shared/src/hydration';
|
||||||
import {separateDisplayNameAndHOCs} from 'react-devtools-shared/src/utils';
|
import {separateDisplayNameAndHOCs} from 'react-devtools-shared/src/utils';
|
||||||
import Store from 'react-devtools-shared/src/devtools/store';
|
import Store from 'react-devtools-shared/src/devtools/store';
|
||||||
import TimeoutError from 'react-devtools-shared/src/TimeoutError';
|
import TimeoutError from 'react-devtools-shared/src/errors/TimeoutError';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
InspectedElement as InspectedElementBackend,
|
InspectedElement as InspectedElementBackend,
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export type OwnersList = {|
|
|||||||
|
|
||||||
export type InspectedElementResponseType =
|
export type InspectedElementResponseType =
|
||||||
| 'error'
|
| 'error'
|
||||||
|
| 'user-error'
|
||||||
| 'full-data'
|
| 'full-data'
|
||||||
| 'hydrated-path'
|
| 'hydrated-path'
|
||||||
| 'no-change'
|
| 'no-change'
|
||||||
|
|||||||
44
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/CaughtErrorView.js
vendored
Normal file
44
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/CaughtErrorView.js
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import styles from './shared.css';
|
||||||
|
|
||||||
|
type Props = {|
|
||||||
|
callStack: string | null,
|
||||||
|
children: React$Node,
|
||||||
|
info: React$Node | null,
|
||||||
|
componentStack: string | null,
|
||||||
|
errorMessage: string,
|
||||||
|
|};
|
||||||
|
|
||||||
|
export default function CaughtErrorView({
|
||||||
|
callStack,
|
||||||
|
children,
|
||||||
|
info,
|
||||||
|
componentStack,
|
||||||
|
errorMessage,
|
||||||
|
}: Props) {
|
||||||
|
return (
|
||||||
|
<div className={styles.ErrorBoundary}>
|
||||||
|
{children}
|
||||||
|
<div className={styles.ErrorInfo}>
|
||||||
|
<div className={styles.HeaderRow}>
|
||||||
|
<div className={styles.ErrorHeader}>{errorMessage}</div>
|
||||||
|
</div>
|
||||||
|
{!!info && <div className={styles.InfoBox}>{info}</div>}
|
||||||
|
{!!callStack && (
|
||||||
|
<div className={styles.ErrorStack}>
|
||||||
|
The error was thrown {callStack.trim()}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,8 +15,11 @@ import ErrorView from './ErrorView';
|
|||||||
import SearchingGitHubIssues from './SearchingGitHubIssues';
|
import SearchingGitHubIssues from './SearchingGitHubIssues';
|
||||||
import SuspendingErrorView from './SuspendingErrorView';
|
import SuspendingErrorView from './SuspendingErrorView';
|
||||||
import TimeoutView from './TimeoutView';
|
import TimeoutView from './TimeoutView';
|
||||||
|
import CaughtErrorView from './CaughtErrorView';
|
||||||
import UnsupportedBridgeOperationError from 'react-devtools-shared/src/UnsupportedBridgeOperationError';
|
import UnsupportedBridgeOperationError from 'react-devtools-shared/src/UnsupportedBridgeOperationError';
|
||||||
import TimeoutError from 'react-devtools-shared/src/TimeoutError';
|
import TimeoutError from 'react-devtools-shared/src/errors/TimeoutError';
|
||||||
|
import UserError from 'react-devtools-shared/src/errors/UserError';
|
||||||
|
import UnsupportedFeatureError from 'react-devtools-shared/src/errors/UnsupportedFeatureError';
|
||||||
import {logEvent} from 'react-devtools-shared/src/Logger';
|
import {logEvent} from 'react-devtools-shared/src/Logger';
|
||||||
|
|
||||||
type Props = {|
|
type Props = {|
|
||||||
@@ -34,6 +37,8 @@ type State = {|
|
|||||||
hasError: boolean,
|
hasError: boolean,
|
||||||
isUnsupportedBridgeOperationError: boolean,
|
isUnsupportedBridgeOperationError: boolean,
|
||||||
isTimeout: boolean,
|
isTimeout: boolean,
|
||||||
|
isUserError: boolean,
|
||||||
|
isUnsupportedFeatureError: boolean,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
const InitialState: State = {
|
const InitialState: State = {
|
||||||
@@ -44,6 +49,8 @@ const InitialState: State = {
|
|||||||
hasError: false,
|
hasError: false,
|
||||||
isUnsupportedBridgeOperationError: false,
|
isUnsupportedBridgeOperationError: false,
|
||||||
isTimeout: false,
|
isTimeout: false,
|
||||||
|
isUserError: false,
|
||||||
|
isUnsupportedFeatureError: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ErrorBoundary extends Component<Props, State> {
|
export default class ErrorBoundary extends Component<Props, State> {
|
||||||
@@ -58,6 +65,8 @@ export default class ErrorBoundary extends Component<Props, State> {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
const isTimeout = error instanceof TimeoutError;
|
const isTimeout = error instanceof TimeoutError;
|
||||||
|
const isUserError = error instanceof UserError;
|
||||||
|
const isUnsupportedFeatureError = error instanceof UnsupportedFeatureError;
|
||||||
const isUnsupportedBridgeOperationError =
|
const isUnsupportedBridgeOperationError =
|
||||||
error instanceof UnsupportedBridgeOperationError;
|
error instanceof UnsupportedBridgeOperationError;
|
||||||
|
|
||||||
@@ -76,7 +85,9 @@ export default class ErrorBoundary extends Component<Props, State> {
|
|||||||
errorMessage,
|
errorMessage,
|
||||||
hasError: true,
|
hasError: true,
|
||||||
isUnsupportedBridgeOperationError,
|
isUnsupportedBridgeOperationError,
|
||||||
|
isUnsupportedFeatureError,
|
||||||
isTimeout,
|
isTimeout,
|
||||||
|
isUserError,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +122,8 @@ export default class ErrorBoundary extends Component<Props, State> {
|
|||||||
hasError,
|
hasError,
|
||||||
isUnsupportedBridgeOperationError,
|
isUnsupportedBridgeOperationError,
|
||||||
isTimeout,
|
isTimeout,
|
||||||
|
isUserError,
|
||||||
|
isUnsupportedFeatureError,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
@@ -133,6 +146,38 @@ export default class ErrorBoundary extends Component<Props, State> {
|
|||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else if (isUserError) {
|
||||||
|
return (
|
||||||
|
<CaughtErrorView
|
||||||
|
callStack={callStack}
|
||||||
|
componentStack={componentStack}
|
||||||
|
errorMessage={errorMessage || 'Error occured in inspected element'}
|
||||||
|
info={
|
||||||
|
<>
|
||||||
|
This is likely to be caused by implementation of current
|
||||||
|
inspected element. Please see your console for logged error.
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else if (isUnsupportedFeatureError) {
|
||||||
|
return (
|
||||||
|
<CaughtErrorView
|
||||||
|
callStack={callStack}
|
||||||
|
componentStack={componentStack}
|
||||||
|
errorMessage={
|
||||||
|
errorMessage ||
|
||||||
|
'Current DevTools version does not support a feature used in the inspected element.'
|
||||||
|
}
|
||||||
|
info={
|
||||||
|
<>
|
||||||
|
React DevTools is unable to handle a feature you are using in
|
||||||
|
this component (e.g. a new React build-in Hook). Please upgrade
|
||||||
|
to the latest version.
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<ErrorView
|
<ErrorView
|
||||||
@@ -141,10 +186,7 @@ export default class ErrorBoundary extends Component<Props, State> {
|
|||||||
dismissError={
|
dismissError={
|
||||||
canDismissProp || canDismissState ? this._dismissError : null
|
canDismissProp || canDismissState ? this._dismissError : null
|
||||||
}
|
}
|
||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}>
|
||||||
isUnsupportedBridgeOperationError={
|
|
||||||
isUnsupportedBridgeOperationError
|
|
||||||
}>
|
|
||||||
<Suspense fallback={<SearchingGitHubIssues />}>
|
<Suspense fallback={<SearchingGitHubIssues />}>
|
||||||
<SuspendingErrorView
|
<SuspendingErrorView
|
||||||
callStack={callStack}
|
callStack={callStack}
|
||||||
|
|||||||
21
packages/react-devtools-shared/src/errors/UnsupportedFeatureError.js
vendored
Normal file
21
packages/react-devtools-shared/src/errors/UnsupportedFeatureError.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class UnsupportedFeatureError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
|
||||||
|
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
||||||
|
if (Error.captureStackTrace) {
|
||||||
|
Error.captureStackTrace(this, UnsupportedFeatureError);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = 'UnsupportedFeatureError';
|
||||||
|
}
|
||||||
|
}
|
||||||
21
packages/react-devtools-shared/src/errors/UserError.js
vendored
Normal file
21
packages/react-devtools-shared/src/errors/UserError.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class UserError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
|
||||||
|
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
||||||
|
if (Error.captureStackTrace) {
|
||||||
|
Error.captureStackTrace(this, UserError);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = 'UserError';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import LRU from 'lru-cache';
|
import LRU from 'lru-cache';
|
||||||
|
import {UserHookError} from 'react-debug-tools';
|
||||||
import {
|
import {
|
||||||
convertInspectedElementBackendToFrontend,
|
convertInspectedElementBackendToFrontend,
|
||||||
hydrateHelper,
|
hydrateHelper,
|
||||||
@@ -19,6 +20,8 @@ import type {LRUCache} from 'react-devtools-shared/src/types';
|
|||||||
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
|
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
|
||||||
import type {
|
import type {
|
||||||
InspectElementError,
|
InspectElementError,
|
||||||
|
InspectElementUserError,
|
||||||
|
InspectElementUnsupportedFeatureError,
|
||||||
InspectElementFullData,
|
InspectElementFullData,
|
||||||
InspectElementHydratedPath,
|
InspectElementHydratedPath,
|
||||||
} from 'react-devtools-shared/src/backend/types';
|
} from 'react-devtools-shared/src/backend/types';
|
||||||
@@ -27,6 +30,8 @@ import type {
|
|||||||
InspectedElement as InspectedElementFrontend,
|
InspectedElement as InspectedElementFrontend,
|
||||||
InspectedElementResponseType,
|
InspectedElementResponseType,
|
||||||
} from 'react-devtools-shared/src/devtools/views/Components/types';
|
} from 'react-devtools-shared/src/devtools/views/Components/types';
|
||||||
|
import UserError from 'react-devtools-shared/src/errors/UserError';
|
||||||
|
import UnsupportedFeatureError from 'react-devtools-shared/src/errors/UnsupportedFeatureError';
|
||||||
|
|
||||||
// Maps element ID to inspected data.
|
// Maps element ID to inspected data.
|
||||||
// We use an LRU for this rather than a WeakMap because of how the "no-change" optimization works.
|
// We use an LRU for this rather than a WeakMap because of how the "no-change" optimization works.
|
||||||
@@ -80,7 +85,7 @@ export function inspectElement({
|
|||||||
|
|
||||||
let inspectedElement;
|
let inspectedElement;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'error':
|
case 'error': {
|
||||||
const {message, stack} = ((data: any): InspectElementError);
|
const {message, stack} = ((data: any): InspectElementError);
|
||||||
|
|
||||||
// The backend's stack (where the error originated) is more meaningful than this stack.
|
// The backend's stack (where the error originated) is more meaningful than this stack.
|
||||||
@@ -88,6 +93,22 @@ export function inspectElement({
|
|||||||
error.stack = stack;
|
error.stack = stack;
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'user-error': {
|
||||||
|
const {message, stack} = (data: InspectElementUserError);
|
||||||
|
// Trying to keep useful information from user's side.
|
||||||
|
const error = new UserError(message);
|
||||||
|
error.stack = stack || error.stack;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'unsupported-feature': {
|
||||||
|
const {message} = (data: InspectElementUnsupportedFeatureError);
|
||||||
|
// Trying to keep useful information from user's side.
|
||||||
|
const error = new UnsupportedFeatureError(message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
case 'no-change':
|
case 'no-change':
|
||||||
// This is a no-op for the purposes of our cache.
|
// This is a no-op for the purposes of our cache.
|
||||||
|
|||||||
Reference in New Issue
Block a user