|
1 | 1 | /* @flow */
|
2 | 2 |
|
3 |
| -import VNode from './vnode' |
| 3 | +import VNode, { cloneVNode } from './vnode' |
4 | 4 | import { createElement } from './create-element'
|
5 | 5 | import { resolveInject } from '../instance/inject'
|
6 | 6 | import { normalizeChildren } from '../vdom/helpers/normalize-children'
|
@@ -32,6 +32,9 @@ export function FunctionalRenderContext (
|
32 | 32 | // $flow-disable-line
|
33 | 33 | contextVm._original = parent
|
34 | 34 | } else {
|
| 35 | + // the context vm passed in is a functional context as well. |
| 36 | + // in this case we want to make sure we are able to get a hold to the |
| 37 | + // real context instance. |
35 | 38 | contextVm = parent
|
36 | 39 | // $flow-disable-line
|
37 | 40 | parent = parent._original
|
@@ -102,23 +105,28 @@ export function createFunctionalComponent (
|
102 | 105 | const vnode = options.render.call(null, renderContext._c, renderContext)
|
103 | 106 |
|
104 | 107 | if (vnode instanceof VNode) {
|
105 |
| - setFunctionalContextForVNode(vnode, data, contextVm, options) |
106 |
| - return vnode |
| 108 | + return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options) |
107 | 109 | } else if (Array.isArray(vnode)) {
|
108 | 110 | const vnodes = normalizeChildren(vnode) || []
|
| 111 | + const res = new Array(vnodes.length) |
109 | 112 | for (let i = 0; i < vnodes.length; i++) {
|
110 |
| - setFunctionalContextForVNode(vnodes[i], data, contextVm, options) |
| 113 | + res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options) |
111 | 114 | }
|
112 |
| - return vnodes |
| 115 | + return res |
113 | 116 | }
|
114 | 117 | }
|
115 | 118 |
|
116 |
| -function setFunctionalContextForVNode (vnode, data, vm, options) { |
117 |
| - vnode.fnContext = vm |
118 |
| - vnode.fnOptions = options |
| 119 | +function cloneAndMarkFunctionalResult (vnode, data, contextVm, options) { |
| 120 | + // #7817 clone node before setting fnContext, otherwise if the node is reused |
| 121 | + // (e.g. it was from a cached normal slot) the fnContext causes named slots |
| 122 | + // that should not be matched to match. |
| 123 | + const clone = cloneVNode(vnode) |
| 124 | + clone.fnContext = contextVm |
| 125 | + clone.fnOptions = options |
119 | 126 | if (data.slot) {
|
120 |
| - (vnode.data || (vnode.data = {})).slot = data.slot |
| 127 | + (clone.data || (clone.data = {})).slot = data.slot |
121 | 128 | }
|
| 129 | + return clone |
122 | 130 | }
|
123 | 131 |
|
124 | 132 | function mergeProps (to, from) {
|
|
0 commit comments