From 3e0aef2107999a9f24ff1d7f7cf89a0ddeff4a16 Mon Sep 17 00:00:00 2001 From: Matt Barlow Date: Sat, 26 May 2018 01:05:14 +0100 Subject: [PATCH] fix(#7913): Prevent erroneous warning when using inside slot-scope Because slotNodes inside a slot-scope context are already set to _rendered = true after initial render, the warning for duplicate slot presence always fires when a slot-scope prop change triggers a re-render. With this change, the compiler tracks whether any slot-scoped elements have been encountered at the point the slot is compiled. If so, the direct ancestors of the slot are checked for slot-scope presence, and if found, the warning is supressed. This is admittedly not a perfect solution, as within a slot-scope context the warning now does not fire even when there _are_ duplicate slots, but I couldn't find a good way to get around that. fix #7913 --- src/compiler/codegen/index.js | 23 +++++++++++-------- .../instance/render-helpers/render-slot.js | 5 ++-- test/unit/modules/compiler/codegen.spec.js | 6 ++--- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 1c912c4d96..d34c700d85 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -18,6 +18,7 @@ export class CodegenState { maybeComponent: (el: ASTElement) => boolean; onceId: number; staticRenderFns: Array; + slotScopeinAst: boolean; constructor (options: CompilerOptions) { this.options = options @@ -29,6 +30,8 @@ export class CodegenState { this.maybeComponent = (el: ASTElement) => !isReservedTag(el.tag) this.onceId = 0 this.staticRenderFns = [] + // we can skip checks for slot-scope parents if we haven't seen any + this.slotScopeinAst = false } } @@ -50,6 +53,7 @@ export function generate ( } export function genElement (el: ASTElement, state: CodegenState): string { + if (el.slotScope) state.slotScopeinAst = true if (el.staticRoot && !el.staticProcessed) { return genStatic(el, state) } else if (el.once && !el.onceProcessed) { @@ -456,19 +460,18 @@ export function genComment (comment: ASTText): string { function genSlot (el: ASTElement, state: CodegenState): string { const slotName = el.slotName || '"default"' const children = genChildren(el, state) - let res = `_t(${slotName}${children ? `,${children}` : ''}` const attrs = el.attrs && `{${el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',')}}` const bind = el.attrsMap['v-bind'] - if ((attrs || bind) && !children) { - res += `,null` - } - if (attrs) { - res += `,${attrs}` - } - if (bind) { - res += `${attrs ? '' : ',null'},${bind}` + let inScopedSlot = false + let ancestor = el + if (process.env.NODE_ENV !== 'production' && state.slotScopeinAst) { + while (!inScopedSlot && ancestor.parent) { + if (ancestor.slotScope) inScopedSlot = true + ancestor = ancestor.parent + } } - return res + ')' + return `_t(${slotName},${children || 'null'},${attrs || 'null'},` + + `${bind || 'null'},${inScopedSlot ? 'true' : 'false'})` } // componentName is el.component, take it as argument to shun flow's pessimistic refinement diff --git a/src/core/instance/render-helpers/render-slot.js b/src/core/instance/render-helpers/render-slot.js index a58daa74e6..4eaa8b6070 100644 --- a/src/core/instance/render-helpers/render-slot.js +++ b/src/core/instance/render-helpers/render-slot.js @@ -9,7 +9,8 @@ export function renderSlot ( name: string, fallback: ?Array, props: ?Object, - bindObject: ?Object + bindObject: ?Object, + inSlotScope: ?boolean ): ?Array { const scopedSlotFn = this.$scopedSlots[name] let nodes @@ -29,7 +30,7 @@ export function renderSlot ( const slotNodes = this.$slots[name] // warn duplicate slot usage if (slotNodes) { - if (process.env.NODE_ENV !== 'production' && slotNodes._rendered) { + if (process.env.NODE_ENV !== 'production' && !inSlotScope && slotNodes._rendered) { warn( `Duplicate presence of slot "${name}" found in the same render tree ` + `- this will likely cause render errors.`, diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 93a27f3b24..6d19496875 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -161,21 +161,21 @@ describe('codegen', () => { it('generate single slot', () => { assertCodegen( '
', - `with(this){return _c('div',[_t("default")],2)}` + `with(this){return _c('div',[_t("default",null,null,null,false)],2)}` ) }) it('generate named slot', () => { assertCodegen( '
', - `with(this){return _c('div',[_t("one")],2)}` + `with(this){return _c('div',[_t("one",null,null,null,false)],2)}` ) }) it('generate slot fallback content', () => { assertCodegen( '
hi
', - `with(this){return _c('div',[_t("default",[_c('div',[_v("hi")])])],2)}` + `with(this){return _c('div',[_t("default",[_c('div',[_v("hi")])],null,null,false)],2)}` ) })