UNPKG

3.83 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 * @format
9 */
10
11'use strict';
12
13import type {BlobData, BlobOptions} from 'BlobTypes';
14
15/**
16 * Opaque JS representation of some binary data in native.
17 *
18 * The API is modeled after the W3C Blob API, with one caveat
19 * regarding explicit deallocation. Refer to the `close()`
20 * method for further details.
21 *
22 * Example usage in a React component:
23 *
24 * class WebSocketImage extends React.Component {
25 * state = {blob: null};
26 * componentDidMount() {
27 * let ws = this.ws = new WebSocket(...);
28 * ws.binaryType = 'blob';
29 * ws.onmessage = (event) => {
30 * if (this.state.blob) {
31 * this.state.blob.close();
32 * }
33 * this.setState({blob: event.data});
34 * };
35 * }
36 * componentUnmount() {
37 * if (this.state.blob) {
38 * this.state.blob.close();
39 * }
40 * this.ws.close();
41 * }
42 * render() {
43 * if (!this.state.blob) {
44 * return <View />;
45 * }
46 * return <Image source={{uri: URL.createObjectURL(this.state.blob)}} />;
47 * }
48 * }
49 *
50 * Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob
51 */
52class Blob {
53 _data: ?BlobData;
54
55 /**
56 * Constructor for JS consumers.
57 * Currently we only support creating Blobs from other Blobs.
58 * Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob
59 */
60 constructor(parts: Array<Blob | string> = [], options?: BlobOptions) {
61 const BlobManager = require('BlobManager');
62 this.data = BlobManager.createFromParts(parts, options).data;
63 }
64
65 /*
66 * This method is used to create a new Blob object containing
67 * the data in the specified range of bytes of the source Blob.
68 * Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice
69 */
70 set data(data: ?BlobData) {
71 this._data = data;
72 }
73
74 get data(): BlobData {
75 if (!this._data) {
76 throw new Error('Blob has been closed and is no longer available');
77 }
78
79 return this._data;
80 }
81
82 slice(start?: number, end?: number): Blob {
83 const BlobManager = require('BlobManager');
84 let {offset, size} = this.data;
85
86 if (typeof start === 'number') {
87 if (start > size) {
88 start = size;
89 }
90 offset += start;
91 size -= start;
92
93 if (typeof end === 'number') {
94 if (end < 0) {
95 end = this.size + end;
96 }
97 size = end - start;
98 }
99 }
100 return BlobManager.createFromOptions({
101 blobId: this.data.blobId,
102 offset,
103 size,
104 });
105 }
106
107 /**
108 * This method is in the standard, but not actually implemented by
109 * any browsers at this point. It's important for how Blobs work in
110 * React Native, however, since we cannot de-allocate resources automatically,
111 * so consumers need to explicitly de-allocate them.
112 *
113 * Note that the semantics around Blobs created via `blob.slice()`
114 * and `new Blob([blob])` are different. `blob.slice()` creates a
115 * new *view* onto the same binary data, so calling `close()` on any
116 * of those views is enough to deallocate the data, whereas
117 * `new Blob([blob, ...])` actually copies the data in memory.
118 */
119 close() {
120 const BlobManager = require('BlobManager');
121 BlobManager.release(this.data.blobId);
122 this.data = null;
123 }
124
125 /**
126 * Size of the data contained in the Blob object, in bytes.
127 */
128 get size(): number {
129 return this.data.size;
130 }
131
132 /*
133 * String indicating the MIME type of the data contained in the Blob.
134 * If the type is unknown, this string is empty.
135 */
136 get type(): string {
137 return this.data.type || '';
138 }
139}
140
141module.exports = Blob;