mirror of https://github.com/vuejs/core.git
feat(runtime-core): add app.config.throwUnhandledErrorInProduction
close #7876
This commit is contained in:
parent
912494318f
commit
f476b7f030
|
|
@ -538,6 +538,23 @@ describe('api: createApp', () => {
|
|||
expect(serializeInner(root)).toBe('hello')
|
||||
})
|
||||
|
||||
test('config.throwUnhandledErrorInProduction', () => {
|
||||
__DEV__ = false
|
||||
try {
|
||||
const err = new Error()
|
||||
const app = createApp({
|
||||
setup() {
|
||||
throw err
|
||||
},
|
||||
})
|
||||
app.config.throwUnhandledErrorInProduction = true
|
||||
const root = nodeOps.createElement('div')
|
||||
expect(() => app.mount(root)).toThrow(err)
|
||||
} finally {
|
||||
__DEV__ = true
|
||||
}
|
||||
})
|
||||
|
||||
test('return property "_" should not overwrite "ctx._", __isScriptSetup: false', () => {
|
||||
const Comp = defineComponent({
|
||||
setup() {
|
||||
|
|
|
|||
|
|
@ -124,6 +124,13 @@ export interface AppConfig {
|
|||
* Enable warnings for computed getters that recursively trigger itself.
|
||||
*/
|
||||
warnRecursiveComputed?: boolean
|
||||
|
||||
/**
|
||||
* Whether to throw unhandled errors in production.
|
||||
* Default is `false` to avoid crashing on any error (and only logs it)
|
||||
* But in some cases, e.g. SSR, throwing might be more desirable.
|
||||
*/
|
||||
throwUnhandledErrorInProduction?: boolean
|
||||
}
|
||||
|
||||
export interface AppContext {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { pauseTracking, resetTracking } from '@vue/reactivity'
|
|||
import type { VNode } from './vnode'
|
||||
import type { ComponentInternalInstance } from './component'
|
||||
import { popWarningContext, pushWarningContext, warn } from './warning'
|
||||
import { isArray, isFunction, isPromise } from '@vue/shared'
|
||||
import { EMPTY_OBJ, isArray, isFunction, isPromise } from '@vue/shared'
|
||||
import { LifecycleHooks } from './enums'
|
||||
|
||||
// contexts where user provided function may be executed, in addition to
|
||||
|
|
@ -111,7 +111,9 @@ export function handleError(
|
|||
type: ErrorTypes,
|
||||
throwInDev = true,
|
||||
) {
|
||||
const contextVNode = instance ? instance.vnode : null
|
||||
const contextVNode = instance && instance.vnode
|
||||
const { errorHandler, throwUnhandledErrorInProduction } =
|
||||
(instance && instance.appContext.config) || EMPTY_OBJ
|
||||
if (instance) {
|
||||
let cur = instance.parent
|
||||
// the exposed instance is the render proxy to keep it consistent with 2.x
|
||||
|
|
@ -134,20 +136,18 @@ export function handleError(
|
|||
cur = cur.parent
|
||||
}
|
||||
// app-level handling
|
||||
const appErrorHandler = instance.appContext.config.errorHandler
|
||||
if (appErrorHandler) {
|
||||
if (errorHandler) {
|
||||
pauseTracking()
|
||||
callWithErrorHandling(
|
||||
appErrorHandler,
|
||||
null,
|
||||
ErrorCodes.APP_ERROR_HANDLER,
|
||||
[err, exposedInstance, errorInfo],
|
||||
)
|
||||
callWithErrorHandling(errorHandler, null, ErrorCodes.APP_ERROR_HANDLER, [
|
||||
err,
|
||||
exposedInstance,
|
||||
errorInfo,
|
||||
])
|
||||
resetTracking()
|
||||
return
|
||||
}
|
||||
}
|
||||
logError(err, type, contextVNode, throwInDev)
|
||||
logError(err, type, contextVNode, throwInDev, throwUnhandledErrorInProduction)
|
||||
}
|
||||
|
||||
function logError(
|
||||
|
|
@ -155,6 +155,7 @@ function logError(
|
|||
type: ErrorTypes,
|
||||
contextVNode: VNode | null,
|
||||
throwInDev = true,
|
||||
throwInProd = false,
|
||||
) {
|
||||
if (__DEV__) {
|
||||
const info = ErrorTypeStrings[type]
|
||||
|
|
@ -171,6 +172,8 @@ function logError(
|
|||
} else if (!__TEST__) {
|
||||
console.error(err)
|
||||
}
|
||||
} else if (throwInProd) {
|
||||
throw err
|
||||
} else {
|
||||
// recover in prod to reduce the impact on end-user
|
||||
console.error(err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue