@@ -16,13 +16,12 @@ function createVNodes (
1616) {
1717 var el = vueTemplateCompiler . compileToFunctions ( ( "<div>" + slotValue + "</div>" ) ) ;
1818 var _staticRenderFns = vm . _renderProxy . $options . staticRenderFns ;
19- // version < 2.5
20- if ( ! vm . _renderProxy . _staticTrees ) {
21- vm . _renderProxy . _staticTrees = [ ] ;
22- }
19+ var _staticTrees = vm . _renderProxy . _staticTrees ;
20+ vm . _renderProxy . _staticTrees = [ ] ;
2321 vm . _renderProxy . $options . staticRenderFns = el . staticRenderFns ;
2422 var vnode = el . render . call ( vm . _renderProxy , vm . $createElement ) ;
2523 vm . _renderProxy . $options . staticRenderFns = _staticRenderFns ;
24+ vm . _renderProxy . _staticTrees = _staticTrees ;
2625 return vnode . children
2726}
2827
@@ -34,6 +33,9 @@ function createVNodesForSlot (
3433 var vnode ;
3534 if ( typeof slotValue === 'string' ) {
3635 var vnodes = createVNodes ( vm , slotValue ) ;
36+ if ( vnodes . length > 1 ) {
37+ return vnodes
38+ }
3739 vnode = vnodes [ 0 ] ;
3840 } else {
3941 vnode = vm . $createElement ( slotValue ) ;
@@ -190,6 +192,12 @@ function isPlainObject (obj) {
190192 return Object . prototype . toString . call ( obj ) === '[object Object]'
191193}
192194
195+ function isRequiredComponent ( name ) {
196+ return (
197+ name === 'KeepAlive' || name === 'Transition' || name === 'TransitionGroup'
198+ )
199+ }
200+
193201//
194202
195203function compileTemplate ( component ) {
@@ -297,10 +305,14 @@ function createBlankStub (
297305 }
298306
299307 return Object . assign ( { } , getCoreProperties ( componentOptions ) ,
300- { render : function render ( h ) {
308+ { render : function render ( h , context ) {
301309 return h (
302310 tagName ,
303- ! componentOptions . functional && this . $slots . default
311+ {
312+ attrs : componentOptions . functional ? Object . assign ( { } , context . props ,
313+ context . data . attrs ) : Object . assign ( { } , this . $props )
314+ } ,
315+ context ? context . children : this . $slots . default
304316 )
305317 } } )
306318}
@@ -424,8 +436,8 @@ function requiresTemplateCompiler (slot) {
424436 if ( typeof slot === 'string' && ! vueTemplateCompiler . compileToFunctions ) {
425437 throwError (
426438 "vueTemplateCompiler is undefined, you must pass " +
427- "precompiled components if vue-template-compiler is " +
428- "undefined"
439+ "precompiled components if vue-template-compiler is " +
440+ "undefined"
429441 ) ;
430442 }
431443}
@@ -507,27 +519,22 @@ function getVueTemplateCompilerHelpers () {
507519 names . forEach ( function ( name ) {
508520 helpers [ name ] = vue . _renderProxy [ name ] ;
509521 } ) ;
522+ helpers . $createElement = vue . _renderProxy . $createElement ;
510523 return helpers
511524}
512525
513526function validateEnvironment ( ) {
514- if ( window . navigator . userAgent . match ( / P h a n t o m J S / i) ) {
515- throwError (
516- "the scopedSlots option does not support PhantomJS. " +
517- "Please use Puppeteer, or pass a component."
518- ) ;
519- }
520- if ( vueVersion < 2.5 ) {
521- throwError ( "the scopedSlots option is only supported in " + "vue@2.5+." ) ;
527+ if ( vueVersion < 2.1 ) {
528+ throwError ( "the scopedSlots option is only supported in vue@2.1+." ) ;
522529 }
523530}
524531
525- function validateTempldate ( template ) {
526- if ( template . trim ( ) . substr ( 0 , 9 ) === '<template' ) {
527- throwError (
528- "the scopedSlots option does not support a template " +
529- "tag as the root element."
530- ) ;
532+ var slotScopeRe = / < [ ^ > ] + s l o t - s c o p e = \" ( . + ) \" / ;
533+
534+ // Hide warning about <template> disallowed as root element
535+ function customWarn ( msg ) {
536+ if ( msg . indexOf ( 'Cannot use <template> as component root element' ) === - 1 ) {
537+ console . error ( msg ) ;
531538 }
532539}
533540
@@ -540,28 +547,35 @@ function createScopedSlots (
540547 }
541548 validateEnvironment ( ) ;
542549 var helpers = getVueTemplateCompilerHelpers ( ) ;
543- var loop = function ( name ) {
544- var template = scopedSlotsOption [ name ] ;
545- validateTempldate ( template ) ;
546- var render = vueTemplateCompiler . compileToFunctions ( template ) . render ;
547- var domParser = new window . DOMParser ( ) ;
548- var _document = domParser . parseFromString ( template , 'text/html' ) ;
549- var slotScope = _document . body . firstChild . getAttribute (
550- 'slot-scope'
551- ) ;
552- var isDestructuring = isDestructuringSlotScope ( slotScope ) ;
553- scopedSlots [ name ] = function ( props ) {
550+ var loop = function ( scopedSlotName ) {
551+ var slot = scopedSlotsOption [ scopedSlotName ] ;
552+ var isFn = typeof slot === 'function' ;
553+ // Type check to silence flow (can't use isFn)
554+ var renderFn = typeof slot === 'function'
555+ ? slot
556+ : vueTemplateCompiler . compileToFunctions ( slot , { warn : customWarn } ) . render ;
557+
558+ var hasSlotScopeAttr = ! isFn && slot . match ( slotScopeRe ) ;
559+ var slotScope = hasSlotScopeAttr && hasSlotScopeAttr [ 1 ] ;
560+ scopedSlots [ scopedSlotName ] = function ( props ) {
554561 var obj ;
555562
556- if ( isDestructuring ) {
557- return render . call ( Object . assign ( { } , helpers , props ) )
563+ var res ;
564+ if ( isFn ) {
565+ res = renderFn . call ( Object . assign ( { } , helpers ) , props ) ;
566+ } else if ( slotScope && ! isDestructuringSlotScope ( slotScope ) ) {
567+ res = renderFn . call ( Object . assign ( { } , helpers , ( obj = { } , obj [ slotScope ] = props , obj ) ) ) ;
568+ } else if ( slotScope && isDestructuringSlotScope ( slotScope ) ) {
569+ res = renderFn . call ( Object . assign ( { } , helpers , props ) ) ;
558570 } else {
559- return render . call ( Object . assign ( { } , helpers , ( obj = { } , obj [ slotScope ] = props , obj ) ) )
571+ res = renderFn . call ( Object . assign ( { } , helpers , { props : props } ) ) ;
560572 }
573+ // res is Array if <template> is a root element
574+ return Array . isArray ( res ) ? res [ 0 ] : res
561575 } ;
562576 } ;
563577
564- for ( var name in scopedSlotsOption ) loop ( name ) ;
578+ for ( var scopedSlotName in scopedSlotsOption ) loop ( scopedSlotName ) ;
565579 return scopedSlots
566580}
567581
@@ -619,24 +633,39 @@ function createInstance (
619633
620634 addEventLogger ( _Vue ) ;
621635
636+ // Replace globally registered components with components extended
637+ // from localVue. This makes sure the beforeMount mixins to add stubs
638+ // is applied to globally registered components.
639+ // Vue version must be 2.3 or greater, because of a bug resolving
640+ // extended constructor options (https://github.com/vuejs/vue/issues/4976)
641+ if ( vueVersion > 2.2 ) {
642+ for ( var c in _Vue . options . components ) {
643+ if ( ! isRequiredComponent ( c ) ) {
644+ _Vue . component ( c , _Vue . extend ( _Vue . options . components [ c ] ) ) ;
645+ }
646+ }
647+ }
648+
622649 var stubComponents = createComponentStubs (
623- // $FlowIgnore
624650 component . components ,
625651 // $FlowIgnore
626652 options . stubs
627653 ) ;
628654 if ( options . stubs ) {
629655 instanceOptions . components = Object . assign ( { } , instanceOptions . components ,
630- // $FlowIgnore
631656 stubComponents ) ;
632657 }
658+ function addStubComponentsMixin ( ) {
659+ Object . assign (
660+ this . $options . components ,
661+ stubComponents
662+ ) ;
663+ }
633664 _Vue . mixin ( {
634- created : function created ( ) {
635- Object . assign (
636- this . $options . components ,
637- stubComponents
638- ) ;
639- }
665+ beforeMount : addStubComponentsMixin ,
666+ // beforeCreate is for components created in node, which
667+ // never mount
668+ beforeCreate : addStubComponentsMixin
640669 } ) ;
641670 Object . keys ( componentOptions . components || { } ) . forEach ( function ( c ) {
642671 if (
@@ -663,7 +692,9 @@ function createInstance (
663692 component . options . _base = _Vue ;
664693 }
665694
666- var Constructor = vueVersion < 2.3 && typeof component === 'function'
695+ // when component constructed by Vue.extend,
696+ // use its own extend method to keep component information
697+ var Constructor = typeof component === 'function'
667698 ? component . extend ( instanceOptions )
668699 : _Vue . extend ( component ) . extend ( instanceOptions ) ;
669700
@@ -708,9 +739,11 @@ function createInstance (
708739 Constructor ,
709740 {
710741 ref : 'vm' ,
711- props : options . propsData ,
712742 on : options . listeners ,
713- attrs : options . attrs ,
743+ attrs : Object . assign ( { } , options . attrs ,
744+ // pass as attrs so that inheritAttrs works correctly
745+ // propsData should take precedence over attrs
746+ options . propsData ) ,
714747 scopedSlots : scopedSlots
715748 } ,
716749 slots
0 commit comments