Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Flight] Support Blobs from Server to Client #28755

Merged
merged 1 commit into from
Apr 5, 2024

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Apr 5, 2024

We currently support Blobs when passing from Client to Server so this adds it in the other direction for parity - when enableFlightBinary is enabled.

We intentionally only support the Blob type to pass-through, not subtype File. That's because passing additional meta data like filename might be an accidental leak. You can still pass a File through but it'll appear as a Blob on the other side. It's also not possible to create a faithful File subclass in all environments without it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few indirections. This is because we need to be able to asynchronously emit the buffers but we have to "block" the parent object from resolving while it's loading.

Ideally, we should be able to create the Blob on the client early and then stream in it lazily. Because the Blob API doesn't guarantee that the data is available synchronously. Unfortunately, the native APIs doesn't have this. We could implement custom versions of all the data read APIs but then the blobs still wouldn't work with native APIs. So we just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even though we can't unblock the parent until they've all loaded. I didn't do this yet mostly because of code structure and I'm lazy.

@react-sizebot
Copy link

Comparing: fd0da3e...6b82d7c

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 168.88 kB 168.88 kB = 52.68 kB 52.69 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 170.69 kB 170.69 kB = 53.23 kB 53.24 kB
facebook-www/ReactDOM-prod.classic.js = 591.32 kB 591.32 kB = 103.85 kB 103.85 kB
facebook-www/ReactDOM-prod.modern.js = 567.65 kB 567.65 kB = 99.80 kB 99.80 kB
oss-experimental/react-server/cjs/react-server-flight.production.min.js +2.54% 18.67 kB 19.14 kB +2.00% 6.69 kB 6.82 kB
test_utils/ReactAllWarnings.js Deleted 64.04 kB 0.00 kB Deleted 16.02 kB 0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-server/cjs/react-server-flight.production.min.js +2.54% 18.67 kB 19.14 kB +2.00% 6.69 kB 6.82 kB
oss-experimental/react-server/cjs/react-server-flight.production.js +1.92% 69.18 kB 70.51 kB +1.55% 16.56 kB 16.82 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +1.63% 93.10 kB 94.62 kB +1.45% 21.19 kB 21.50 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.min.js +1.63% 29.28 kB 29.76 kB +1.38% 9.91 kB 10.05 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.production.min.js +1.55% 30.57 kB 31.04 kB +1.25% 9.89 kB 10.02 kB
oss-experimental/react-server-dom-turbopack/umd/react-server-dom-turbopack-server.browser.production.min.js +1.55% 30.68 kB 31.15 kB +1.26% 9.99 kB 10.12 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.production.min.js +1.53% 31.10 kB 31.58 kB +1.24% 10.06 kB 10.18 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.min.js +1.53% 31.09 kB 31.56 kB +1.27% 10.02 kB 10.15 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.production.min.js +1.53% 31.19 kB 31.67 kB +1.19% 10.14 kB 10.26 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.min.js +1.51% 31.51 kB 31.99 kB +1.21% 10.16 kB 10.28 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.production.min.js +1.50% 31.82 kB 32.30 kB +1.32% 10.33 kB 10.47 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.min.js +1.47% 32.32 kB 32.79 kB +1.52% 10.48 kB 10.64 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.production.min.js +1.47% 32.39 kB 32.87 kB +1.62% 10.48 kB 10.65 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.min.js +1.45% 32.90 kB 33.37 kB +1.26% 10.66 kB 10.80 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js +1.26% 105.59 kB 106.92 kB +1.04% 24.82 kB 25.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.production.js +1.22% 108.72 kB 110.05 kB +1.03% 25.58 kB 25.84 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.production.js +1.21% 109.57 kB 110.89 kB +1.01% 25.82 kB 26.08 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.js +1.20% 110.97 kB 112.30 kB +0.99% 26.18 kB 26.44 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.js +1.19% 111.29 kB 112.62 kB +1.03% 26.25 kB 26.52 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.production.js +1.19% 111.74 kB 113.07 kB +0.99% 25.81 kB 26.07 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.production.js +1.17% 113.82 kB 115.15 kB +0.97% 26.31 kB 26.56 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +1.16% 130.41 kB 131.93 kB +1.07% 29.71 kB 30.03 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js +1.16% 114.41 kB 115.73 kB +1.02% 26.65 kB 26.92 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +1.14% 133.12 kB 134.64 kB +1.03% 30.27 kB 30.59 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js +1.14% 116.48 kB 117.80 kB +1.00% 27.20 kB 27.47 kB
oss-experimental/react-server-dom-turbopack/umd/react-server-dom-turbopack-server.browser.development.js +1.13% 140.31 kB 141.90 kB +0.86% 30.70 kB 30.96 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +1.13% 134.69 kB 136.20 kB +1.01% 30.76 kB 31.08 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +1.12% 135.57 kB 137.08 kB +0.98% 30.96 kB 31.26 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.development.js +1.11% 136.57 kB 138.09 kB +1.03% 30.77 kB 31.09 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js +1.11% 142.88 kB 144.47 kB +0.85% 31.39 kB 31.65 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +1.11% 136.62 kB 138.13 kB +0.98% 31.27 kB 31.58 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +1.09% 138.86 kB 140.38 kB +0.99% 31.37 kB 31.68 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +1.09% 139.21 kB 140.73 kB +0.97% 31.58 kB 31.88 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +1.07% 141.50 kB 143.01 kB +0.95% 32.21 kB 32.52 kB
oss-experimental/react-client/cjs/react-client-flight.production.min.js +0.67% 12.48 kB 12.57 kB +0.33% 4.51 kB 4.53 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.min.js +0.64% 13.36 kB 13.44 kB +0.42% 4.78 kB 4.80 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.min.js +0.61% 14.03 kB 14.12 kB +0.38% 5.05 kB 5.07 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.min.js +0.60% 14.15 kB 14.24 kB +0.31% 5.09 kB 5.11 kB
oss-experimental/react-server-dom-turbopack/umd/react-server-dom-turbopack-client.browser.production.min.js +0.59% 14.21 kB 14.30 kB +0.39% 5.15 kB 5.17 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.browser.production.min.js +0.59% 14.34 kB 14.42 kB +0.48% 5.18 kB 5.21 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.min.js +0.56% 50.09 kB 50.37 kB +0.47% 11.64 kB 11.69 kB
oss-experimental/react-client/cjs/react-client-flight.production.js +0.55% 50.23 kB 50.51 kB +0.37% 12.03 kB 12.08 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +0.55% 50.24 kB 50.52 kB +0.49% 11.66 kB 11.72 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.min.js +0.54% 15.48 kB 15.57 kB +0.37% 5.47 kB 5.49 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.production.min.js +0.53% 15.88 kB 15.96 kB +0.35% 5.66 kB 5.68 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.production.min.js +0.53% 15.88 kB 15.96 kB +0.39% 5.65 kB 5.68 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js +0.52% 53.50 kB 53.78 kB +0.43% 12.61 kB 12.66 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.min.js +0.52% 16.19 kB 16.28 kB +0.38% 5.76 kB 5.78 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.min.js +0.52% 16.20 kB 16.28 kB +0.38% 5.77 kB 5.79 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js +0.51% 54.02 kB 54.30 kB +0.42% 12.77 kB 12.82 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.min.js +0.51% 16.63 kB 16.72 kB +0.34% 5.89 kB 5.91 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.min.js +0.51% 16.64 kB 16.73 kB +0.34% 5.90 kB 5.92 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +0.48% 57.33 kB 57.60 kB +0.35% 13.47 kB 13.52 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.production.js +0.47% 59.11 kB 59.39 kB +0.34% 14.02 kB 14.07 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.production.js +0.47% 59.15 kB 59.43 kB +0.34% 14.04 kB 14.09 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js +0.46% 60.55 kB 60.83 kB +0.34% 14.39 kB 14.44 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js +0.46% 60.58 kB 60.86 kB +0.33% 14.43 kB 14.48 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js +0.45% 61.66 kB 61.94 kB +0.34% 14.60 kB 14.65 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js +0.45% 61.69 kB 61.97 kB +0.33% 14.64 kB 14.69 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +0.43% 66.53 kB 66.82 kB +0.34% 15.71 kB 15.76 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +0.43% 66.77 kB 67.06 kB +0.34% 15.78 kB 15.83 kB
oss-experimental/react-client/cjs/react-client-flight.development.js +0.43% 66.85 kB 67.13 kB +0.37% 16.03 kB 16.09 kB
oss-experimental/react-server-dom-turbopack/umd/react-server-dom-turbopack-client.browser.development.js +0.41% 74.30 kB 74.61 kB +0.35% 17.01 kB 17.07 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.browser.development.js +0.41% 74.85 kB 75.15 kB +0.34% 17.19 kB 17.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +0.41% 70.02 kB 70.31 kB +0.33% 16.74 kB 16.80 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +0.41% 70.53 kB 70.82 kB +0.32% 16.91 kB 16.97 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +0.38% 74.47 kB 74.76 kB +0.35% 17.79 kB 17.85 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +0.38% 76.25 kB 76.54 kB +0.34% 18.36 kB 18.43 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +0.37% 76.29 kB 76.57 kB +0.34% 18.39 kB 18.45 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +0.37% 77.69 kB 77.97 kB +0.34% 18.73 kB 18.79 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +0.37% 77.71 kB 78.00 kB +0.34% 18.77 kB 18.83 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +0.36% 78.76 kB 79.04 kB +0.35% 18.94 kB 19.01 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +0.36% 78.78 kB 79.07 kB +0.36% 18.98 kB 19.05 kB
test_utils/ReactAllWarnings.js Deleted 64.04 kB 0.00 kB Deleted 16.02 kB 0.00 kB

Generated by 🚫 dangerJS against 6b82d7c

@sebmarkbage sebmarkbage merged commit cbb6f2b into facebook:main Apr 5, 2024
38 checks passed
github-actions bot pushed a commit that referenced this pull request Apr 5, 2024
We currently support Blobs when passing from Client to Server so this
adds it in the other direction for parity - when `enableFlightBinary` is
enabled.

We intentionally only support the `Blob` type to pass-through, not
subtype `File`. That's because passing additional meta data like
filename might be an accidental leak. You can still pass a `File`
through but it'll appear as a `Blob` on the other side. It's also not
possible to create a faithful File subclass in all environments without
it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few
indirections. This is because we need to be able to asynchronously emit
the buffers but we have to "block" the parent object from resolving
while it's loading.

Ideally, we should be able to create the Blob on the client early and
then stream in it lazily. Because the Blob API doesn't guarantee that
the data is available synchronously. Unfortunately, the native APIs
doesn't have this. We could implement custom versions of all the data
read APIs but then the blobs still wouldn't work with native APIs. So we
just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even
though we can't unblock the parent until they've all loaded. I didn't do
this yet mostly because of code structure and I'm lazy.

DiffTrain build for [cbb6f2b](cbb6f2b)
@sebmarkbage
Copy link
Collaborator Author

sebmarkbage commented Apr 5, 2024

Actually, this is no good because it means that outlined models can now be blocked on a future reference which isn't supported atm. So if this is inside a Map or FormData it doesn't work. It's a good indication that the outlined models need to work differently.

sebmarkbage added a commit that referenced this pull request Apr 5, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.
github-actions bot pushed a commit that referenced this pull request Apr 5, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.

DiffTrain build for [2acfb7b](2acfb7b)
kassens pushed a commit to kassens/react that referenced this pull request Apr 11, 2024
We currently support Blobs when passing from Client to Server so this
adds it in the other direction for parity - when `enableFlightBinary` is
enabled.

We intentionally only support the `Blob` type to pass-through, not
subtype `File`. That's because passing additional meta data like
filename might be an accidental leak. You can still pass a `File`
through but it'll appear as a `Blob` on the other side. It's also not
possible to create a faithful File subclass in all environments without
it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few
indirections. This is because we need to be able to asynchronously emit
the buffers but we have to "block" the parent object from resolving
while it's loading.

Ideally, we should be able to create the Blob on the client early and
then stream in it lazily. Because the Blob API doesn't guarantee that
the data is available synchronously. Unfortunately, the native APIs
doesn't have this. We could implement custom versions of all the data
read APIs but then the blobs still wouldn't work with native APIs. So we
just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even
though we can't unblock the parent until they've all loaded. I didn't do
this yet mostly because of code structure and I'm lazy.
kassens pushed a commit to kassens/react that referenced this pull request Apr 11, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

facebook#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.
kassens pushed a commit to kassens/react that referenced this pull request Apr 11, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

facebook#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.
github-actions bot pushed a commit that referenced this pull request Apr 11, 2024
We currently support Blobs when passing from Client to Server so this
adds it in the other direction for parity - when `enableFlightBinary` is
enabled.

We intentionally only support the `Blob` type to pass-through, not
subtype `File`. That's because passing additional meta data like
filename might be an accidental leak. You can still pass a `File`
through but it'll appear as a `Blob` on the other side. It's also not
possible to create a faithful File subclass in all environments without
it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few
indirections. This is because we need to be able to asynchronously emit
the buffers but we have to "block" the parent object from resolving
while it's loading.

Ideally, we should be able to create the Blob on the client early and
then stream in it lazily. Because the Blob API doesn't guarantee that
the data is available synchronously. Unfortunately, the native APIs
doesn't have this. We could implement custom versions of all the data
read APIs but then the blobs still wouldn't work with native APIs. So we
just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even
though we can't unblock the parent until they've all loaded. I didn't do
this yet mostly because of code structure and I'm lazy.

DiffTrain build for [c0b5d43](c0b5d43)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
We currently support Blobs when passing from Client to Server so this
adds it in the other direction for parity - when `enableFlightBinary` is
enabled.

We intentionally only support the `Blob` type to pass-through, not
subtype `File`. That's because passing additional meta data like
filename might be an accidental leak. You can still pass a `File`
through but it'll appear as a `Blob` on the other side. It's also not
possible to create a faithful File subclass in all environments without
it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few
indirections. This is because we need to be able to asynchronously emit
the buffers but we have to "block" the parent object from resolving
while it's loading.

Ideally, we should be able to create the Blob on the client early and
then stream in it lazily. Because the Blob API doesn't guarantee that
the data is available synchronously. Unfortunately, the native APIs
doesn't have this. We could implement custom versions of all the data
read APIs but then the blobs still wouldn't work with native APIs. So we
just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even
though we can't unblock the parent until they've all loaded. I didn't do
this yet mostly because of code structure and I'm lazy.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
We currently support Blobs when passing from Client to Server so this
adds it in the other direction for parity - when `enableFlightBinary` is
enabled.

We intentionally only support the `Blob` type to pass-through, not
subtype `File`. That's because passing additional meta data like
filename might be an accidental leak. You can still pass a `File`
through but it'll appear as a `Blob` on the other side. It's also not
possible to create a faithful File subclass in all environments without
it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few
indirections. This is because we need to be able to asynchronously emit
the buffers but we have to "block" the parent object from resolving
while it's loading.

Ideally, we should be able to create the Blob on the client early and
then stream in it lazily. Because the Blob API doesn't guarantee that
the data is available synchronously. Unfortunately, the native APIs
doesn't have this. We could implement custom versions of all the data
read APIs but then the blobs still wouldn't work with native APIs. So we
just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even
though we can't unblock the parent until they've all loaded. I didn't do
this yet mostly because of code structure and I'm lazy.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
We currently support Blobs when passing from Client to Server so this
adds it in the other direction for parity - when `enableFlightBinary` is
enabled.

We intentionally only support the `Blob` type to pass-through, not
subtype `File`. That's because passing additional meta data like
filename might be an accidental leak. You can still pass a `File`
through but it'll appear as a `Blob` on the other side. It's also not
possible to create a faithful File subclass in all environments without
it actually being backed by a file.

This implementation isn't great but at least it works. It creates a few
indirections. This is because we need to be able to asynchronously emit
the buffers but we have to "block" the parent object from resolving
while it's loading.

Ideally, we should be able to create the Blob on the client early and
then stream in it lazily. Because the Blob API doesn't guarantee that
the data is available synchronously. Unfortunately, the native APIs
doesn't have this. We could implement custom versions of all the data
read APIs but then the blobs still wouldn't work with native APIs. So we
just have to wait until Blob accepts a stream in the constructor.

We should be able to stream each chunk early in the protocol though even
though we can't unblock the parent until they've all loaded. I didn't do
this yet mostly because of code structure and I'm lazy.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
We currently support FormData for Replies mainly for Form Actions. This
supports it in the other direction too which lets you return it from an
action as the response. Mainly for parity.

We don't really recommend that you just pass the original form data back
because the action is supposed to be able to clear fields and such but
you could potentially at least use this as the format and could clear
some fields.

We could potentially optimize this with a temporary reference if the
same object was passed to a reply in case you use it as a round trip to
avoid serializing it back again. That way the action has the ability to
override it to clear fields but if it doesn't you get back the same as
you sent.

facebook#28755 adds support for Blobs when the `enableBinaryFlight` is enabled
which allows them to be used inside FormData too.
facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS

This sync includes the following changes:
- **[b5e5ce8e0](facebook/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](facebook/react#28857)) //<Ricky>//
- **[da6ba53b1](facebook/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](facebook/react#28735)) //<Josh Story>//
- **[0c245df1d](facebook/react@0c245df1d )**: Complete the typo fix ([#28856](facebook/react#28856)) //<Sebastian Silbermann>//
- **[f82051d7a](facebook/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](facebook/react#28855)) //<Andrew Clark>//
- **[4ca20fd36](facebook/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](facebook/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c696](facebook/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](facebook/react#28851)) //<Sebastian Markbåge>//
- **[657428a9e](facebook/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](facebook/react#28850)) //<Ricky>//
- **[7909d8eab](facebook/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](facebook/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d05](facebook/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](facebook/react#28818)) //<Andrew Clark>//
- **[8afa144bd](facebook/react@8afa144bd )**: Enable flag disableClientCache ([#28846](facebook/react#28846)) //<Jan Kassens>//
- **[734956ace](facebook/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](facebook/react#28413)) //<Sebastian Silbermann>//
- **[17e920c00](facebook/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](facebook/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd00](facebook/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](facebook/react#28836)) //<Ricky>//
- **[c113503ad](facebook/react@c113503ad )**: Flush direct streams in Bun ([#28837](facebook/react#28837)) //<Kenta Iwasaki>//
- **[9defcd56b](facebook/react@9defcd56b )**: Remove redundant props assign ([#28829](facebook/react#28829)) //<Sebastian Silbermann>//
- **[ed4023603](facebook/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](facebook/react#28835)) //<Sebastian Markbåge>//
- **[c8a035036](facebook/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](facebook/react#28802)) //<Josh Story>//
- **[4f5c812a3](facebook/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](facebook/react#28593)) //<Sebastian Silbermann>//
- **[435415962](facebook/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](facebook/react#28826)) //<Jack Pope>//
- **[608edcc90](facebook/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](facebook/react#28732)) //<Ricky>//
- **[da69b6af9](facebook/react@da69b6af9 )**: ReactDOM.requestFormReset  ([#28809](facebook/react#28809)) //<Andrew Clark>//
- **[374b5d26c](facebook/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](facebook/react#28808)) //<Andrew Clark>//
- **[41950d14a](facebook/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](facebook/react#28804)) //<Andrew Clark>//
- **[dc6a7e01e](facebook/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](facebook/react#28815)) //<Josh Story>//
- **[3f947b1b4](facebook/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](facebook/react#28737)) //<Ricky>//
- **[bf09089f6](facebook/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](facebook/react#28812)) //<Ricky>//
- **[84cb3b4cb](facebook/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](facebook/react#28811)) //<Ricky>//
- **[2243b40ab](facebook/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](facebook/react#28763)) //<Ricky>//
- **[dfc64c6e3](facebook/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](facebook/react#28762)) //<Ricky>//
- **[42eff4bc7](facebook/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](facebook/react#28745)) //<Ricky>//
- **[ed3c65caf](facebook/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](facebook/react#28781)) //<Andrew Clark>//
- **[3f9e237a2](facebook/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](facebook/react#28800)) //<Andrew Clark>//
- **[7f5d25e23](facebook/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](facebook/react#28797)) //<Joseph Savona>//
- **[bf40b0244](facebook/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](facebook/react#28796)) //<Josh Story>//
- **[7f93cb41c](facebook/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](facebook/react#28795)) //<Josh Story>//
- **[f61316535](facebook/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](facebook/react#28789)) //<Sebastian Markbåge>//
- **[9644d206e](facebook/react@9644d206e )**: Soften useFormState warning ([#28788](facebook/react#28788)) //<Ricky>//
- **[c771016e1](facebook/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](facebook/react#28786)) //<Sebastian Markbåge>//
- **[d50323eb8](facebook/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](facebook/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c62](facebook/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](facebook/react#26760)) //<Josh Story>//
- **[dfd3d5af8](facebook/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](facebook/react#27345)) //<Hugo Sales>//
- **[1f8327f83](facebook/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](facebook/react#28765)) //<Josh Story>//
- **[97c90ed88](facebook/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](facebook/react#28770)) //<Josh Story>//
- **[9007fdc8f](facebook/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](facebook/react#28771)) //<Josh Story>//
- **[14f50ad15](facebook/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](facebook/react#28780)) //<Sebastian Markbåge>//
- **[4c12339ce](facebook/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](facebook/react#28500)) //<Josh Story>//
- **[8e1462e8c](facebook/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](facebook/react#28751)) //<Josh Story>//
- **[0b3b8a6a3](facebook/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](facebook/react#28775)) //<Andrew Clark>//
- **[2acfb7b60](facebook/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](facebook/react#28754)) //<Sebastian Markbåge>//
- **[d1547defe](facebook/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](facebook/react#28768)) //<Andrew Clark>//
- **[bfd8da807](facebook/react@bfd8da807 )**: Make class prop resolution faster ([#28766](facebook/react#28766)) //<Andrew Clark>//
- **[cbb6f2b54](facebook/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](facebook/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b69c](facebook/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](facebook/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd54b](facebook/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](facebook/react#28473)) //<Andrew Clark>//
- **[fd0da3eef](facebook/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](facebook/react#28739)) //<Sebastian Markbåge>//

Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8

jest_e2e[run_all_tests]
bypass-github-export-checks

Reviewed By: kassens

Differential Revision: D56251607

fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants