@@ -19,7 +19,7 @@ if (__DEV__) {
19
19
var React = require ( "react" ) ;
20
20
var ReactDOM = require ( "react-dom" ) ;
21
21
22
- var ReactVersion = "18.3.0-www-classic-605a9ce6 " ;
22
+ var ReactVersion = "18.3.0-www-classic-de28fc21 " ;
23
23
24
24
// This refers to a WWW module.
25
25
var warningWWW = require ( "warning" ) ;
@@ -3153,6 +3153,15 @@ function pushStartOption(target, props, formatContext) {
3153
3153
return children ;
3154
3154
}
3155
3155
3156
+ var formStateMarkerIsMatching = stringToPrecomputedChunk ( "<!--F!-->" ) ;
3157
+ var formStateMarkerIsNotMatching = stringToPrecomputedChunk ( "<!--F-->" ) ;
3158
+ function pushFormStateMarkerIsMatching ( target ) {
3159
+ target . push ( formStateMarkerIsMatching ) ;
3160
+ }
3161
+ function pushFormStateMarkerIsNotMatching ( target ) {
3162
+ target . push ( formStateMarkerIsNotMatching ) ;
3163
+ }
3164
+
3156
3165
function pushStartForm ( target , props , resumableState , renderState ) {
3157
3166
target . push ( startChunkForTag ( "form" ) ) ;
3158
3167
var children = null ;
@@ -9152,7 +9161,14 @@ var isReRender = false; // Whether an update was scheduled during the currently
9152
9161
9153
9162
var didScheduleRenderPhaseUpdate = false ; // Counts the number of useId hooks in this component
9154
9163
9155
- var localIdCounter = 0 ; // Counts the number of use(thenable) calls in this component
9164
+ var localIdCounter = 0 ; // Chunks that should be pushed to the stream once the component
9165
+ // finishes rendering.
9166
+ // Counts the number of useFormState calls in this component
9167
+
9168
+ var formStateCounter = 0 ; // The index of the useFormState hook that matches the one passed in at the
9169
+ // root during an MPA navigation, if any.
9170
+
9171
+ var formStateMatchingIndex = - 1 ; // Counts the number of use(thenable) calls in this component
9156
9172
9157
9173
var thenableIndexCounter = 0 ;
9158
9174
var thenableState = null ; // Lazily created map of render-phase updates
@@ -9285,6 +9301,8 @@ function prepareToUseHooks(task, componentIdentity, prevThenableState) {
9285
9301
// workInProgressHook = null;
9286
9302
9287
9303
localIdCounter = 0 ;
9304
+ formStateCounter = 0 ;
9305
+ formStateMatchingIndex = - 1 ;
9288
9306
thenableIndexCounter = 0 ;
9289
9307
thenableState = prevThenableState ;
9290
9308
}
@@ -9298,6 +9316,8 @@ function finishHooks(Component, props, children, refOrContext) {
9298
9316
// restarting until no more updates are scheduled.
9299
9317
didScheduleRenderPhaseUpdate = false ;
9300
9318
localIdCounter = 0 ;
9319
+ formStateCounter = 0 ;
9320
+ formStateMatchingIndex = - 1 ;
9301
9321
thenableIndexCounter = 0 ;
9302
9322
numberOfReRenders += 1 ; // Start over from the beginning of the list
9303
9323
@@ -9319,6 +9339,18 @@ function checkDidRenderIdHook() {
9319
9339
// separate function to avoid using an array tuple.
9320
9340
var didRenderIdHook = localIdCounter !== 0 ;
9321
9341
return didRenderIdHook ;
9342
+ }
9343
+ function getFormStateCount ( ) {
9344
+ // This should be called immediately after every finishHooks call.
9345
+ // Conceptually, it's part of the return value of finishHooks; it's only a
9346
+ // separate function to avoid using an array tuple.
9347
+ return formStateCounter ;
9348
+ }
9349
+ function getFormStateMatchingIndex ( ) {
9350
+ // This should be called immediately after every finishHooks call.
9351
+ // Conceptually, it's part of the return value of finishHooks; it's only a
9352
+ // separate function to avoid using an array tuple.
9353
+ return formStateMatchingIndex ;
9322
9354
} // Reset the internal hooks state if an error occurs while rendering a component
9323
9355
9324
9356
function resetHooksState ( ) {
@@ -9608,7 +9640,11 @@ function useOptimistic(passthrough, reducer) {
9608
9640
}
9609
9641
9610
9642
function useFormState ( action , initialState , permalink ) {
9611
- resolveCurrentlyRenderingComponent ( ) ; // Bind the initial state to the first argument of the action.
9643
+ resolveCurrentlyRenderingComponent ( ) ; // Count the number of useFormState hooks per component.
9644
+ // TODO: We should also track which hook matches the form state passed at
9645
+ // the root, if any. Matching is not yet implemented.
9646
+
9647
+ formStateCounter ++ ; // Bind the initial state to the first argument of the action.
9612
9648
// TODO: Use the keypath (or permalink) to check if there's matching state
9613
9649
// from the previous page.
9614
9650
@@ -10400,6 +10436,8 @@ function renderIndeterminateComponent(
10400
10436
legacyContext
10401
10437
) ;
10402
10438
var hasId = checkDidRenderIdHook ( ) ;
10439
+ var formStateCount = getFormStateCount ( ) ;
10440
+ var formStateMatchingIndex = getFormStateMatchingIndex ( ) ;
10403
10441
10404
10442
{
10405
10443
// Support for module components is deprecated and is removed behind a flag.
@@ -10432,30 +10470,79 @@ function renderIndeterminateComponent(
10432
10470
{
10433
10471
{
10434
10472
validateFunctionComponentInDev ( Component ) ;
10435
- } // We're now successfully past this task, and we don't have to pop back to
10436
- // the previous task every again, so we can use the destructive recursive form.
10437
-
10438
- if ( hasId ) {
10439
- // This component materialized an id. We treat this as its own level, with
10440
- // a single "child" slot.
10441
- var prevTreeContext = task . treeContext ;
10442
- var totalChildren = 1 ;
10443
- var index = 0 ; // Modify the id context. Because we'll need to reset this if something
10444
- // suspends or errors, we'll use the non-destructive render path.
10445
-
10446
- task . treeContext = pushTreeContext ( prevTreeContext , totalChildren , index ) ;
10447
- renderNode ( request , task , value , 0 ) ; // Like the other contexts, this does not need to be in a finally block
10448
- // because renderNode takes care of unwinding the stack.
10449
-
10450
- task . treeContext = prevTreeContext ;
10451
- } else {
10452
- renderNodeDestructive ( request , task , null , value , 0 ) ;
10453
10473
}
10474
+
10475
+ finishFunctionComponent (
10476
+ request ,
10477
+ task ,
10478
+ value ,
10479
+ hasId ,
10480
+ formStateCount ,
10481
+ formStateMatchingIndex
10482
+ ) ;
10454
10483
}
10455
10484
10456
10485
popComponentStackInDEV ( task ) ;
10457
10486
}
10458
10487
10488
+ function finishFunctionComponent (
10489
+ request ,
10490
+ task ,
10491
+ children ,
10492
+ hasId ,
10493
+ formStateCount ,
10494
+ formStateMatchingIndex
10495
+ ) {
10496
+ var didEmitFormStateMarkers = false ;
10497
+
10498
+ if ( formStateCount !== 0 ) {
10499
+ // For each useFormState hook, emit a marker that indicates whether we
10500
+ // rendered using the form state passed at the root.
10501
+ // TODO: As an optimization, Fizz should only emit these markers if form
10502
+ // state is passed at the root.
10503
+ var segment = task . blockedSegment ;
10504
+
10505
+ if ( segment === null ) ;
10506
+ else {
10507
+ didEmitFormStateMarkers = true ;
10508
+ var target = segment . chunks ;
10509
+
10510
+ for ( var i = 0 ; i < formStateCount ; i ++ ) {
10511
+ if ( i === formStateMatchingIndex ) {
10512
+ pushFormStateMarkerIsMatching ( target ) ;
10513
+ } else {
10514
+ pushFormStateMarkerIsNotMatching ( target ) ;
10515
+ }
10516
+ }
10517
+ }
10518
+ }
10519
+
10520
+ if ( hasId ) {
10521
+ // This component materialized an id. We treat this as its own level, with
10522
+ // a single "child" slot.
10523
+ var prevTreeContext = task . treeContext ;
10524
+ var totalChildren = 1 ;
10525
+ var index = 0 ; // Modify the id context. Because we'll need to reset this if something
10526
+ // suspends or errors, we'll use the non-destructive render path.
10527
+
10528
+ task . treeContext = pushTreeContext ( prevTreeContext , totalChildren , index ) ;
10529
+ renderNode ( request , task , children , 0 ) ; // Like the other contexts, this does not need to be in a finally block
10530
+ // because renderNode takes care of unwinding the stack.
10531
+
10532
+ task . treeContext = prevTreeContext ;
10533
+ } else if ( didEmitFormStateMarkers ) {
10534
+ // If there were formState hooks, we must use the non-destructive path
10535
+ // because this component is not a pure indirection; we emitted markers
10536
+ // to the stream.
10537
+ renderNode ( request , task , children , 0 ) ;
10538
+ } else {
10539
+ // We're now successfully past this task, and we haven't modified the
10540
+ // context stack. We don't have to pop back to the previous task every
10541
+ // again, so we can use the destructive recursive form.
10542
+ renderNodeDestructive ( request , task , null , children , 0 ) ;
10543
+ }
10544
+ }
10545
+
10459
10546
function validateFunctionComponentInDev ( Component ) {
10460
10547
{
10461
10548
if ( Component ) {
@@ -10541,22 +10628,16 @@ function renderForwardRef(request, task, prevThenableState, type, props, ref) {
10541
10628
ref
10542
10629
) ;
10543
10630
var hasId = checkDidRenderIdHook ( ) ;
10544
-
10545
- if ( hasId ) {
10546
- // This component materialized an id. We treat this as its own level, with
10547
- // a single "child" slot.
10548
- var prevTreeContext = task . treeContext ;
10549
- var totalChildren = 1 ;
10550
- var index = 0 ; // Modify the id context. Because we'll need to reset this if something
10551
- // suspends or errors, we'll use the non-destructive render path.
10552
-
10553
- task . treeContext = pushTreeContext ( prevTreeContext , totalChildren , index ) ;
10554
- renderNode ( request , task , children , 0 ) ; // Like the other contexts, this does not need to be in a finally block
10555
- // because renderNode takes care of unwinding the stack.
10556
- } else {
10557
- renderNodeDestructive ( request , task , null , children , 0 ) ;
10558
- }
10559
-
10631
+ var formStateCount = getFormStateCount ( ) ;
10632
+ var formStateMatchingIndex = getFormStateMatchingIndex ( ) ;
10633
+ finishFunctionComponent (
10634
+ request ,
10635
+ task ,
10636
+ children ,
10637
+ hasId ,
10638
+ formStateCount ,
10639
+ formStateMatchingIndex
10640
+ ) ;
10560
10641
popComponentStackInDEV ( task ) ;
10561
10642
}
10562
10643
0 commit comments