@@ -60,12 +60,13 @@ export function renderComponentRoot(
6060 } = instance
6161
6262 let result
63+ let fallthroughAttrs
6364 const prev = setCurrentRenderingInstance ( instance )
6465 if ( __DEV__ ) {
6566 accessedAttrs = false
6667 }
68+
6769 try {
68- let fallthroughAttrs
6970 if ( vnode . shapeFlag & ShapeFlags . STATEFUL_COMPONENT ) {
7071 // withProxy is a proxy with a different `has` trap only for
7172 // runtime-compiled render functions using `with` block.
@@ -110,127 +111,127 @@ export function renderComponentRoot(
110111 ? attrs
111112 : getFunctionalFallthrough ( attrs )
112113 }
114+ } catch ( err ) {
115+ blockStack . length = 0
116+ handleError ( err , instance , ErrorCodes . RENDER_FUNCTION )
117+ result = createVNode ( Comment )
118+ }
113119
114- // attr merging
115- // in dev mode, comments are preserved, and it's possible for a template
116- // to have comments along side the root element which makes it a fragment
117- let root = result
118- let setRoot : ( ( root : VNode ) => void ) | undefined = undefined
119- if (
120- __DEV__ &&
121- result . patchFlag > 0 &&
122- result . patchFlag & PatchFlags . DEV_ROOT_FRAGMENT
123- ) {
124- ; [ root , setRoot ] = getChildRoot ( result )
125- }
120+ // attr merging
121+ // in dev mode, comments are preserved, and it's possible for a template
122+ // to have comments along side the root element which makes it a fragment
123+ let root = result
124+ let setRoot : ( ( root : VNode ) => void ) | undefined = undefined
125+ if (
126+ __DEV__ &&
127+ result . patchFlag > 0 &&
128+ result . patchFlag & PatchFlags . DEV_ROOT_FRAGMENT
129+ ) {
130+ ; [ root , setRoot ] = getChildRoot ( result )
131+ }
126132
127- if ( fallthroughAttrs && inheritAttrs !== false ) {
128- const keys = Object . keys ( fallthroughAttrs )
129- const { shapeFlag } = root
130- if ( keys . length ) {
131- if ( shapeFlag & ( ShapeFlags . ELEMENT | ShapeFlags . COMPONENT ) ) {
132- if ( propsOptions && keys . some ( isModelListener ) ) {
133- // If a v-model listener (onUpdate:xxx) has a corresponding declared
134- // prop, it indicates this component expects to handle v-model and
135- // it should not fallthrough.
136- // related: #1543, #1643, #1989
137- fallthroughAttrs = filterModelListeners (
138- fallthroughAttrs ,
139- propsOptions
140- )
141- }
142- root = cloneVNode ( root , fallthroughAttrs )
143- } else if ( __DEV__ && ! accessedAttrs && root . type !== Comment ) {
144- const allAttrs = Object . keys ( attrs )
145- const eventAttrs : string [ ] = [ ]
146- const extraAttrs : string [ ] = [ ]
147- for ( let i = 0 , l = allAttrs . length ; i < l ; i ++ ) {
148- const key = allAttrs [ i ]
149- if ( isOn ( key ) ) {
150- // ignore v-model handlers when they fail to fallthrough
151- if ( ! isModelListener ( key ) ) {
152- // remove `on`, lowercase first letter to reflect event casing
153- // accurately
154- eventAttrs . push ( key [ 2 ] . toLowerCase ( ) + key . slice ( 3 ) )
155- }
156- } else {
157- extraAttrs . push ( key )
133+ if ( fallthroughAttrs && inheritAttrs !== false ) {
134+ const keys = Object . keys ( fallthroughAttrs )
135+ const { shapeFlag } = root
136+ if ( keys . length ) {
137+ if ( shapeFlag & ( ShapeFlags . ELEMENT | ShapeFlags . COMPONENT ) ) {
138+ if ( propsOptions && keys . some ( isModelListener ) ) {
139+ // If a v-model listener (onUpdate:xxx) has a corresponding declared
140+ // prop, it indicates this component expects to handle v-model and
141+ // it should not fallthrough.
142+ // related: #1543, #1643, #1989
143+ fallthroughAttrs = filterModelListeners (
144+ fallthroughAttrs ,
145+ propsOptions
146+ )
147+ }
148+ root = cloneVNode ( root , fallthroughAttrs )
149+ } else if ( __DEV__ && ! accessedAttrs && root . type !== Comment ) {
150+ const allAttrs = Object . keys ( attrs )
151+ const eventAttrs : string [ ] = [ ]
152+ const extraAttrs : string [ ] = [ ]
153+ for ( let i = 0 , l = allAttrs . length ; i < l ; i ++ ) {
154+ const key = allAttrs [ i ]
155+ if ( isOn ( key ) ) {
156+ // ignore v-model handlers when they fail to fallthrough
157+ if ( ! isModelListener ( key ) ) {
158+ // remove `on`, lowercase first letter to reflect event casing
159+ // accurately
160+ eventAttrs . push ( key [ 2 ] . toLowerCase ( ) + key . slice ( 3 ) )
158161 }
159- }
160- if ( extraAttrs . length ) {
161- warn (
162- `Extraneous non-props attributes (` +
163- `${ extraAttrs . join ( ', ' ) } ) ` +
164- `were passed to component but could not be automatically inherited ` +
165- `because component renders fragment or text root nodes.`
166- )
167- }
168- if ( eventAttrs . length ) {
169- warn (
170- `Extraneous non-emits event listeners (` +
171- `${ eventAttrs . join ( ', ' ) } ) ` +
172- `were passed to component but could not be automatically inherited ` +
173- `because component renders fragment or text root nodes. ` +
174- `If the listener is intended to be a component custom event listener only, ` +
175- `declare it using the "emits" option.`
176- )
162+ } else {
163+ extraAttrs . push ( key )
177164 }
178165 }
179- }
180- }
181-
182- if (
183- __COMPAT__ &&
184- isCompatEnabled ( DeprecationTypes . INSTANCE_ATTRS_CLASS_STYLE , instance ) &&
185- vnode . shapeFlag & ShapeFlags . STATEFUL_COMPONENT &&
186- root . shapeFlag & ( ShapeFlags . ELEMENT | ShapeFlags . COMPONENT )
187- ) {
188- const { class : cls , style } = vnode . props || { }
189- if ( cls || style ) {
190- if ( __DEV__ && inheritAttrs === false ) {
191- warnDeprecation (
192- DeprecationTypes . INSTANCE_ATTRS_CLASS_STYLE ,
193- instance ,
194- getComponentName ( instance . type )
166+ if ( extraAttrs . length ) {
167+ warn (
168+ `Extraneous non-props attributes (` +
169+ ` ${ extraAttrs . join ( ', ' ) } ) ` +
170+ `were passed to component but could not be automatically inherited ` +
171+ `because component renders fragment or text root nodes.`
172+ )
173+ }
174+ if ( eventAttrs . length ) {
175+ warn (
176+ `Extraneous non-emits event listeners (` +
177+ ` ${ eventAttrs . join ( ', ' ) } ) ` +
178+ `were passed to component but could not be automatically inherited ` +
179+ `because component renders fragment or text root nodes. ` +
180+ `If the listener is intended to be a component custom event listener only, ` +
181+ `declare it using the "emits" option.`
195182 )
196183 }
197- root = cloneVNode ( root , {
198- class : cls ,
199- style : style
200- } )
201184 }
202185 }
186+ }
203187
204- // inherit directives
205- if ( vnode . dirs ) {
206- if ( __DEV__ && ! isElementRoot ( root ) ) {
207- warn (
208- `Runtime directive used on component with non-element root node. ` +
209- `The directives will not function as intended.`
188+ if (
189+ __COMPAT__ &&
190+ isCompatEnabled ( DeprecationTypes . INSTANCE_ATTRS_CLASS_STYLE , instance ) &&
191+ vnode . shapeFlag & ShapeFlags . STATEFUL_COMPONENT &&
192+ root . shapeFlag & ( ShapeFlags . ELEMENT | ShapeFlags . COMPONENT )
193+ ) {
194+ const { class : cls , style } = vnode . props || { }
195+ if ( cls || style ) {
196+ if ( __DEV__ && inheritAttrs === false ) {
197+ warnDeprecation (
198+ DeprecationTypes . INSTANCE_ATTRS_CLASS_STYLE ,
199+ instance ,
200+ getComponentName ( instance . type )
210201 )
211202 }
212- root . dirs = root . dirs ? root . dirs . concat ( vnode . dirs ) : vnode . dirs
213- }
214- // inherit transition data
215- if ( vnode . transition ) {
216- if ( __DEV__ && ! isElementRoot ( root ) ) {
217- warn (
218- `Component inside <Transition> renders non-element root node ` +
219- `that cannot be animated.`
220- )
221- }
222- root . transition = vnode . transition
203+ root = cloneVNode ( root , {
204+ class : cls ,
205+ style : style
206+ } )
223207 }
208+ }
224209
225- if ( __DEV__ && setRoot ) {
226- setRoot ( root )
227- } else {
228- result = root
210+ // inherit directives
211+ if ( vnode . dirs ) {
212+ if ( __DEV__ && ! isElementRoot ( root ) ) {
213+ warn (
214+ `Runtime directive used on component with non-element root node. ` +
215+ `The directives will not function as intended.`
216+ )
229217 }
230- } catch ( err ) {
231- blockStack . length = 0
232- handleError ( err , instance , ErrorCodes . RENDER_FUNCTION )
233- result = createVNode ( Comment )
218+ root . dirs = root . dirs ? root . dirs . concat ( vnode . dirs ) : vnode . dirs
219+ }
220+ // inherit transition data
221+ if ( vnode . transition ) {
222+ if ( __DEV__ && ! isElementRoot ( root ) ) {
223+ warn (
224+ `Component inside <Transition> renders non-element root node ` +
225+ `that cannot be animated.`
226+ )
227+ }
228+ root . transition = vnode . transition
229+ }
230+
231+ if ( __DEV__ && setRoot ) {
232+ setRoot ( root )
233+ } else {
234+ result = root
234235 }
235236
236237 setCurrentRenderingInstance ( prev )
0 commit comments