865
} else {
866
result = Component(props, secondArg);
867
}
868
- if (
869
- typeof result === 'object' &&
870
- result !== null &&
871
- typeof result.then === 'function'
872
- ) {
873
- // When the return value is in children position we can resolve it immediately,
874
- // to its value without a wrapper if it's synchronously available.
875
- const thenable: Thenable<any> = result;
876
- if (thenable.status === 'fulfilled') {
877
- return thenable.value;
878
- }
879
- // TODO: Once we accept Promises as children on the client, we can just return
880
- // the thenable here.
881
- result = createLazyWrapperAroundWakeable(result);
868
+ if (typeof result === 'object' && result !== null) {
869
+ if (typeof result.then === 'function') {
870
+ // When the return value is in children position we can resolve it immediately,
871
+ // to its value without a wrapper if it's synchronously available.
872
+ const thenable: Thenable<any> = result;
873
+ if (thenable.status === 'fulfilled') {
874
+ return thenable.value;
875
+ }
876
+ // TODO: Once we accept Promises as children on the client, we can just return
877
+ // the thenable here.
878
+ result = createLazyWrapperAroundWakeable(result);
879
+ }
880
+
881
+ // Normally we'd serialize an Iterator/AsyncIterator as a single-shot which is not compatible
882
+ // to be rendered as a React Child. However, because we have the function to recreate
883
+ // an iterable from rendering the element again, we can effectively treat it as multi-
884
+ // shot. Therefore we treat this as an Iterable/AsyncIterable, whether it was one or not, by
885
+ // adding a wrapper so that this component effectively renders down to an AsyncIterable.
886
+ const iteratorFn = getIteratorFn(result);
887
+ if (iteratorFn) {
888
+ const iterableChild = result;
889
+ result = {
890
+ [Symbol.iterator]: function () {
891
+ const iterator = iteratorFn.call(iterableChild);
892
+ if (__DEV__) {
893
+ // If this was an Iterator but not a GeneratorFunction we warn because
894
+ // it might have been a mistake. Technically you can make this mistake with
895
+ // GeneratorFunctions and even single-shot Iterables too but it's extra
896
+ // tempting to try to return the value from a generator.
897
+ if (iterator === iterableChild) {
898
+ const isGeneratorComponent =
899
+ // $FlowIgnore[method-unbinding]
900
+ Object.prototype.toString.call(Component) ===
901
+ '[object GeneratorFunction]' &&
902
+ // $FlowIgnore[method-unbinding]
903
+ Object.prototype.toString.call(iterableChild) ===
904
+ '[object Generator]';
905
+ if (!isGeneratorComponent) {
906
+ console.error(
907
+ 'Returning an Iterator from a Server Component is not supported ' +
908
+ 'since it cannot be looped over more than once. ',
909
+ );
910
+ }
911
+ }
912
+ }
913
+ return (iterator: any);
914
+ },
915
+ };
916
+ if (__DEV__) {
917
+ (result: any)._debugInfo = iterableChild._debugInfo;
918
+ }
919
+ } else if (
920
+ enableFlightReadableStream &&
921
+ typeof (result: any)[ASYNC_ITERATOR] === 'function' &&
922
+ (typeof ReadableStream !== 'function' ||
923
+ !(result instanceof ReadableStream))
924
+ ) {
925
+ const iterableChild = result;
926
+ result = {
927
+ [ASYNC_ITERATOR]: function () {
928
+ const iterator = (iterableChild: any)[ASYNC_ITERATOR]();
929
+ if (__DEV__) {
930
+ // If this was an AsyncIterator but not an AsyncGeneratorFunction we warn because
931
+ // it might have been a mistake. Technically you can make this mistake with
932
+ // AsyncGeneratorFunctions and even single-shot AsyncIterables too but it's extra
933
+ // tempting to try to return the value from a generator.
934
+ if (iterator === iterableChild) {
935
+ const isGeneratorComponent =
936
+ // $FlowIgnore[method-unbinding]
937
+ Object.prototype.toString.call(Component) ===
938
+ '[object AsyncGeneratorFunction]' &&
939
+ // $FlowIgnore[method-unbinding]
940
+ Object.prototype.toString.call(iterableChild) ===
941
+ '[object AsyncGenerator]';
942
+ if (!isGeneratorComponent) {
943
+ console.error(
944
+ 'Returning an AsyncIterator from a Server Component is not supported ' +
945
+ 'since it cannot be looped over more than once. ',
946
+ );
947
+ }
948
+ }
949
+ }
950
+ return iterator;
951
+ },
952
+ };
953
+ if (__DEV__) {
954
+ (result: any)._debugInfo = iterableChild._debugInfo;
955
+ }
956
+ }
957
}
958
// Track this element's key on the Server Component on the keyPath context..
959
const prevKeyPath = task.keyPath;