@@ -44,6 +44,7 @@ import { selectWorkerForForwarding } from './action-utils'
44
44
import { isNodeNextRequest , isWebNextRequest } from '../base-http/helpers'
45
45
import { RedirectStatusCode } from '../../client/components/redirect-status-code'
46
46
import { synchronizeMutableCookies } from '../async-storage/request-store'
47
+ import type { TemporaryReferenceSet } from 'react-server-dom-webpack/server.edge'
47
48
48
49
function formDataFromSearchQueryString ( query : string ) {
49
50
const searchParams = new URLSearchParams ( query )
@@ -394,12 +395,11 @@ function limitUntrustedHeaderValueForLogs(value: string) {
394
395
395
396
type ServerModuleMap = Record <
396
397
string ,
397
- | {
398
- id : string
399
- chunks : string [ ]
400
- name : string
401
- }
402
- | undefined
398
+ {
399
+ id : string
400
+ chunks : string [ ]
401
+ name : string
402
+ }
403
403
>
404
404
405
405
type ServerActionsConfig = {
@@ -460,6 +460,8 @@ export async function handleAction({
460
460
)
461
461
}
462
462
463
+ let temporaryReferences : TemporaryReferenceSet | undefined
464
+
463
465
const finalizeAndGenerateFlight : GenerateFlight = ( ...args ) => {
464
466
// When we switch to the render phase, cookies() will return
465
467
// `workUnitStore.cookies` instead of `workUnitStore.userspaceMutableCookies`.
@@ -562,6 +564,7 @@ export async function handleAction({
562
564
actionResult : promise ,
563
565
// if the page was not revalidated, we can skip the rendering the flight tree
564
566
skipFlight : ! workStore . pathWasRevalidated ,
567
+ temporaryReferences,
565
568
} ) ,
566
569
}
567
570
}
@@ -617,19 +620,31 @@ export async function handleAction({
617
620
process . env . NEXT_RUNTIME === 'edge' &&
618
621
isWebNextRequest ( req )
619
622
) {
620
- // Use react-server-dom-webpack/server.edge
621
- const { decodeReply, decodeAction, decodeFormState } = ComponentMod
622
623
if ( ! req . body ) {
623
624
throw new Error ( 'invariant: Missing request body.' )
624
625
}
625
626
626
627
// TODO: add body limit
627
628
629
+ // Use react-server-dom-webpack/server.edge
630
+ const {
631
+ createTemporaryReferenceSet,
632
+ decodeReply,
633
+ decodeAction,
634
+ decodeFormState,
635
+ } = ComponentMod
636
+
637
+ temporaryReferences = createTemporaryReferenceSet ( )
638
+
628
639
if ( isMultipartAction ) {
629
640
// TODO-APP: Add streaming support
630
641
const formData = await req . request . formData ( )
631
642
if ( isFetchAction ) {
632
- boundActionArguments = await decodeReply ( formData , serverModuleMap )
643
+ boundActionArguments = await decodeReply (
644
+ formData ,
645
+ serverModuleMap ,
646
+ { temporaryReferences }
647
+ )
633
648
} else {
634
649
const action = await decodeAction ( formData , serverModuleMap )
635
650
if ( typeof action === 'function' ) {
@@ -672,11 +687,16 @@ export async function handleAction({
672
687
673
688
if ( isURLEncodedAction ) {
674
689
const formData = formDataFromSearchQueryString ( actionData )
675
- boundActionArguments = await decodeReply ( formData , serverModuleMap )
690
+ boundActionArguments = await decodeReply (
691
+ formData ,
692
+ serverModuleMap ,
693
+ { temporaryReferences }
694
+ )
676
695
} else {
677
696
boundActionArguments = await decodeReply (
678
697
actionData ,
679
- serverModuleMap
698
+ serverModuleMap ,
699
+ { temporaryReferences }
680
700
)
681
701
}
682
702
}
@@ -688,11 +708,16 @@ export async function handleAction({
688
708
) {
689
709
// Use react-server-dom-webpack/server.node which supports streaming
690
710
const {
711
+ createTemporaryReferenceSet,
691
712
decodeReply,
692
713
decodeReplyFromBusboy,
693
714
decodeAction,
694
715
decodeFormState,
695
- } = require ( `./react-server.node` )
716
+ } = require (
717
+ `./react-server.node`
718
+ ) as typeof import ( './react-server.node' )
719
+
720
+ temporaryReferences = createTemporaryReferenceSet ( )
696
721
697
722
const { Transform } =
698
723
require ( 'node:stream' ) as typeof import ( 'node:stream' )
@@ -742,7 +767,8 @@ export async function handleAction({
742
767
743
768
boundActionArguments = await decodeReplyFromBusboy (
744
769
busboy ,
745
- serverModuleMap
770
+ serverModuleMap ,
771
+ { temporaryReferences }
746
772
)
747
773
} else {
748
774
// React doesn't yet publish a busboy version of decodeAction
@@ -772,7 +798,11 @@ export async function handleAction({
772
798
// Only warn if it's a server action, otherwise skip for other post requests
773
799
warnBadServerActionRequest ( )
774
800
const actionReturnedState = await action ( )
775
- formState = await decodeFormState ( actionReturnedState , formData )
801
+ formState = await decodeFormState (
802
+ actionReturnedState ,
803
+ formData ,
804
+ serverModuleMap
805
+ )
776
806
}
777
807
778
808
// Skip the fetch path
@@ -799,11 +829,16 @@ export async function handleAction({
799
829
800
830
if ( isURLEncodedAction ) {
801
831
const formData = formDataFromSearchQueryString ( actionData )
802
- boundActionArguments = await decodeReply ( formData , serverModuleMap )
832
+ boundActionArguments = await decodeReply (
833
+ formData ,
834
+ serverModuleMap ,
835
+ { temporaryReferences }
836
+ )
803
837
} else {
804
838
boundActionArguments = await decodeReply (
805
839
actionData ,
806
- serverModuleMap
840
+ serverModuleMap ,
841
+ { temporaryReferences }
807
842
)
808
843
}
809
844
}
@@ -855,6 +890,7 @@ export async function handleAction({
855
890
actionResult : Promise . resolve ( returnVal ) ,
856
891
// if the page was not revalidated, or if the action was forwarded from another worker, we can skip the rendering the flight tree
857
892
skipFlight : ! workStore . pathWasRevalidated || actionWasForwarded ,
893
+ temporaryReferences,
858
894
} )
859
895
}
860
896
} )
@@ -929,6 +965,7 @@ export async function handleAction({
929
965
result : await finalizeAndGenerateFlight ( req , ctx , {
930
966
skipFlight : false ,
931
967
actionResult : promise ,
968
+ temporaryReferences,
932
969
} ) ,
933
970
}
934
971
}
@@ -963,6 +1000,7 @@ export async function handleAction({
963
1000
actionResult : promise ,
964
1001
// if the page was not revalidated, or if the action was forwarded from another worker, we can skip the rendering the flight tree
965
1002
skipFlight : ! workStore . pathWasRevalidated || actionWasForwarded ,
1003
+ temporaryReferences,
966
1004
} ) ,
967
1005
}
968
1006
}
0 commit comments