[Flight] Support Blobs from Server to Client (#28755)

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 [c0b5d435986e7d9b52a529b73b9317a7e5772172](https://github.com/facebook/react/commit/c0b5d435986e7d9b52a529b73b9317a7e5772172)
This commit is contained in:
kassens
2024-04-11 19:21:35 +00:00
parent d9f3448f11
commit 2f685cbcac
3 changed files with 9 additions and 3 deletions
+1 -1
View File
@@ -1 +1 @@
87b495f7d26a2c631c08952661d38bb5ce5acb03
c0b5d435986e7d9b52a529b73b9317a7e5772172
@@ -834,6 +834,10 @@ if (__DEV__) {
return new Set(_data);
}
case "B": {
return undefined;
}
case "I": {
// $Infinity
return Infinity;
@@ -886,9 +890,9 @@ if (__DEV__) {
default: {
// We assume that anything else is a reference ID.
var _id6 = parseInt(value.slice(1), 16);
var _id7 = parseInt(value.slice(1), 16);
var _chunk2 = getChunk(response, _id6);
var _chunk2 = getChunk(response, _id7);
switch (_chunk2.status) {
case RESOLVED_MODEL:
@@ -294,6 +294,8 @@ function parseModelString(response, parentObject, key, value) {
(response = getOutlinedModel(response, parentObject)),
new Set(response)
);
case "B":
return;
case "I":
return Infinity;
case "-":