Skip to content

Commit 53ab5d5

Browse files
authored
feat: attrs fallthrough (#14144)
1 parent 05b8dbd commit 53ab5d5

File tree

11 files changed

+845
-112
lines changed

11 files changed

+845
-112
lines changed

packages/runtime-core/src/componentRenderUtils.ts

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
305312
export 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)) {

packages/runtime-core/src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,3 +674,11 @@ export {
674674
* @internal
675675
*/
676676
export type { GenericComponent } from './component'
677+
678+
/**
679+
* @internal
680+
*/
681+
export {
682+
warnExtraneousAttributes,
683+
getFunctionalFallthrough,
684+
} from './componentRenderUtils'

0 commit comments

Comments
 (0)