From abfa6fb3a485368ad1bcc39eac4eefa82f199705 Mon Sep 17 00:00:00 2001
From: liximomo <lixi@mufengcm.com>
Date: Thu, 26 Jul 2018 21:25:53 +0800
Subject: [PATCH 1/4] fix(compiler): normalize nested arrays when use
 functional components with v-for

#8468
---
 src/compiler/codegen/index.js                 |  4 +++-
 test/unit/features/options/functional.spec.js | 21 +++++++++++++++++++
 test/unit/modules/compiler/codegen.spec.js    | 14 ++++++-------
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js
index 1c912c4d96f..2c96e61a6e9 100644
--- a/src/compiler/codegen/index.js
+++ b/src/compiler/codegen/index.js
@@ -389,7 +389,9 @@ export function genChildren (
       el.tag !== 'template' &&
       el.tag !== 'slot'
     ) {
-      return (altGenElement || genElement)(el, state)
+      // because el may be a functional component and return an Array instead of a single root.
+      // In this case, just a simple normalization is needed
+      return `${(altGenElement || genElement)(el, state)},1`
     }
     const normalizationType = checkSkip
       ? getNormalizationType(children, state.maybeComponent)
diff --git a/test/unit/features/options/functional.spec.js b/test/unit/features/options/functional.spec.js
index 2c6abe95972..46100af83db 100644
--- a/test/unit/features/options/functional.spec.js
+++ b/test/unit/features/options/functional.spec.js
@@ -316,4 +316,25 @@ describe('Options functional', () => {
     triggerEvent(parent.$el.querySelector('.clickable'), 'click')
     waitForUpdate(assertMarkup).then(done)
   })
+
+  // #8468
+  it('should normalize nested arrays when use functional components with v-for', () => {
+    const Foo = {
+      functional: true,
+      props: {
+        name: {}
+      },
+      render (h, context) {
+        return [h('span', 'hi'), h('span', context.props.name)]
+      }
+    }
+    const vm = new Vue({
+      template: `<div><foo v-for="name in names" :name="name" /></div>`,
+      data: {
+        names: ['foo', 'bar']
+      },
+      components: { Foo }
+    }).$mount()
+    expect(vm.$el.innerHTML).toBe('<span>hi</span><span>foo</span><span>hi</span><span>bar</span>')
+  })
 })
diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js
index 93a27f3b245..8a8f202f1df 100644
--- a/test/unit/modules/compiler/codegen.spec.js
+++ b/test/unit/modules/compiler/codegen.spec.js
@@ -54,25 +54,25 @@ describe('codegen', () => {
   it('generate v-for directive', () => {
     assertCodegen(
       '<div><li v-for="item in items" :key="item.uid"></li></div>',
-      `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}))}`
+      `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}),1)}`
     )
     // iterator syntax
     assertCodegen(
       '<div><li v-for="(item, i) in items"></li></div>',
-      `with(this){return _c('div',_l((items),function(item,i){return _c('li')}))}`
+      `with(this){return _c('div',_l((items),function(item,i){return _c('li')}),1)}`
     )
     assertCodegen(
       '<div><li v-for="(item, key, index) in items"></li></div>',
-      `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}))}`
+      `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}),1)}`
     )
     // destructuring
     assertCodegen(
       '<div><li v-for="{ a, b } in items"></li></div>',
-      `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}))}`
+      `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}),1)}`
     )
     assertCodegen(
       '<div><li v-for="({ a, b }, key, index) in items"></li></div>',
-      `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}))}`
+      `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}),1)}`
     )
     // v-for with extra element
     assertCodegen(
@@ -126,7 +126,7 @@ describe('codegen', () => {
   it('generate ref on v-for', () => {
     assertCodegen(
       '<ul><li v-for="item in items" ref="component1"></li></ul>',
-      `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}))}`
+      `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}),1)}`
     )
   })
 
@@ -550,7 +550,7 @@ describe('codegen', () => {
   it('generate static trees inside v-for', () => {
     assertCodegen(
       `<div><div v-for="i in 10"><p><span></span></p></div></div>`,
-      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`,
+      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}),1)}`,
       [`with(this){return _c('p',[_c('span')])}`]
     )
   })

From 0c9b3958bbbf2d222b65d18076e42f875355daa3 Mon Sep 17 00:00:00 2001
From: Evan You <yyx990803@gmail.com>
Date: Tue, 23 Oct 2018 16:12:18 -0400
Subject: [PATCH 2/4] Update index.js

---
 src/compiler/codegen/index.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js
index 2c96e61a6e9..b1c4116696d 100644
--- a/src/compiler/codegen/index.js
+++ b/src/compiler/codegen/index.js
@@ -391,7 +391,8 @@ export function genChildren (
     ) {
       // because el may be a functional component and return an Array instead of a single root.
       // In this case, just a simple normalization is needed
-      return `${(altGenElement || genElement)(el, state)},1`
+      const normalizationType = state.maybeComponent(el) ? `,1` : ``
+      return `${(altGenElement || genElement)(el, state)}${normalizationType}`
     }
     const normalizationType = checkSkip
       ? getNormalizationType(children, state.maybeComponent)

From 5604ef1b87e3a2a72ae25aa55da96a5196bcde8b Mon Sep 17 00:00:00 2001
From: Evan You <yyx990803@gmail.com>
Date: Wed, 24 Oct 2018 14:01:26 -0400
Subject: [PATCH 3/4] Update codegen.spec.js

---
 test/unit/modules/compiler/codegen.spec.js | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js
index 8a8f202f1df..14ad1d48287 100644
--- a/test/unit/modules/compiler/codegen.spec.js
+++ b/test/unit/modules/compiler/codegen.spec.js
@@ -54,25 +54,25 @@ describe('codegen', () => {
   it('generate v-for directive', () => {
     assertCodegen(
       '<div><li v-for="item in items" :key="item.uid"></li></div>',
-      `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}),1)}`
+      `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}))}`
     )
     // iterator syntax
     assertCodegen(
       '<div><li v-for="(item, i) in items"></li></div>',
-      `with(this){return _c('div',_l((items),function(item,i){return _c('li')}),1)}`
+      `with(this){return _c('div',_l((items),function(item,i){return _c('li')}))}`
     )
     assertCodegen(
       '<div><li v-for="(item, key, index) in items"></li></div>',
-      `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}),1)}`
+      `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}))}`
     )
     // destructuring
     assertCodegen(
       '<div><li v-for="{ a, b } in items"></li></div>',
-      `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}),1)}`
+      `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}))}`
     )
     assertCodegen(
       '<div><li v-for="({ a, b }, key, index) in items"></li></div>',
-      `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}),1)}`
+      `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}))}`
     )
     // v-for with extra element
     assertCodegen(
@@ -126,7 +126,7 @@ describe('codegen', () => {
   it('generate ref on v-for', () => {
     assertCodegen(
       '<ul><li v-for="item in items" ref="component1"></li></ul>',
-      `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}),1)}`
+      `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}))}`
     )
   })
 

From 63012f8074469579d28399e54750be11744e6cef Mon Sep 17 00:00:00 2001
From: Evan You <yyx990803@gmail.com>
Date: Wed, 24 Oct 2018 14:01:55 -0400
Subject: [PATCH 4/4] Update codegen.spec.js

---
 test/unit/modules/compiler/codegen.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js
index 14ad1d48287..93a27f3b245 100644
--- a/test/unit/modules/compiler/codegen.spec.js
+++ b/test/unit/modules/compiler/codegen.spec.js
@@ -550,7 +550,7 @@ describe('codegen', () => {
   it('generate static trees inside v-for', () => {
     assertCodegen(
       `<div><div v-for="i in 10"><p><span></span></p></div></div>`,
-      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}),1)}`,
+      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`,
       [`with(this){return _c('p',[_c('span')])}`]
     )
   })