|
|
@@ -60,12 +60,13 @@ export function renderComponentRoot(
|
|
|
} = instance
|
|
|
|
|
|
let result
|
|
|
+ let fallthroughAttrs
|
|
|
const prev = setCurrentRenderingInstance(instance)
|
|
|
if (__DEV__) {
|
|
|
accessedAttrs = false
|
|
|
}
|
|
|
+
|
|
|
try {
|
|
|
- let fallthroughAttrs
|
|
|
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
|
|
|
// withProxy is a proxy with a different `has` trap only for
|
|
|
// runtime-compiled render functions using `with` block.
|
|
|
@@ -110,127 +111,127 @@ export function renderComponentRoot(
|
|
|
? attrs
|
|
|
: getFunctionalFallthrough(attrs)
|
|
|
}
|
|
|
+ } catch (err) {
|
|
|
+ blockStack.length = 0
|
|
|
+ handleError(err, instance, ErrorCodes.RENDER_FUNCTION)
|
|
|
+ result = createVNode(Comment)
|
|
|
+ }
|
|
|
|
|
|
- // attr merging
|
|
|
- // in dev mode, comments are preserved, and it's possible for a template
|
|
|
- // to have comments along side the root element which makes it a fragment
|
|
|
- let root = result
|
|
|
- let setRoot: ((root: VNode) => void) | undefined = undefined
|
|
|
- if (
|
|
|
- __DEV__ &&
|
|
|
- result.patchFlag > 0 &&
|
|
|
- result.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
|
|
|
- ) {
|
|
|
- ;[root, setRoot] = getChildRoot(result)
|
|
|
- }
|
|
|
+ // attr merging
|
|
|
+ // in dev mode, comments are preserved, and it's possible for a template
|
|
|
+ // to have comments along side the root element which makes it a fragment
|
|
|
+ let root = result
|
|
|
+ let setRoot: ((root: VNode) => void) | undefined = undefined
|
|
|
+ if (
|
|
|
+ __DEV__ &&
|
|
|
+ result.patchFlag > 0 &&
|
|
|
+ result.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
|
|
|
+ ) {
|
|
|
+ ;[root, setRoot] = getChildRoot(result)
|
|
|
+ }
|
|
|
|
|
|
- if (fallthroughAttrs && inheritAttrs !== false) {
|
|
|
- const keys = Object.keys(fallthroughAttrs)
|
|
|
- const { shapeFlag } = root
|
|
|
- if (keys.length) {
|
|
|
- if (shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.COMPONENT)) {
|
|
|
- if (propsOptions && keys.some(isModelListener)) {
|
|
|
- // If a v-model listener (onUpdate:xxx) has a corresponding declared
|
|
|
- // prop, it indicates this component expects to handle v-model and
|
|
|
- // it should not fallthrough.
|
|
|
- // related: #1543, #1643, #1989
|
|
|
- fallthroughAttrs = filterModelListeners(
|
|
|
- fallthroughAttrs,
|
|
|
- propsOptions
|
|
|
- )
|
|
|
- }
|
|
|
- root = cloneVNode(root, fallthroughAttrs)
|
|
|
- } else if (__DEV__ && !accessedAttrs && root.type !== Comment) {
|
|
|
- const allAttrs = Object.keys(attrs)
|
|
|
- const eventAttrs: string[] = []
|
|
|
- const extraAttrs: string[] = []
|
|
|
- for (let i = 0, l = allAttrs.length; i < l; i++) {
|
|
|
- const key = allAttrs[i]
|
|
|
- if (isOn(key)) {
|
|
|
- // ignore v-model handlers when they fail to fallthrough
|
|
|
- if (!isModelListener(key)) {
|
|
|
- // remove `on`, lowercase first letter to reflect event casing
|
|
|
- // accurately
|
|
|
- eventAttrs.push(key[2].toLowerCase() + key.slice(3))
|
|
|
- }
|
|
|
- } else {
|
|
|
- extraAttrs.push(key)
|
|
|
+ if (fallthroughAttrs && inheritAttrs !== false) {
|
|
|
+ const keys = Object.keys(fallthroughAttrs)
|
|
|
+ const { shapeFlag } = root
|
|
|
+ if (keys.length) {
|
|
|
+ if (shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.COMPONENT)) {
|
|
|
+ if (propsOptions && keys.some(isModelListener)) {
|
|
|
+ // If a v-model listener (onUpdate:xxx) has a corresponding declared
|
|
|
+ // prop, it indicates this component expects to handle v-model and
|
|
|
+ // it should not fallthrough.
|
|
|
+ // related: #1543, #1643, #1989
|
|
|
+ fallthroughAttrs = filterModelListeners(
|
|
|
+ fallthroughAttrs,
|
|
|
+ propsOptions
|
|
|
+ )
|
|
|
+ }
|
|
|
+ root = cloneVNode(root, fallthroughAttrs)
|
|
|
+ } else if (__DEV__ && !accessedAttrs && root.type !== Comment) {
|
|
|
+ const allAttrs = Object.keys(attrs)
|
|
|
+ const eventAttrs: string[] = []
|
|
|
+ const extraAttrs: string[] = []
|
|
|
+ for (let i = 0, l = allAttrs.length; i < l; i++) {
|
|
|
+ const key = allAttrs[i]
|
|
|
+ if (isOn(key)) {
|
|
|
+ // ignore v-model handlers when they fail to fallthrough
|
|
|
+ if (!isModelListener(key)) {
|
|
|
+ // remove `on`, lowercase first letter to reflect event casing
|
|
|
+ // accurately
|
|
|
+ eventAttrs.push(key[2].toLowerCase() + key.slice(3))
|
|
|
}
|
|
|
- }
|
|
|
- if (extraAttrs.length) {
|
|
|
- warn(
|
|
|
- `Extraneous non-props attributes (` +
|
|
|
- `${extraAttrs.join(', ')}) ` +
|
|
|
- `were passed to component but could not be automatically inherited ` +
|
|
|
- `because component renders fragment or text root nodes.`
|
|
|
- )
|
|
|
- }
|
|
|
- if (eventAttrs.length) {
|
|
|
- warn(
|
|
|
- `Extraneous non-emits event listeners (` +
|
|
|
- `${eventAttrs.join(', ')}) ` +
|
|
|
- `were passed to component but could not be automatically inherited ` +
|
|
|
- `because component renders fragment or text root nodes. ` +
|
|
|
- `If the listener is intended to be a component custom event listener only, ` +
|
|
|
- `declare it using the "emits" option.`
|
|
|
- )
|
|
|
+ } else {
|
|
|
+ extraAttrs.push(key)
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (
|
|
|
- __COMPAT__ &&
|
|
|
- isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance) &&
|
|
|
- vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT &&
|
|
|
- root.shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.COMPONENT)
|
|
|
- ) {
|
|
|
- const { class: cls, style } = vnode.props || {}
|
|
|
- if (cls || style) {
|
|
|
- if (__DEV__ && inheritAttrs === false) {
|
|
|
- warnDeprecation(
|
|
|
- DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE,
|
|
|
- instance,
|
|
|
- getComponentName(instance.type)
|
|
|
+ if (extraAttrs.length) {
|
|
|
+ warn(
|
|
|
+ `Extraneous non-props attributes (` +
|
|
|
+ `${extraAttrs.join(', ')}) ` +
|
|
|
+ `were passed to component but could not be automatically inherited ` +
|
|
|
+ `because component renders fragment or text root nodes.`
|
|
|
+ )
|
|
|
+ }
|
|
|
+ if (eventAttrs.length) {
|
|
|
+ warn(
|
|
|
+ `Extraneous non-emits event listeners (` +
|
|
|
+ `${eventAttrs.join(', ')}) ` +
|
|
|
+ `were passed to component but could not be automatically inherited ` +
|
|
|
+ `because component renders fragment or text root nodes. ` +
|
|
|
+ `If the listener is intended to be a component custom event listener only, ` +
|
|
|
+ `declare it using the "emits" option.`
|
|
|
)
|
|
|
}
|
|
|
- root = cloneVNode(root, {
|
|
|
- class: cls,
|
|
|
- style: style
|
|
|
- })
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // inherit directives
|
|
|
- if (vnode.dirs) {
|
|
|
- if (__DEV__ && !isElementRoot(root)) {
|
|
|
- warn(
|
|
|
- `Runtime directive used on component with non-element root node. ` +
|
|
|
- `The directives will not function as intended.`
|
|
|
+ if (
|
|
|
+ __COMPAT__ &&
|
|
|
+ isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance) &&
|
|
|
+ vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT &&
|
|
|
+ root.shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.COMPONENT)
|
|
|
+ ) {
|
|
|
+ const { class: cls, style } = vnode.props || {}
|
|
|
+ if (cls || style) {
|
|
|
+ if (__DEV__ && inheritAttrs === false) {
|
|
|
+ warnDeprecation(
|
|
|
+ DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE,
|
|
|
+ instance,
|
|
|
+ getComponentName(instance.type)
|
|
|
)
|
|
|
}
|
|
|
- root.dirs = root.dirs ? root.dirs.concat(vnode.dirs) : vnode.dirs
|
|
|
- }
|
|
|
- // inherit transition data
|
|
|
- if (vnode.transition) {
|
|
|
- if (__DEV__ && !isElementRoot(root)) {
|
|
|
- warn(
|
|
|
- `Component inside <Transition> renders non-element root node ` +
|
|
|
- `that cannot be animated.`
|
|
|
- )
|
|
|
- }
|
|
|
- root.transition = vnode.transition
|
|
|
+ root = cloneVNode(root, {
|
|
|
+ class: cls,
|
|
|
+ style: style
|
|
|
+ })
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (__DEV__ && setRoot) {
|
|
|
- setRoot(root)
|
|
|
- } else {
|
|
|
- result = root
|
|
|
+ // inherit directives
|
|
|
+ if (vnode.dirs) {
|
|
|
+ if (__DEV__ && !isElementRoot(root)) {
|
|
|
+ warn(
|
|
|
+ `Runtime directive used on component with non-element root node. ` +
|
|
|
+ `The directives will not function as intended.`
|
|
|
+ )
|
|
|
}
|
|
|
- } catch (err) {
|
|
|
- blockStack.length = 0
|
|
|
- handleError(err, instance, ErrorCodes.RENDER_FUNCTION)
|
|
|
- result = createVNode(Comment)
|
|
|
+ root.dirs = root.dirs ? root.dirs.concat(vnode.dirs) : vnode.dirs
|
|
|
+ }
|
|
|
+ // inherit transition data
|
|
|
+ if (vnode.transition) {
|
|
|
+ if (__DEV__ && !isElementRoot(root)) {
|
|
|
+ warn(
|
|
|
+ `Component inside <Transition> renders non-element root node ` +
|
|
|
+ `that cannot be animated.`
|
|
|
+ )
|
|
|
+ }
|
|
|
+ root.transition = vnode.transition
|
|
|
+ }
|
|
|
+
|
|
|
+ if (__DEV__ && setRoot) {
|
|
|
+ setRoot(root)
|
|
|
+ } else {
|
|
|
+ result = root
|
|
|
}
|
|
|
|
|
|
setCurrentRenderingInstance(prev)
|