From: Eduardo San Martin Morote Date: Wed, 6 May 2020 09:29:38 +0000 (+0200) Subject: feat(warn): warn if next was called multiple times X-Git-Tag: v4.0.0-alpha.11~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dce2612e495b1d5789cd993a54d24599967a8cf4;p=thirdparty%2Fvuejs%2Frouter.git feat(warn): warn if next was called multiple times --- diff --git a/__tests__/warnings.spec.ts b/__tests__/warnings.spec.ts index 7b54705b..12f5b455 100644 --- a/__tests__/warnings.spec.ts +++ b/__tests__/warnings.spec.ts @@ -90,4 +90,27 @@ describe('warnings', () => { 'Alias "/:p/:c" and the original record: "/:p/c" should have the exact same param named "c"' ).toHaveBeenWarned() }) + + it('warns if next is called multiple times in one navigation guard', done => { + expect.assertions(3) + let router = createRouter({ + history: createMemoryHistory(), + routes: [ + { path: '/', name: 'a', component }, + { path: '/b', name: 'a', component }, + ], + }) + + router.beforeEach((to, from, next) => { + next() + expect('').not.toHaveBeenWarned() + next() + expect('called more than once').toHaveBeenWarnedTimes(1) + next() + expect('called more than once').toHaveBeenWarnedTimes(1) + done() + }) + + router.push('/b') + }) }) diff --git a/src/navigationGuards.ts b/src/navigationGuards.ts index fba11dbe..d906e365 100644 --- a/src/navigationGuards.ts +++ b/src/navigationGuards.ts @@ -127,12 +127,32 @@ export function guardToPromiseFn( } // wrapping with Promise.resolve allows it to work with both async and sync guards - Promise.resolve(guard.call(instance, to, from, next)).catch(err => - reject(err) - ) + Promise.resolve( + guard.call( + instance, + to, + from, + __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next + ) + ).catch(err => reject(err)) }) } +function canOnlyBeCalledOnce( + next: NavigationGuardCallback, + to: RouteLocationNormalized, + from: RouteLocationNormalized +): NavigationGuardCallback { + let called = 0 + return function () { + if (called++ === 1) + warn( + `The "next" callback was called more than once in one navigation guard when going from "${from.fullPath}" to "${to.fullPath}". It should be called exactly one time in each navigation guard. This will fail in production.` + ) + if (called === 1) next.apply(null, arguments as any) + } +} + type GuardType = 'beforeRouteEnter' | 'beforeRouteUpdate' | 'beforeRouteLeave' export function extractComponentsGuards(