Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BlobManager: implement Blob from ArrayBuffer (facebook#39276)
Summary: Fixes a critical networking path used commonly in graphics code, among many other use-cases. It is commonplace to store images within a single binary such as a GLB (see [KHR_binary_glTF](https://github.com/KhronosGroup/glTF/blob/main/extensions/1.0/Khronos/KHR_binary_glTF/README.md#overview)). Base64 encoded glTF can be critically slow in older browsers with an increased size, so it's not a suitable fallback for those targeting multiple platforms. Furthermore, large base64 payloads can cause crash behavior on native when passed via JSI (e.g. `expo-gl`). For textures, this can be several megabytes of high precision data, and a uri from a blob is preferred rather than writing platform-specific workarounds via the filesystem. A user-land patch I've employed in [pmndrs/react-three-fiber](https://github.com/pmndrs/react-three-fiber), as well as [existing user-land patches](https://github.com/mrousavy/react-native-blob-jsi-helper), is to test the `Blob` constructor with an empty `ArrayBuffer`. `base64-js` is used here since it's already installed with `react-native` for binary utils elsewhere. This is declared as a dependency in the linked library since this is an implementation detail, but will be de-duplicated at install time. ```js import { fromByteArray } from 'base64-js' // Patch Blob for ArrayBuffer if unsupported try { new Blob([new ArrayBuffer(4)]) } catch (_) { global.Blob = class extends Blob { constructor(parts, options) { super( parts?.map((part) => { if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) { part = fromByteArray(new Uint8Array(part)) } return part }), options, ) } } } ``` ## Changelog: [INTERNAL] [FIXED] - Implement Blob from ArrayBuffer Pull Request resolved: facebook#39276 Test Plan: Run the following at the project root to selectively test changes: `jest packages/react-native/Libraries/Blob` > **Note**: base64 encoding will add an additional ~33% size increase to binary data as part of this PR. This is padded to 4 bytes so a byte length of 4 will encode as 8. Native `ArrayBuffer` support would not have this behavior and remove the overhead of base64 encoding back and forth. This is a growing behavior across the networking stack, such as in `FileReader`. Reviewed By: NickGerleman Differential Revision: D48954160 Pulled By: dmytrorykun fbshipit-source-id: 9d3b984aefe16bad2ee1088140b6e1160df52f55
- Loading branch information