Skip to content

Commit f0e423f

Browse files
authored
fix(watch): errors thrown in the asynchronous callback function in watch will not be caught. (#751)
1 parent a279eab commit f0e423f

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

src/apis/watch.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,14 +235,14 @@ function createWatcher(
235235
) {
236236
return fn
237237
}
238-
return (((...args: any[]) =>
238+
return ((...args: any[]) =>
239239
queueFlushJob(
240240
vm,
241241
() => {
242242
fn(...args)
243243
},
244244
flushMode as 'pre' | 'post'
245-
)) as any) as T
245+
)) as any as T
246246
}
247247

248248
// effect watch
@@ -320,7 +320,7 @@ function createWatcher(
320320
const applyCb = (n: any, o: any) => {
321321
// cleanup before running cb again
322322
runCleanup()
323-
cb(n, o, registerCleanup)
323+
return cb(n, o, registerCleanup)
324324
}
325325
let callback = createScheduler(applyCb)
326326
if (options.immediate) {
@@ -330,10 +330,10 @@ function createWatcher(
330330
let shiftCallback = (n: any, o: any) => {
331331
shiftCallback = originalCallback
332332
// o is undefined on the first call
333-
applyCb(n, isArray(n) ? [] : o)
333+
return applyCb(n, isArray(n) ? [] : o)
334334
}
335335
callback = (n: any, o: any) => {
336-
shiftCallback(n, o)
336+
return shiftCallback(n, o)
337337
}
338338
}
339339

test/apis/watch.spec.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
const Vue = require('vue/dist/vue.common.js')
2-
const { ref, reactive, watch, watchEffect, set } = require('../../src')
2+
const {
3+
ref,
4+
reactive,
5+
watch,
6+
watchEffect,
7+
set,
8+
nextTick,
9+
} = require('../../src')
10+
const { mockWarn } = require('../helpers')
311

412
describe('api/watch', () => {
13+
mockWarn(true)
514
const anyFn = expect.any(Function)
615
let spy
716
beforeEach(() => {
@@ -587,6 +596,27 @@ describe('api/watch', () => {
587596
expect(spy).toHaveBeenNthCalledWith(2, [3, 1], [2, 1])
588597
expect(spy).toHaveBeenNthCalledWith(3, [3, 3], [3, 1])
589598
})
599+
600+
it('config.errorHandler should capture render errors', async () => {
601+
new Vue({
602+
setup() {
603+
const a = ref(1)
604+
watch(
605+
a,
606+
async () => {
607+
throw new Error('userWatcherCallback error')
608+
},
609+
{ immediate: true }
610+
)
611+
return {
612+
a,
613+
}
614+
},
615+
template: `<div>{{a}}</div>`,
616+
}).$mount()
617+
await nextTick()
618+
expect(`userWatcherCallback error`).toHaveBeenWarned()
619+
})
590620
})
591621

592622
describe('Out of setup', () => {

test/helpers/mockWarn.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function mockWarn(asError = false) {
1515
toHaveBeenWarned(received: string) {
1616
asserted.add(received)
1717
const passed = warn.mock.calls.some(
18-
(args) => args[0].indexOf(received) > -1
18+
(args) => args[0].toString().indexOf(received) > -1
1919
)
2020
if (passed) {
2121
return {
@@ -91,7 +91,7 @@ export function mockWarn(asError = false) {
9191
.map((args) => args[0])
9292
.filter((received) => {
9393
return !assertedArray.some((assertedMsg) => {
94-
return received.indexOf(assertedMsg) > -1
94+
return received.toString().indexOf(assertedMsg) > -1
9595
})
9696
})
9797
warn.mockRestore()

0 commit comments

Comments
 (0)