@@ -1953,19 +1953,16 @@ var isReservedTag = function (tag) { return isHTMLTag(tag) || isSVG(tag); };
19531953
19541954//
19551955
1956- function compileFromString ( str ) {
1957- if ( ! vueTemplateCompiler . compileToFunctions ) {
1958- throwError (
1959- "vueTemplateCompiler is undefined, you must pass " +
1960- "precompiled components if vue-template-compiler is " +
1961- "undefined"
1962- ) ;
1963- }
1964- return vueTemplateCompiler . compileToFunctions ( str )
1965- }
1966-
19671956function compileTemplate ( component ) {
19681957 if ( component . template ) {
1958+ if ( ! vueTemplateCompiler . compileToFunctions ) {
1959+ throwError (
1960+ "vueTemplateCompiler is undefined, you must pass " +
1961+ "precompiled components if vue-template-compiler is " +
1962+ "undefined"
1963+ ) ;
1964+ }
1965+
19691966 if ( component . template . charAt ( '#' ) === '#' ) {
19701967 var el = document . querySelector ( component . template ) ;
19711968 if ( ! el ) {
@@ -1976,7 +1973,8 @@ function compileTemplate(component) {
19761973 component . template = el . innerHTML ;
19771974 }
19781975
1979- Object . assign ( component , vueTemplateCompiler . compileToFunctions ( component . template ) ) ;
1976+ Object . assign ( component , Object . assign ( { } , vueTemplateCompiler . compileToFunctions ( component . template ) ,
1977+ { name : component . name } ) ) ;
19801978 }
19811979
19821980 if ( component . components ) {
@@ -2035,7 +2033,7 @@ function extractInstanceOptions(options) {
20352033//
20362034
20372035function isDestructuringSlotScope ( slotScope ) {
2038- return slotScope [ 0 ] === '{' && slotScope [ slotScope . length - 1 ] === '}'
2036+ return / ^ { . * } $ / . test ( slotScope )
20392037}
20402038
20412039function getVueTemplateCompilerHelpers (
@@ -2076,7 +2074,36 @@ function validateEnvironment() {
20762074 }
20772075}
20782076
2079- var slotScopeRe = / < [ ^ > ] + s l o t - s c o p e = \" ( .+ ) \" / ;
2077+ function isScopedSlot ( slot ) {
2078+ if ( typeof slot === 'function' ) { return { match : null , slot : slot } }
2079+
2080+ var slotScopeRe = / < [ ^ > ] + s l o t - s c o p e = " ( .+ ) " / ;
2081+ var vSlotRe = / < t e m p l a t e v - s l o t (?: : .+ ) ? = " ( .+ ) " / ;
2082+ var shortVSlotRe = / < t e m p l a t e # .* = " ( .+ ) " / ;
2083+
2084+ var hasOldSlotScope = slot . match ( slotScopeRe ) ;
2085+ var hasVSlotScopeAttr = slot . match ( vSlotRe ) ;
2086+ var hasShortVSlotScopeAttr = slot . match ( shortVSlotRe ) ;
2087+
2088+ if ( hasOldSlotScope ) {
2089+ return { slot : slot , match : hasOldSlotScope }
2090+ } else if ( hasVSlotScopeAttr || hasShortVSlotScopeAttr ) {
2091+ // Strip v-slot and #slot attributes from `template` tag. compileToFunctions leaves empty `template` tag otherwise.
2092+ var sanitizedSlot = slot . replace (
2093+ / ( < t e m p l a t e ) ( [ ^ > ] + ) ( > .+ < \/ t e m p l a t e > ) / ,
2094+ '$1$3'
2095+ ) ;
2096+ return {
2097+ slot : sanitizedSlot ,
2098+ match : hasVSlotScopeAttr || hasShortVSlotScopeAttr
2099+ }
2100+ }
2101+ // we have no matches, so we just return
2102+ return {
2103+ slot : slot ,
2104+ match : null
2105+ }
2106+ }
20802107
20812108// Hide warning about <template> disallowed as root element
20822109function customWarn ( msg ) {
@@ -2098,14 +2125,18 @@ function createScopedSlots(
20982125 var loop = function ( scopedSlotName ) {
20992126 var slot = scopedSlotsOption [ scopedSlotName ] ;
21002127 var isFn = typeof slot === 'function' ;
2128+
2129+ var scopedSlotMatches = isScopedSlot ( slot ) ;
2130+
21012131 // Type check to silence flow (can't use isFn)
21022132 var renderFn =
21032133 typeof slot === 'function'
21042134 ? slot
2105- : vueTemplateCompiler . compileToFunctions ( slot , { warn : customWarn } ) . render ;
2135+ : vueTemplateCompiler . compileToFunctions ( scopedSlotMatches . slot , { warn : customWarn } )
2136+ . render ;
2137+
2138+ var slotScope = scopedSlotMatches . match && scopedSlotMatches . match [ 1 ] ;
21062139
2107- var hasSlotScopeAttr = ! isFn && slot . match ( slotScopeRe ) ;
2108- var slotScope = hasSlotScopeAttr && hasSlotScopeAttr [ 1 ] ;
21092140 scopedSlots [ scopedSlotName ] = function ( props ) {
21102141 var obj ;
21112142
@@ -2173,24 +2204,35 @@ function getCoreProperties(componentOptions) {
21732204}
21742205
21752206function createClassString ( staticClass , dynamicClass ) {
2176- if ( staticClass && dynamicClass ) {
2177- return staticClass + ' ' + dynamicClass
2207+ // :class="someComputedObject" can return a string, object or undefined
2208+ // if it is a string, we don't need to do anything special.
2209+ var evaluatedDynamicClass = dynamicClass ;
2210+
2211+ // if it is an object, eg { 'foo': true }, we need to evaluate it.
2212+ // see https://github.com/vuejs/vue-test-utils/issues/1474 for more context.
2213+ if ( typeof dynamicClass === 'object' ) {
2214+ evaluatedDynamicClass = Object . keys ( dynamicClass ) . reduce ( function ( acc , key ) {
2215+ if ( dynamicClass [ key ] ) {
2216+ return acc + ' ' + key
2217+ }
2218+ return acc
2219+ } , '' ) ;
2220+ }
2221+
2222+ if ( staticClass && evaluatedDynamicClass ) {
2223+ return staticClass + ' ' + evaluatedDynamicClass
21782224 }
2179- return staticClass || dynamicClass
2225+ return staticClass || evaluatedDynamicClass
21802226}
21812227
21822228function resolveOptions ( component , _Vue ) {
21832229 if ( isDynamicComponent ( component ) ) {
21842230 return { }
21852231 }
21862232
2187- if ( isConstructor ( component ) ) {
2188- return component . options
2189- }
2190- var options = _Vue . extend ( component ) . options ;
2191- component . _Ctor = { } ;
2192-
2193- return options
2233+ return isConstructor ( component )
2234+ ? component . options
2235+ : _Vue . extend ( component ) . options
21942236}
21952237
21962238function getScopedSlotRenderFunctions ( ctx ) {
@@ -2253,22 +2295,31 @@ function createStubFromComponent(
22532295 } } )
22542296}
22552297
2256- function createStubFromString (
2257- templateString ,
2298+ // DEPRECATED: converts string stub to template stub.
2299+ function createStubFromString ( templateString , name ) {
2300+ warn ( 'String stubs are deprecated and will be removed in future versions' ) ;
2301+
2302+ if ( templateContainsComponent ( templateString , name ) ) {
2303+ throwError ( 'options.stub cannot contain a circular reference' ) ;
2304+ }
2305+
2306+ return {
2307+ template : templateString ,
2308+ $_doNotStubChildren : true
2309+ }
2310+ }
2311+
2312+ function setStubComponentName (
2313+ stub ,
22582314 originalComponent ,
2259- name ,
22602315 _Vue
22612316) {
22622317 if ( originalComponent === void 0 ) originalComponent = { } ;
22632318
2264- if ( templateContainsComponent ( templateString , name ) ) {
2265- throwError ( 'options.stub cannot contain a circular reference' ) ;
2266- }
2267- var componentOptions = resolveOptions ( originalComponent , _Vue ) ;
2319+ if ( stub . name ) { return }
22682320
2269- return Object . assign ( { } , getCoreProperties ( componentOptions ) ,
2270- { $_doNotStubChildren : true } ,
2271- compileFromString ( templateString ) )
2321+ var componentOptions = resolveOptions ( originalComponent , _Vue ) ;
2322+ stub . name = getCoreProperties ( componentOptions ) . name ;
22722323}
22732324
22742325function validateStub ( stub ) {
@@ -2293,18 +2344,19 @@ function createStubsFromStubsObject(
22932344 return acc
22942345 }
22952346
2347+ var component = resolveComponent$1 ( originalComponents , stubName ) ;
2348+
22962349 if ( stub === true ) {
2297- var component = resolveComponent$1 ( originalComponents , stubName ) ;
22982350 acc [ stubName ] = createStubFromComponent ( component , stubName , _Vue ) ;
22992351 return acc
23002352 }
23012353
23022354 if ( typeof stub === 'string' ) {
2303- var component$1 = resolveComponent$1 ( originalComponents , stubName ) ;
2304- acc [ stubName ] = createStubFromString ( stub , component$1 , stubName , _Vue ) ;
2305- return acc
2355+ stub = createStubFromString ( stub , stubName ) ;
2356+ stubs [ stubName ] ;
23062357 }
23072358
2359+ setStubComponentName ( stub , component , _Vue ) ;
23082360 if ( componentNeedsCompiling ( stub ) ) {
23092361 compileTemplate ( stub ) ;
23102362 }
@@ -2326,7 +2378,6 @@ function shouldExtend(component, _Vue) {
23262378function extend ( component , _Vue ) {
23272379 var componentOptions = component . options ? component . options : component ;
23282380 var stub = _Vue . extend ( componentOptions ) ;
2329- componentOptions . _Ctor = { } ;
23302381 stub . options . $_vueTestUtils_original = component ;
23312382 stub . options . _base = _Vue ;
23322383 return stub
@@ -2445,6 +2496,13 @@ function createChildren(vm, h, ref) {
24452496 )
24462497}
24472498
2499+ function getValuesFromCallableOption ( optionValue ) {
2500+ if ( typeof optionValue === 'function' ) {
2501+ return optionValue . call ( this )
2502+ }
2503+ return optionValue
2504+ }
2505+
24482506function createInstance (
24492507 component ,
24502508 options ,
@@ -2499,15 +2557,18 @@ function createInstance(
24992557
25002558 // make sure all extends are based on this instance
25012559 var Constructor = _Vue . extend ( componentOptions ) . extend ( instanceOptions ) ;
2502- componentOptions . _Ctor = { } ;
25032560 Constructor . options . _base = _Vue ;
25042561
25052562 var scopedSlots = createScopedSlots ( options . scopedSlots , _Vue ) ;
25062563
25072564 var parentComponentOptions = options . parentComponent || { } ;
25082565
2509- parentComponentOptions . provide = options . provide ;
2510- parentComponentOptions . _provided = options . provide ;
2566+ var originalParentComponentProvide = parentComponentOptions . provide ;
2567+ parentComponentOptions . provide = function ( ) {
2568+ return Object . assign ( { } , getValuesFromCallableOption . call ( this , originalParentComponentProvide ) ,
2569+ getValuesFromCallableOption . call ( this , options . provide ) )
2570+ } ;
2571+
25112572 parentComponentOptions . $_doNotStubChildren = true ;
25122573 parentComponentOptions . _isFunctionalContainer = componentOptions . functional ;
25132574 parentComponentOptions . render = function ( h ) {
0 commit comments