@@ -169,40 +169,7 @@ export function renderComponentRoot(
169169 }
170170 root = cloneVNode ( root , fallthroughAttrs , false , true )
171171 } else if ( __DEV__ && ! accessedAttrs && root . type !== Comment ) {
172- const allAttrs = Object . keys ( attrs )
173- const eventAttrs : string [ ] = [ ]
174- const extraAttrs : string [ ] = [ ]
175- for ( let i = 0 , l = allAttrs . length ; i < l ; i ++ ) {
176- const key = allAttrs [ i ]
177- if ( isOn ( key ) ) {
178- // ignore v-model handlers when they fail to fallthrough
179- if ( ! isModelListener ( key ) ) {
180- // remove `on`, lowercase first letter to reflect event casing
181- // accurately
182- eventAttrs . push ( key [ 2 ] . toLowerCase ( ) + key . slice ( 3 ) )
183- }
184- } else {
185- extraAttrs . push ( key )
186- }
187- }
188- if ( extraAttrs . length ) {
189- warn (
190- `Extraneous non-props attributes (` +
191- `${ extraAttrs . join ( ', ' ) } ) ` +
192- `were passed to component but could not be automatically inherited ` +
193- `because component renders fragment or text or teleport root nodes.` ,
194- )
195- }
196- if ( eventAttrs . length ) {
197- warn (
198- `Extraneous non-emits event listeners (` +
199- `${ eventAttrs . join ( ', ' ) } ) ` +
200- `were passed to component but could not be automatically inherited ` +
201- `because component renders fragment or text root nodes. ` +
202- `If the listener is intended to be a component custom event listener only, ` +
203- `declare it using the "emits" option.` ,
204- )
205- }
172+ warnExtraneousAttributes ( attrs )
206173 }
207174 }
208175 }
@@ -302,6 +269,46 @@ const getChildRoot = (vnode: VNode): [VNode, SetRootFn] => {
302269 return [ normalizeVNode ( childRoot ) , setRoot ]
303270}
304271
272+ /**
273+ * Dev only
274+ */
275+ export function warnExtraneousAttributes ( attrs : Record < string , any > ) : void {
276+ const allAttrs = Object . keys ( attrs )
277+ const eventAttrs : string [ ] = [ ]
278+ const extraAttrs : string [ ] = [ ]
279+ for ( let i = 0 , l = allAttrs . length ; i < l ; i ++ ) {
280+ const key = allAttrs [ i ]
281+ if ( isOn ( key ) ) {
282+ // ignore v-model handlers when they fail to fallthrough
283+ if ( ! isModelListener ( key ) ) {
284+ // remove `on`, lowercase first letter to reflect event casing
285+ // accurately
286+ eventAttrs . push ( key [ 2 ] . toLowerCase ( ) + key . slice ( 3 ) )
287+ }
288+ } else {
289+ extraAttrs . push ( key )
290+ }
291+ }
292+ if ( extraAttrs . length ) {
293+ warn (
294+ `Extraneous non-props attributes (` +
295+ `${ extraAttrs . join ( ', ' ) } ) ` +
296+ `were passed to component but could not be automatically inherited ` +
297+ `because component renders fragment or text or teleport root nodes.` ,
298+ )
299+ }
300+ if ( eventAttrs . length ) {
301+ warn (
302+ `Extraneous non-emits event listeners (` +
303+ `${ eventAttrs . join ( ', ' ) } ) ` +
304+ `were passed to component but could not be automatically inherited ` +
305+ `because component renders fragment or text root nodes. ` +
306+ `If the listener is intended to be a component custom event listener only, ` +
307+ `declare it using the "emits" option.` ,
308+ )
309+ }
310+ }
311+
305312export function filterSingleRoot (
306313 children : VNodeArrayChildren ,
307314 recurse = true ,
@@ -334,7 +341,7 @@ export function filterSingleRoot(
334341 return singleRoot
335342}
336343
337- const getFunctionalFallthrough = ( attrs : Data ) : Data | undefined => {
344+ export const getFunctionalFallthrough = ( attrs : Data ) : Data | undefined => {
338345 let res : Data | undefined
339346 for ( const key in attrs ) {
340347 if ( key === 'class' || key === 'style' || isOn ( key ) ) {
0 commit comments