@@ -5,7 +5,7 @@ import { parseHTML } from './html-parser'
55import { parseText } from './text-parser'
66import { parseFilters } from './filter-parser'
77import { genAssignmentCode } from '../directives/model'
8- import { extend , cached , no , camelize , hyphenate , hasOwn } from 'shared/util'
8+ import { extend , cached , no , camelize , hyphenate } from 'shared/util'
99import { isIE , isEdge , isServerRendering } from 'core/util/env'
1010
1111import {
@@ -45,7 +45,6 @@ let postTransforms
4545let platformIsPreTag
4646let platformMustUseProp
4747let platformGetTagNamespace
48- let maybeComponent
4948
5049export function createASTElement (
5150 tag : string ,
@@ -75,8 +74,6 @@ export function parse (
7574 platformIsPreTag = options . isPreTag || no
7675 platformMustUseProp = options . mustUseProp || no
7776 platformGetTagNamespace = options . getTagNamespace || no
78- const isReservedTag = options . isReservedTag || no
79- maybeComponent = ( el : ASTElement ) => ! ! el . component || ! isReservedTag ( el . tag )
8077
8178 transforms = pluckModuleFunction ( options . modules , 'transformNode' )
8279 preTransforms = pluckModuleFunction ( options . modules , 'preTransformNode' )
@@ -102,7 +99,7 @@ export function parse (
10299
103100 function closeElement ( element ) {
104101 if ( ! inVPre && ! element . processed ) {
105- element = processElement ( element , options )
102+ element = processElement ( element , options , currentParent )
106103 }
107104 // tree management
108105 if ( ! stack . length && element !== root ) {
@@ -156,7 +153,7 @@ export function parse (
156153 { start : el . start }
157154 )
158155 }
159- if ( hasOwn ( el . attrsMap , 'v-for' ) ) {
156+ if ( el . attrsMap . hasOwnProperty ( 'v-for' ) ) {
160157 warnOnce (
161158 'Cannot use v-for on stateful component root element because ' +
162159 'it renders multiple elements.' ,
@@ -380,7 +377,8 @@ function processRawAttrs (el) {
380377
381378export function processElement (
382379 element : ASTElement ,
383- options : CompilerOptions
380+ options : CompilerOptions ,
381+ parent : ASTElement | undefined
384382) {
385383 processKey ( element )
386384
@@ -393,7 +391,7 @@ export function processElement (
393391 )
394392
395393 processRef ( element )
396- processSlot ( element )
394+ processSlot ( element , parent )
397395 processComponent ( element )
398396 for ( let i = 0 ; i < transforms . length ; i ++ ) {
399397 element = transforms [ i ] ( element , options ) || element
@@ -584,86 +582,19 @@ function processSlot (el) {
584582 )
585583 }
586584 el . slotScope = slotScope
587- if ( process . env . NODE_ENV !== 'production' && nodeHas$Slot ( el ) ) {
588- warn ( 'Unepxected mixed usage of `slot-scope` and `$slot`.' , el )
589- }
590- } else {
591- // 2.6 $slot support
592- // Context: https://github.com/vuejs/vue/issues/9180
593- // Ideally, all slots should be compiled as functions (this is what we
594- // are doing in 3.x), but for 2.x e want to preserve complete backwards
595- // compatibility, and maintain the exact same compilation output for any
596- // code that does not use the new syntax.
597-
598- // recursively check component children for presence of `$slot` in all
599- // expressions until running into a nested child component.
600- if ( maybeComponent ( el ) && childrenHas$Slot ( el ) ) {
601- processScopedSlots ( el )
602- }
603585 }
604586 const slotTarget = getBindingAttr ( el , 'slot' )
605587 if ( slotTarget ) {
606588 el . slotTarget = slotTarget === '""' ? '"default"' : slotTarget
607589 // preserve slot as an attribute for native shadow DOM compat
608590 // only for non-scoped slots.
609- if ( el . tag !== 'template' && ! el . slotScope && ! nodeHas$Slot ( el ) ) {
591+ if ( el . tag !== 'template' && ! el . slotScope ) {
610592 addAttr ( el , 'slot' , slotTarget , getRawBindingAttr ( el , 'slot' ) )
611593 }
612594 }
613595 }
614596}
615597
616- function childrenHas$Slot ( el ) : boolean {
617- return el . children ? el . children . some ( nodeHas$Slot ) : false
618- }
619-
620- const $slotRE = / ( ^ | [ ^ \w _ $ ] ) \$ s l o t ( $ | [ ^ \w _ $ ] ) /
621- function nodeHas$Slot ( node ) : boolean {
622- // caching
623- if ( hasOwn ( node , 'has$Slot' ) ) {
624- return ( node . has$Slot : any )
625- }
626- if ( node . type === 1 ) { // element
627- for ( const key in node . attrsMap ) {
628- if ( dirRE . test ( key ) && $slotRE . test ( node . attrsMap [ key ] ) ) {
629- return ( node . has$Slot = true )
630- }
631- }
632- return ( node . has$Slot = childrenHas$Slot ( node ) )
633- } else if ( node . type === 2 ) { // expression
634- // TODO more robust logic for checking $slot usage
635- return ( node . has$Slot = $slotRE . test ( node . expression ) )
636- }
637- return false
638- }
639-
640- function processScopedSlots ( el ) {
641- // 1. group children by slot target
642- const groups : any = { }
643- for ( let i = 0 ; i < el . children . length ; i ++ ) {
644- const child = el . children [ i ]
645- const target = child . slotTarget || '"default"'
646- if ( ! groups [ target ] ) {
647- groups [ target ] = [ ]
648- }
649- groups [ target ] . push ( child )
650- }
651- // 2. for each slot group, check if the group contains $slot
652- for ( const name in groups ) {
653- const group = groups [ name ]
654- if ( group . some ( nodeHas$Slot ) ) {
655- // 3. if a group contains $slot, all nodes in that group gets assigned
656- // as a scoped slot to el and removed from children
657- el . plain = false
658- const slots = el . scopedSlots || ( el . scopedSlots = { } )
659- const slotContainer = slots [ name ] = createASTElement ( 'template' , [ ] , el )
660- slotContainer . children = group
661- slotContainer . slotScope = '$slot'
662- el . children = el . children . filter ( c => group . indexOf ( c ) === - 1 )
663- }
664- }
665- }
666-
667598function processComponent ( el ) {
668599 let binding
669600 if ( ( binding = getBindingAttr ( el , 'is' ) ) ) {
0 commit comments