Skip to content

Commit e747d5e

Browse files
fix(ssr): Memory leak in poll method, take 2 (fix vuejs#2606)
1 parent 5141def commit e747d5e

File tree

4 files changed

+21
-26
lines changed

4 files changed

+21
-26
lines changed

flow/declarations.js

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ declare type RouteRecord = {
6868
regex: RouteRegExp;
6969
components: Dictionary<any>;
7070
instances: Dictionary<any>;
71+
pendingCbs: Dictionary<Function>;
7172
name: ?string;
7273
parent: ?RouteRecord;
7374
redirect: ?RedirectOption;

src/components/view.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { warn } from '../util/warn'
22
import { extend } from '../util/misc'
3+
import { tryFinalizeTransition } from '../history/base'
34

45
export default {
56
name: 'RouterView',
@@ -63,13 +64,18 @@ export default {
6364
(!val && current === vm)
6465
) {
6566
matched.instances[name] = val
67+
// if the route transition has already been confirmed then we weren't
68+
// able to call the cb during confirmation as the component was not
69+
// registered yet, so we call it here.
70+
tryFinalizeTransition(matched, name)
6671
}
6772
}
6873

6974
// also register instance in prepatch hook
7075
// in case the same component instance is reused across different routes
7176
;(data.hook || (data.hook = {})).prepatch = (_, vnode) => {
7277
matched.instances[name] = vnode.componentInstance
78+
tryFinalizeTransition(matched, name)
7379
}
7480

7581
// register instance in init hook
@@ -80,6 +86,7 @@ export default {
8086
vnode.componentInstance !== matched.instances[name]
8187
) {
8288
matched.instances[name] = vnode.componentInstance
89+
tryFinalizeTransition(matched, name)
8390
}
8491
}
8592

src/create-route-map.js

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ function addRouteRecord (
7373
regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
7474
components: route.components || { default: route.component },
7575
instances: {},
76+
pendingCbs: {},
7677
name,
7778
parent,
7879
matchAs,

src/history/base.js

+12-26
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,9 @@ export class History {
178178

179179
runQueue(queue, iterator, () => {
180180
const postEnterCbs = []
181-
const isValid = () => this.current === route
182181
// wait until async components are resolved before
183182
// extracting in-component enter guards
184-
const enterGuards = extractEnterGuards(activated, postEnterCbs, isValid)
183+
const enterGuards = extractEnterGuards(activated, postEnterCbs)
185184
const queue = enterGuards.concat(this.router.resolveHooks)
186185
runQueue(queue, iterator, () => {
187186
if (this.pending !== route) {
@@ -299,13 +298,12 @@ function bindGuard (guard: NavigationGuard, instance: ?_Vue): ?NavigationGuard {
299298
function extractEnterGuards (
300299
activated: Array<RouteRecord>,
301300
cbs: Array<Function>,
302-
isValid: () => boolean
303301
): Array<?Function> {
304302
return extractGuards(
305303
activated,
306304
'beforeRouteEnter',
307305
(guard, _, match, key) => {
308-
return bindEnterGuard(guard, match, key, cbs, isValid)
306+
return bindEnterGuard(guard, match, key, cbs)
309307
}
310308
)
311309
}
@@ -315,39 +313,27 @@ function bindEnterGuard (
315313
match: RouteRecord,
316314
key: string,
317315
cbs: Array<Function>,
318-
isValid: () => boolean
319316
): NavigationGuard {
320317
return function routeEnterGuard (to, from, next) {
321318
return guard(to, from, cb => {
322319
if (typeof cb === 'function') {
320+
match.pendingCbs[key] = cb
323321
cbs.push(() => {
324-
// #750
325-
// if a router-view is wrapped with an out-in transition,
326-
// the instance may not have been registered at this time.
327-
// we will need to poll for registration until current route
328-
// is no longer valid.
329-
poll(cb, match.instances, key, isValid)
322+
// if the instance is registered call the cb here, otherwise it will
323+
// get called when it is registered in the component's lifecycle hooks
324+
tryFinalizeTransition(match, key)
330325
})
331326
}
332327
next(cb)
333328
})
334329
}
335330
}
336331

337-
function poll (
338-
cb: any, // somehow flow cannot infer this is a function
339-
instances: Object,
340-
key: string,
341-
isValid: () => boolean
342-
) {
343-
if (
344-
instances[key] &&
345-
!instances[key]._isBeingDestroyed // do not reuse being destroyed instance
346-
) {
347-
cb(instances[key])
348-
} else if (isValid()) {
349-
setTimeout(() => {
350-
poll(cb, instances, key, isValid)
351-
}, 16)
332+
export function tryFinalizeTransition (record: RouteRecord, name: string) {
333+
if (record.instances[name] && record.pendingCbs[name]) {
334+
const instance = record.instances[name]
335+
const cb = record.pendingCbs[name]
336+
delete record.pendingCbs[name]
337+
cb(instance)
352338
}
353339
}

0 commit comments

Comments
 (0)