99 getStatefulHookValue ,
1010 TYPE_COMPONENT ,
1111 isRoot ,
12+ getVNodeId ,
1213} from "./bindings" ;
1314import { RendererConfig } from "../shared/renderer" ;
1415import { Renderer } from "../renderer" ;
@@ -31,6 +32,8 @@ import { getRenderReasonPre, RenderReasonTmpData } from "./renderReason";
3132export interface VNodeV11 < P = Record < string , unknown > > {
3233 type : ComponentType < P > | string | null ;
3334 props : P ;
35+ _vnodeId ?: number ;
36+ __v ?: number ;
3437}
3538
3639export interface OptionsV11 {
@@ -63,6 +66,7 @@ export interface OptionsV11 {
6366 _catchError ?( error : any , internal : Internal ) : void ;
6467 __e ?( error : any , internal : Internal ) : void ;
6568
69+ vnode ( vnode : VNodeV11 ) : void ;
6670 _internal ?( internal : Internal , vnode : VNodeV11 | string ) : void ;
6771 __i ?( internal : Internal , vnode : VNodeV11 | string ) : void ;
6872
@@ -107,21 +111,27 @@ export function setupOptionsV11(
107111 const timings = createVNodeTimings < Internal > ( ) ;
108112 let renderReasons = new Map < Internal , RenderReasonData > ( ) ;
109113 let reasonTmpData = new Map < Internal , RenderReasonTmpData > ( ) ;
110- const owners = new Map ( ) ;
114+ const vnodeIdToOwner = new Map < number , Internal > ( ) ;
115+ const owners = new Map < Internal , Internal > ( ) ;
116+ let ownerStack : Internal [ ] = [ ] ;
111117
112118 const o = options ;
113119
114120 // Store (possible) previous hooks so that we don't overwrite them
115- const prevVNodeHook = options . _internal ;
121+ const prevVNodeHook = options . vnode ;
122+ const prevInternalHook = options . _internal || o . __i ;
116123 const prevCommitRoot = o . _commit || o . __c ;
117124 const prevBeforeUnmount = options . unmount ;
118125 const prevBeforeDiff = o . _diff || o . __b ;
126+ const prevRender = o . _render || o . __r ;
119127 const prevAfterDiff = options . diffed ;
120128 let prevHook = o . _hook || o . __h ;
121129 let prevUseDebugValue = options . useDebugValue ;
122130 // @ts -ignore
123131 let prevHookName = options . useDebugName ;
124132
133+ const skipEffects = o . _skipEffects || o . __s ;
134+
125135 // Make sure that we are always the first `option._hook` to be called.
126136 // This is necessary to ensure that our callstack remains consistent.
127137 // Othwerwise we'll end up with an unknown number of frames in-between
@@ -159,12 +169,41 @@ export function setupOptionsV11(
159169 } ;
160170 } , 100 ) ;
161171
172+ options . vnode = vnode => {
173+ if (
174+ ownerStack . length > 0 &&
175+ typeof vnode . type === "function" &&
176+ vnode . type !== config . Fragment
177+ ) {
178+ vnodeIdToOwner . set ( getVNodeId ( vnode ) , ownerStack [ ownerStack . length - 1 ] ) ;
179+ }
180+ if ( prevVNodeHook ) prevVNodeHook ( vnode ) ;
181+ } ;
182+
183+ options . _internal = options . __i = ( internal , vnode ) => {
184+ const owner = vnodeIdToOwner . get ( getVNodeId ( internal ) ) ;
185+ if ( owner ) {
186+ owners . set ( internal , owner ) ;
187+ }
188+ if ( prevInternalHook ) prevInternalHook ( internal , vnode ) ;
189+ } ;
190+
162191 o . _diff = o . __b = ( internal : Internal , vnode : VNodeV11 ) => {
163192 if ( internal . flags & TYPE_COMPONENT ) {
164193 timings . start . set ( internal , performance . now ( ) ) ;
165194 const name = getDisplayName ( internal , config ) ;
166195 recordMark ( `${ name } _diff` ) ;
167196
197+ const internalId = getVNodeId ( internal ) ;
198+ const vnodeId = getVNodeId ( vnode ) ;
199+ if ( internalId !== vnodeId ) {
200+ const owner = vnodeIdToOwner . get ( internalId ) ;
201+ if ( owner ) {
202+ vnodeIdToOwner . set ( vnodeId , owner ) ;
203+ }
204+ vnodeIdToOwner . delete ( internalId ) ;
205+ }
206+
168207 if ( profiler . captureRenderReasons ) {
169208 if ( internal === null ) {
170209 if ( vnode !== null ) {
@@ -182,8 +221,23 @@ export function setupOptionsV11(
182221 if ( prevBeforeDiff != null ) prevBeforeDiff ( internal ) ;
183222 } ;
184223
224+ o . _render = o . __r = ( internal : Internal ) => {
225+ if (
226+ ! skipEffects &&
227+ internal . flags & TYPE_COMPONENT &&
228+ internal . type !== config . Fragment
229+ ) {
230+ ownerStack . push ( internal ) ;
231+ }
232+ if ( prevRender != null ) prevRender ( internal ) ;
233+ } ;
234+
185235 options . diffed = internal => {
186236 if ( internal . flags & TYPE_COMPONENT ) {
237+ if ( internal . type !== config . Fragment ) {
238+ ownerStack . pop ( ) ;
239+ }
240+
187241 timings . end . set ( internal , performance . now ( ) ) ;
188242 endMark ( getDisplayName ( internal , config ) ) ;
189243
@@ -221,6 +275,7 @@ export function setupOptionsV11(
221275 }
222276 }
223277
278+ ownerStack = [ ] ;
224279 renderer . onCommit ( internal , owners , timings , renderReasons ) ;
225280
226281 if ( profiler . captureRenderReasons ) {
@@ -231,6 +286,8 @@ export function setupOptionsV11(
231286
232287 options . unmount = internal => {
233288 if ( prevBeforeUnmount ) prevBeforeUnmount ( internal ) ;
289+ vnodeIdToOwner . delete ( getVNodeId ( internal ) ) ;
290+ owners . delete ( internal ) ;
234291 timings . start . delete ( internal ) ;
235292 timings . end . delete ( internal ) ;
236293 renderer . onUnmount ( internal ) ;
@@ -240,10 +297,13 @@ export function setupOptionsV11(
240297 return ( ) => {
241298 options . unmount = prevBeforeUnmount ;
242299 o . _commit = o . __c = prevCommitRoot ;
243- options . diffed = prevAfterDiff ;
244300 o . _diff = o . __b = prevBeforeDiff ;
301+ o . _render = o . __r = prevRender ;
302+ options . diffed = prevAfterDiff ;
245303 options . _internal = prevVNodeHook ;
246304 o . _hook = o . __h = prevHook ;
305+ o . vnode = prevVNodeHook ;
306+ o . _internal = o . __i = prevInternalHook ;
247307 options . useDebugValue = prevUseDebugValue ;
248308 } ;
249309}
0 commit comments