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() {
* 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 {
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
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
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(
type: ErrorTypes,
contextVNode: VNode | null,
throwInDev = true,
+ throwInProd = false,
) {
if (__DEV__) {
const info = ErrorTypeStrings[type]
} 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)