yeet
This commit is contained in:
141
node_modules/react-native/Libraries/Blob/Blob.js
generated
vendored
Normal file
141
node_modules/react-native/Libraries/Blob/Blob.js
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {BlobData, BlobOptions} from './BlobTypes';
|
||||
|
||||
/**
|
||||
* Opaque JS representation of some binary data in native.
|
||||
*
|
||||
* The API is modeled after the W3C Blob API, with one caveat
|
||||
* regarding explicit deallocation. Refer to the `close()`
|
||||
* method for further details.
|
||||
*
|
||||
* Example usage in a React component:
|
||||
*
|
||||
* class WebSocketImage extends React.Component {
|
||||
* state = {blob: null};
|
||||
* componentDidMount() {
|
||||
* let ws = this.ws = new WebSocket(...);
|
||||
* ws.binaryType = 'blob';
|
||||
* ws.onmessage = (event) => {
|
||||
* if (this.state.blob) {
|
||||
* this.state.blob.close();
|
||||
* }
|
||||
* this.setState({blob: event.data});
|
||||
* };
|
||||
* }
|
||||
* componentUnmount() {
|
||||
* if (this.state.blob) {
|
||||
* this.state.blob.close();
|
||||
* }
|
||||
* this.ws.close();
|
||||
* }
|
||||
* render() {
|
||||
* if (!this.state.blob) {
|
||||
* return <View />;
|
||||
* }
|
||||
* return <Image source={{uri: URL.createObjectURL(this.state.blob)}} />;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob
|
||||
*/
|
||||
class Blob {
|
||||
_data: ?BlobData;
|
||||
|
||||
/**
|
||||
* Constructor for JS consumers.
|
||||
* Currently we only support creating Blobs from other Blobs.
|
||||
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob
|
||||
*/
|
||||
constructor(parts: Array<Blob | string> = [], options?: BlobOptions) {
|
||||
const BlobManager = require('./BlobManager');
|
||||
this.data = BlobManager.createFromParts(parts, options).data;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is used to create a new Blob object containing
|
||||
* the data in the specified range of bytes of the source Blob.
|
||||
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice
|
||||
*/
|
||||
set data(data: ?BlobData) {
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
get data(): BlobData {
|
||||
if (!this._data) {
|
||||
throw new Error('Blob has been closed and is no longer available');
|
||||
}
|
||||
|
||||
return this._data;
|
||||
}
|
||||
|
||||
slice(start?: number, end?: number): Blob {
|
||||
const BlobManager = require('./BlobManager');
|
||||
let {offset, size} = this.data;
|
||||
|
||||
if (typeof start === 'number') {
|
||||
if (start > size) {
|
||||
start = size;
|
||||
}
|
||||
offset += start;
|
||||
size -= start;
|
||||
|
||||
if (typeof end === 'number') {
|
||||
if (end < 0) {
|
||||
end = this.size + end;
|
||||
}
|
||||
size = end - start;
|
||||
}
|
||||
}
|
||||
return BlobManager.createFromOptions({
|
||||
blobId: this.data.blobId,
|
||||
offset,
|
||||
size,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is in the standard, but not actually implemented by
|
||||
* any browsers at this point. It's important for how Blobs work in
|
||||
* React Native, however, since we cannot de-allocate resources automatically,
|
||||
* so consumers need to explicitly de-allocate them.
|
||||
*
|
||||
* Note that the semantics around Blobs created via `blob.slice()`
|
||||
* and `new Blob([blob])` are different. `blob.slice()` creates a
|
||||
* new *view* onto the same binary data, so calling `close()` on any
|
||||
* of those views is enough to deallocate the data, whereas
|
||||
* `new Blob([blob, ...])` actually copies the data in memory.
|
||||
*/
|
||||
close() {
|
||||
const BlobManager = require('./BlobManager');
|
||||
BlobManager.release(this.data.blobId);
|
||||
this.data = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the data contained in the Blob object, in bytes.
|
||||
*/
|
||||
get size(): number {
|
||||
return this.data.size;
|
||||
}
|
||||
|
||||
/*
|
||||
* String indicating the MIME type of the data contained in the Blob.
|
||||
* If the type is unknown, this string is empty.
|
||||
*/
|
||||
get type(): string {
|
||||
return this.data.type || '';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Blob;
|
182
node_modules/react-native/Libraries/Blob/BlobManager.js
generated
vendored
Normal file
182
node_modules/react-native/Libraries/Blob/BlobManager.js
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Blob = require('./Blob');
|
||||
const BlobRegistry = require('./BlobRegistry');
|
||||
|
||||
import type {BlobData, BlobOptions, BlobCollector} from './BlobTypes';
|
||||
import NativeBlobModule from './NativeBlobModule';
|
||||
import invariant from 'invariant';
|
||||
|
||||
/*eslint-disable no-bitwise */
|
||||
/*eslint-disable eqeqeq */
|
||||
|
||||
/**
|
||||
* Based on the rfc4122-compliant solution posted at
|
||||
* http://stackoverflow.com/questions/105034
|
||||
*/
|
||||
function uuidv4(): string {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
const r = (Math.random() * 16) | 0,
|
||||
v = c == 'x' ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
// **Temporary workaround**
|
||||
// TODO(#24654): Use turbomodules for the Blob module.
|
||||
// Blob collector is a jsi::HostObject that is used by native to know
|
||||
// when the a Blob instance is deallocated. This allows to free the
|
||||
// underlying native resources. This is a hack to workaround the fact
|
||||
// that the current bridge infra doesn't allow to track js objects
|
||||
// deallocation. Ideally the whole Blob object should be a jsi::HostObject.
|
||||
function createBlobCollector(blobId: string): BlobCollector | null {
|
||||
if (global.__blobCollectorProvider == null) {
|
||||
return null;
|
||||
} else {
|
||||
return global.__blobCollectorProvider(blobId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Module to manage blobs. Wrapper around the native blob module.
|
||||
*/
|
||||
class BlobManager {
|
||||
/**
|
||||
* If the native blob module is available.
|
||||
*/
|
||||
static isAvailable: boolean = !!NativeBlobModule;
|
||||
|
||||
/**
|
||||
* Create blob from existing array of blobs.
|
||||
*/
|
||||
static createFromParts(
|
||||
parts: Array<Blob | string>,
|
||||
options?: BlobOptions,
|
||||
): Blob {
|
||||
invariant(NativeBlobModule, 'NativeBlobModule is available.');
|
||||
|
||||
const blobId = uuidv4();
|
||||
const items = parts.map(part => {
|
||||
if (
|
||||
part instanceof ArrayBuffer ||
|
||||
(global.ArrayBufferView && part instanceof global.ArrayBufferView)
|
||||
) {
|
||||
throw new Error(
|
||||
"Creating blobs from 'ArrayBuffer' and 'ArrayBufferView' are not supported",
|
||||
);
|
||||
}
|
||||
if (part instanceof Blob) {
|
||||
return {
|
||||
data: part.data,
|
||||
type: 'blob',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
data: String(part),
|
||||
type: 'string',
|
||||
};
|
||||
}
|
||||
});
|
||||
const size = items.reduce((acc, curr) => {
|
||||
if (curr.type === 'string') {
|
||||
return acc + global.unescape(encodeURI(curr.data)).length;
|
||||
} else {
|
||||
return acc + curr.data.size;
|
||||
}
|
||||
}, 0);
|
||||
|
||||
NativeBlobModule.createFromParts(items, blobId);
|
||||
|
||||
return BlobManager.createFromOptions({
|
||||
blobId,
|
||||
offset: 0,
|
||||
size,
|
||||
type: options ? options.type : '',
|
||||
lastModified: options ? options.lastModified : Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create blob instance from blob data from native.
|
||||
* Used internally by modules like XHR, WebSocket, etc.
|
||||
*/
|
||||
static createFromOptions(options: BlobData): Blob {
|
||||
BlobRegistry.register(options.blobId);
|
||||
return Object.assign(Object.create(Blob.prototype), {
|
||||
data:
|
||||
// Reuse the collector instance when creating from an existing blob.
|
||||
// This will make sure that the underlying resource is only deallocated
|
||||
// when all blobs that refer to it are deallocated.
|
||||
options.__collector == null
|
||||
? {
|
||||
...options,
|
||||
__collector: createBlobCollector(options.blobId),
|
||||
}
|
||||
: options,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocate resources for a blob.
|
||||
*/
|
||||
static release(blobId: string): void {
|
||||
invariant(NativeBlobModule, 'NativeBlobModule is available.');
|
||||
|
||||
BlobRegistry.unregister(blobId);
|
||||
if (BlobRegistry.has(blobId)) {
|
||||
return;
|
||||
}
|
||||
NativeBlobModule.release(blobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the blob content handler in the networking module to support blob
|
||||
* requests and responses.
|
||||
*/
|
||||
static addNetworkingHandler(): void {
|
||||
invariant(NativeBlobModule, 'NativeBlobModule is available.');
|
||||
|
||||
NativeBlobModule.addNetworkingHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate the websocket should return a blob for incoming binary
|
||||
* messages.
|
||||
*/
|
||||
static addWebSocketHandler(socketId: number): void {
|
||||
invariant(NativeBlobModule, 'NativeBlobModule is available.');
|
||||
|
||||
NativeBlobModule.addWebSocketHandler(socketId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate the websocket should no longer return a blob for incoming
|
||||
* binary messages.
|
||||
*/
|
||||
static removeWebSocketHandler(socketId: number): void {
|
||||
invariant(NativeBlobModule, 'NativeBlobModule is available.');
|
||||
|
||||
NativeBlobModule.removeWebSocketHandler(socketId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a blob message to a websocket.
|
||||
*/
|
||||
static sendOverSocket(blob: Blob, socketId: number): void {
|
||||
invariant(NativeBlobModule, 'NativeBlobModule is available.');
|
||||
|
||||
NativeBlobModule.sendOverSocket(blob.data, socketId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BlobManager;
|
38
node_modules/react-native/Libraries/Blob/BlobRegistry.js
generated
vendored
Normal file
38
node_modules/react-native/Libraries/Blob/BlobRegistry.js
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
const registry: {[key: string]: number, ...} = {};
|
||||
|
||||
const register = (id: string) => {
|
||||
if (registry[id]) {
|
||||
registry[id]++;
|
||||
} else {
|
||||
registry[id] = 1;
|
||||
}
|
||||
};
|
||||
|
||||
const unregister = (id: string) => {
|
||||
if (registry[id]) {
|
||||
registry[id]--;
|
||||
if (registry[id] <= 0) {
|
||||
delete registry[id];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const has = (id: string): number | boolean => {
|
||||
return registry[id] && registry[id] > 0;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
register,
|
||||
unregister,
|
||||
has,
|
||||
};
|
30
node_modules/react-native/Libraries/Blob/BlobTypes.js
generated
vendored
Normal file
30
node_modules/react-native/Libraries/Blob/BlobTypes.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
export opaque type BlobCollector = {...};
|
||||
|
||||
export type BlobData = {
|
||||
blobId: string,
|
||||
offset: number,
|
||||
size: number,
|
||||
name?: string,
|
||||
type?: string,
|
||||
lastModified?: number,
|
||||
__collector?: ?BlobCollector,
|
||||
...
|
||||
};
|
||||
|
||||
export type BlobOptions = {
|
||||
type: string,
|
||||
lastModified: number,
|
||||
...
|
||||
};
|
56
node_modules/react-native/Libraries/Blob/File.js
generated
vendored
Normal file
56
node_modules/react-native/Libraries/Blob/File.js
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Blob = require('./Blob');
|
||||
|
||||
const invariant = require('invariant');
|
||||
|
||||
import type {BlobOptions} from './BlobTypes';
|
||||
|
||||
/**
|
||||
* The File interface provides information about files.
|
||||
*/
|
||||
class File extends Blob {
|
||||
/**
|
||||
* Constructor for JS consumers.
|
||||
*/
|
||||
constructor(
|
||||
parts: Array<Blob | string>,
|
||||
name: string,
|
||||
options?: BlobOptions,
|
||||
) {
|
||||
invariant(
|
||||
parts != null && name != null,
|
||||
'Failed to construct `File`: Must pass both `parts` and `name` arguments.',
|
||||
);
|
||||
|
||||
super(parts, options);
|
||||
this.data.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the file.
|
||||
*/
|
||||
get name(): string {
|
||||
invariant(this.data.name != null, 'Files must have a name set.');
|
||||
return this.data.name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Last modified time of the file.
|
||||
*/
|
||||
get lastModified(): number {
|
||||
return this.data.lastModified || 0;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = File;
|
166
node_modules/react-native/Libraries/Blob/FileReader.js
generated
vendored
Normal file
166
node_modules/react-native/Libraries/Blob/FileReader.js
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Blob = require('./Blob');
|
||||
const EventTarget = require('event-target-shim');
|
||||
|
||||
import NativeFileReaderModule from './NativeFileReaderModule';
|
||||
|
||||
type ReadyState =
|
||||
| 0 // EMPTY
|
||||
| 1 // LOADING
|
||||
| 2; // DONE
|
||||
|
||||
type ReaderResult = string | ArrayBuffer;
|
||||
|
||||
const READER_EVENTS = [
|
||||
'abort',
|
||||
'error',
|
||||
'load',
|
||||
'loadstart',
|
||||
'loadend',
|
||||
'progress',
|
||||
];
|
||||
|
||||
const EMPTY = 0;
|
||||
const LOADING = 1;
|
||||
const DONE = 2;
|
||||
|
||||
class FileReader extends (EventTarget(...READER_EVENTS): any) {
|
||||
static EMPTY: number = EMPTY;
|
||||
static LOADING: number = LOADING;
|
||||
static DONE: number = DONE;
|
||||
|
||||
EMPTY: number = EMPTY;
|
||||
LOADING: number = LOADING;
|
||||
DONE: number = DONE;
|
||||
|
||||
_readyState: ReadyState;
|
||||
_error: ?Error;
|
||||
_result: ?ReaderResult;
|
||||
_aborted: boolean = false;
|
||||
_subscriptions: Array<*> = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._reset();
|
||||
}
|
||||
|
||||
_reset(): void {
|
||||
this._readyState = EMPTY;
|
||||
this._error = null;
|
||||
this._result = null;
|
||||
}
|
||||
|
||||
_clearSubscriptions(): void {
|
||||
this._subscriptions.forEach(sub => sub.remove());
|
||||
this._subscriptions = [];
|
||||
}
|
||||
|
||||
_setReadyState(newState: ReadyState) {
|
||||
this._readyState = newState;
|
||||
this.dispatchEvent({type: 'readystatechange'});
|
||||
if (newState === DONE) {
|
||||
if (this._aborted) {
|
||||
this.dispatchEvent({type: 'abort'});
|
||||
} else if (this._error) {
|
||||
this.dispatchEvent({type: 'error'});
|
||||
} else {
|
||||
this.dispatchEvent({type: 'load'});
|
||||
}
|
||||
this.dispatchEvent({type: 'loadend'});
|
||||
}
|
||||
}
|
||||
|
||||
readAsArrayBuffer() {
|
||||
throw new Error('FileReader.readAsArrayBuffer is not implemented');
|
||||
}
|
||||
|
||||
readAsDataURL(blob: ?Blob) {
|
||||
this._aborted = false;
|
||||
|
||||
if (blob == null) {
|
||||
throw new TypeError(
|
||||
"Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'",
|
||||
);
|
||||
}
|
||||
|
||||
NativeFileReaderModule.readAsDataURL(blob.data).then(
|
||||
(text: string) => {
|
||||
if (this._aborted) {
|
||||
return;
|
||||
}
|
||||
this._result = text;
|
||||
this._setReadyState(DONE);
|
||||
},
|
||||
error => {
|
||||
if (this._aborted) {
|
||||
return;
|
||||
}
|
||||
this._error = error;
|
||||
this._setReadyState(DONE);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
readAsText(blob: ?Blob, encoding: string = 'UTF-8') {
|
||||
this._aborted = false;
|
||||
|
||||
if (blob == null) {
|
||||
throw new TypeError(
|
||||
"Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'",
|
||||
);
|
||||
}
|
||||
|
||||
NativeFileReaderModule.readAsText(blob.data, encoding).then(
|
||||
(text: string) => {
|
||||
if (this._aborted) {
|
||||
return;
|
||||
}
|
||||
this._result = text;
|
||||
this._setReadyState(DONE);
|
||||
},
|
||||
error => {
|
||||
if (this._aborted) {
|
||||
return;
|
||||
}
|
||||
this._error = error;
|
||||
this._setReadyState(DONE);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
abort() {
|
||||
this._aborted = true;
|
||||
// only call onreadystatechange if there is something to abort, as per spec
|
||||
if (this._readyState !== EMPTY && this._readyState !== DONE) {
|
||||
this._reset();
|
||||
this._setReadyState(DONE);
|
||||
}
|
||||
// Reset again after, in case modified in handler
|
||||
this._reset();
|
||||
}
|
||||
|
||||
get readyState(): ReadyState {
|
||||
return this._readyState;
|
||||
}
|
||||
|
||||
get error(): ?Error {
|
||||
return this._error;
|
||||
}
|
||||
|
||||
get result(): ?ReaderResult {
|
||||
return this._result;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileReader;
|
26
node_modules/react-native/Libraries/Blob/NativeBlobModule.js
generated
vendored
Normal file
26
node_modules/react-native/Libraries/Blob/NativeBlobModule.js
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {TurboModule} from '../TurboModule/RCTExport';
|
||||
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+getConstants: () => {|BLOB_URI_SCHEME: ?string, BLOB_URI_HOST: ?string|};
|
||||
+addNetworkingHandler: () => void;
|
||||
+addWebSocketHandler: (id: number) => void;
|
||||
+removeWebSocketHandler: (id: number) => void;
|
||||
+sendOverSocket: (blob: Object, socketID: number) => void;
|
||||
+createFromParts: (parts: Array<Object>, withId: string) => void;
|
||||
+release: (blobId: string) => void;
|
||||
}
|
||||
|
||||
export default (TurboModuleRegistry.get<Spec>('BlobModule'): ?Spec);
|
23
node_modules/react-native/Libraries/Blob/NativeFileReaderModule.js
generated
vendored
Normal file
23
node_modules/react-native/Libraries/Blob/NativeFileReaderModule.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {TurboModule} from '../TurboModule/RCTExport';
|
||||
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+readAsDataURL: (data: Object) => Promise<string>;
|
||||
+readAsText: (data: Object, encoding: string) => Promise<string>;
|
||||
}
|
||||
|
||||
export default (TurboModuleRegistry.getEnforcing<Spec>(
|
||||
'FileReaderModule',
|
||||
): Spec);
|
30
node_modules/react-native/Libraries/Blob/RCTBlobCollector.h
generated
vendored
Normal file
30
node_modules/react-native/Libraries/Blob/RCTBlobCollector.h
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <jsi/jsi.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
@class RCTBlobManager;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSI_EXPORT RCTBlobCollector : public jsi::HostObject {
|
||||
public:
|
||||
RCTBlobCollector(RCTBlobManager *blobManager, const std::string &blobId);
|
||||
~RCTBlobCollector();
|
||||
|
||||
static void install(RCTBlobManager *blobManager);
|
||||
|
||||
private:
|
||||
const std::string blobId_;
|
||||
RCTBlobManager *blobManager_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
52
node_modules/react-native/Libraries/Blob/RCTBlobCollector.mm
generated
vendored
Normal file
52
node_modules/react-native/Libraries/Blob/RCTBlobCollector.mm
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTBlobCollector.h"
|
||||
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBlobManager.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
RCTBlobCollector::RCTBlobCollector(RCTBlobManager *blobManager, const std::string &blobId)
|
||||
: blobId_(blobId), blobManager_(blobManager) {}
|
||||
|
||||
RCTBlobCollector::~RCTBlobCollector() {
|
||||
RCTBlobManager *blobManager = blobManager_;
|
||||
NSString *blobId = [NSString stringWithUTF8String:blobId_.c_str()];
|
||||
dispatch_async([blobManager_ methodQueue], ^{
|
||||
[blobManager remove:blobId];
|
||||
});
|
||||
}
|
||||
|
||||
void RCTBlobCollector::install(RCTBlobManager *blobManager) {
|
||||
__weak RCTCxxBridge *cxxBridge = (RCTCxxBridge *)blobManager.bridge;
|
||||
[cxxBridge dispatchBlock:^{
|
||||
if (!cxxBridge || cxxBridge.runtime == nullptr) {
|
||||
return;
|
||||
}
|
||||
jsi::Runtime &runtime = *(jsi::Runtime *)cxxBridge.runtime;
|
||||
runtime.global().setProperty(
|
||||
runtime,
|
||||
"__blobCollectorProvider",
|
||||
jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
jsi::PropNameID::forAscii(runtime, "__blobCollectorProvider"),
|
||||
1,
|
||||
[blobManager](jsi::Runtime& rt, const jsi::Value& thisVal, const jsi::Value* args, size_t count) {
|
||||
auto blobId = args[0].asString(rt).utf8(rt);
|
||||
auto blobCollector = std::make_shared<RCTBlobCollector>(blobManager, blobId);
|
||||
return jsi::Object::createFromHostObject(rt, blobCollector);
|
||||
}
|
||||
)
|
||||
);
|
||||
} queue:RCTJSThread];
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
28
node_modules/react-native/Libraries/Blob/RCTBlobManager.h
generated
vendored
Executable file
28
node_modules/react-native/Libraries/Blob/RCTBlobManager.h
generated
vendored
Executable file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTURLRequestHandler.h>
|
||||
|
||||
@interface RCTBlobManager : NSObject <RCTBridgeModule, RCTURLRequestHandler>
|
||||
|
||||
- (NSString *)store:(NSData *)data;
|
||||
|
||||
- (void)store:(NSData *)data withId:(NSString *)blobId;
|
||||
|
||||
- (NSData *)resolve:(NSDictionary<NSString *, id> *)blob;
|
||||
|
||||
- (NSData *)resolve:(NSString *)blobId offset:(NSInteger)offset size:(NSInteger)size;
|
||||
|
||||
- (NSData *)resolveURL:(NSURL *)url;
|
||||
|
||||
- (void)remove:(NSString *)blobId;
|
||||
|
||||
- (void)createFromParts:(NSArray<NSDictionary<NSString *, id> *> *)parts withId:(NSString *)blobId;
|
||||
|
||||
@end
|
325
node_modules/react-native/Libraries/Blob/RCTBlobManager.mm
generated
vendored
Executable file
325
node_modules/react-native/Libraries/Blob/RCTBlobManager.mm
generated
vendored
Executable file
@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBlobManager.h>
|
||||
|
||||
#import <mutex>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTNetworking.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <React/RCTWebSocketModule.h>
|
||||
|
||||
#import "RCTBlobPlugins.h"
|
||||
#import "RCTBlobCollector.h"
|
||||
|
||||
static NSString *const kBlobURIScheme = @"blob";
|
||||
|
||||
@interface RCTBlobManager () <RCTNetworkingRequestHandler, RCTNetworkingResponseHandler, RCTWebSocketContentHandler, NativeBlobModuleSpec>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBlobManager
|
||||
{
|
||||
// Blobs should be thread safe since they are used from the websocket and networking module,
|
||||
// make sure to use proper locking when accessing this.
|
||||
NSMutableDictionary<NSString *, NSData *> *_blobs;
|
||||
std::mutex _blobsMutex;
|
||||
|
||||
NSOperationQueue *_queue;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE(BlobModule)
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@synthesize methodQueue = _methodQueue;
|
||||
@synthesize turboModuleLookupDelegate = _turboModuleLookupDelegate;
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_bridge = bridge;
|
||||
|
||||
std::lock_guard<std::mutex> lock(_blobsMutex);
|
||||
_blobs = [NSMutableDictionary new];
|
||||
|
||||
facebook::react::RCTBlobCollector::install(self);
|
||||
}
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)constantsToExport
|
||||
{
|
||||
return [self getConstants];
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)getConstants
|
||||
{
|
||||
return @{
|
||||
@"BLOB_URI_SCHEME": kBlobURIScheme,
|
||||
@"BLOB_URI_HOST": [NSNull null],
|
||||
};
|
||||
}
|
||||
|
||||
- (NSString *)store:(NSData *)data
|
||||
{
|
||||
NSString *blobId = [NSUUID UUID].UUIDString;
|
||||
[self store:data withId:blobId];
|
||||
return blobId;
|
||||
}
|
||||
|
||||
- (void)store:(NSData *)data withId:(NSString *)blobId
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_blobsMutex);
|
||||
_blobs[blobId] = data;
|
||||
}
|
||||
|
||||
- (NSData *)resolve:(NSDictionary<NSString *, id> *)blob
|
||||
{
|
||||
NSString *blobId = [RCTConvert NSString:blob[@"blobId"]];
|
||||
NSNumber *offset = [RCTConvert NSNumber:blob[@"offset"]];
|
||||
NSNumber *size = [RCTConvert NSNumber:blob[@"size"]];
|
||||
return [self resolve:blobId
|
||||
offset:offset ? [offset integerValue] : 0
|
||||
size:size ? [size integerValue] : -1];
|
||||
}
|
||||
|
||||
- (NSData *)resolve:(NSString *)blobId offset:(NSInteger)offset size:(NSInteger)size
|
||||
{
|
||||
NSData *data;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_blobsMutex);
|
||||
data = _blobs[blobId];
|
||||
}
|
||||
if (!data) {
|
||||
return nil;
|
||||
}
|
||||
if (offset != 0 || (size != -1 && size != data.length)) {
|
||||
data = [data subdataWithRange:NSMakeRange(offset, size)];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
- (NSData *)resolveURL:(NSURL *)url
|
||||
{
|
||||
NSURLComponents *components = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
|
||||
|
||||
NSString *blobId = components.path;
|
||||
NSInteger offset = 0;
|
||||
NSInteger size = -1;
|
||||
|
||||
if (components.queryItems) {
|
||||
for (NSURLQueryItem *queryItem in components.queryItems) {
|
||||
if ([queryItem.name isEqualToString:@"offset"]) {
|
||||
offset = [queryItem.value integerValue];
|
||||
}
|
||||
if ([queryItem.name isEqualToString:@"size"]) {
|
||||
size = [queryItem.value integerValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blobId) {
|
||||
return [self resolve:blobId offset:offset size:size];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)remove:(NSString *)blobId
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_blobsMutex);
|
||||
[_blobs removeObjectForKey:blobId];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(addNetworkingHandler)
|
||||
{
|
||||
RCTNetworking *const networking = _bridge ? _bridge.networking : [_turboModuleLookupDelegate moduleForName:"RCTNetworking"];
|
||||
|
||||
// TODO(T63516227): Why can methodQueue be nil here?
|
||||
// We don't want to do anything when methodQueue is nil.
|
||||
if (!networking.methodQueue) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(networking.methodQueue, ^{
|
||||
[networking addRequestHandler:self];
|
||||
[networking addResponseHandler:self];
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(addWebSocketHandler:(double)socketID)
|
||||
{
|
||||
dispatch_async(_bridge.webSocketModule.methodQueue, ^{
|
||||
[self->_bridge.webSocketModule setContentHandler:self forSocketID:[NSNumber numberWithDouble:socketID]];
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(removeWebSocketHandler:(double)socketID)
|
||||
{
|
||||
dispatch_async(_bridge.webSocketModule.methodQueue, ^{
|
||||
[self->_bridge.webSocketModule setContentHandler:nil forSocketID:[NSNumber numberWithDouble:socketID]];
|
||||
});
|
||||
}
|
||||
|
||||
// @lint-ignore FBOBJCUNTYPEDCOLLECTION1
|
||||
RCT_EXPORT_METHOD(sendOverSocket:(NSDictionary *)blob socketID:(double)socketID)
|
||||
{
|
||||
dispatch_async(_bridge.webSocketModule.methodQueue, ^{
|
||||
[self->_bridge.webSocketModule sendData:[self resolve:blob] forSocketID:[NSNumber numberWithDouble:socketID]];
|
||||
});
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(createFromParts:(NSArray<NSDictionary<NSString *, id> *> *)parts withId:(NSString *)blobId)
|
||||
{
|
||||
NSMutableData *data = [NSMutableData new];
|
||||
for (NSDictionary<NSString *, id> *part in parts) {
|
||||
NSString *type = [RCTConvert NSString:part[@"type"]];
|
||||
|
||||
if ([type isEqualToString:@"blob"]) {
|
||||
NSData *partData = [self resolve:part[@"data"]];
|
||||
[data appendData:partData];
|
||||
} else if ([type isEqualToString:@"string"]) {
|
||||
NSData *partData = [[RCTConvert NSString:part[@"data"]] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[data appendData:partData];
|
||||
} else {
|
||||
[NSException raise:@"Invalid type for blob" format:@"%@ is invalid", type];
|
||||
}
|
||||
}
|
||||
[self store:data withId:blobId];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(release:(NSString *)blobId)
|
||||
{
|
||||
[self remove:blobId];
|
||||
}
|
||||
|
||||
#pragma mark - RCTURLRequestHandler methods
|
||||
|
||||
- (BOOL)canHandleRequest:(NSURLRequest *)request
|
||||
{
|
||||
return [request.URL.scheme caseInsensitiveCompare:kBlobURIScheme] == NSOrderedSame;
|
||||
}
|
||||
|
||||
- (id)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate
|
||||
{
|
||||
// Lazy setup
|
||||
if (!_queue) {
|
||||
_queue = [NSOperationQueue new];
|
||||
_queue.maxConcurrentOperationCount = 2;
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
__weak __block NSBlockOperation *weakOp;
|
||||
__block NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
|
||||
__typeof(self) strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL
|
||||
MIMEType:nil
|
||||
expectedContentLength:-1
|
||||
textEncodingName:nil];
|
||||
|
||||
[delegate URLRequest:weakOp didReceiveResponse:response];
|
||||
|
||||
NSData *data = [strongSelf resolveURL:response.URL];
|
||||
NSError *error;
|
||||
if (data) {
|
||||
[delegate URLRequest:weakOp didReceiveData:data];
|
||||
} else {
|
||||
error = [[NSError alloc] initWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];
|
||||
}
|
||||
[delegate URLRequest:weakOp didCompleteWithError:error];
|
||||
}];
|
||||
|
||||
weakOp = op;
|
||||
[_queue addOperation:op];
|
||||
return op;
|
||||
}
|
||||
|
||||
- (void)cancelRequest:(NSOperation *)op
|
||||
{
|
||||
[op cancel];
|
||||
}
|
||||
|
||||
#pragma mark - RCTNetworkingRequestHandler methods
|
||||
|
||||
// @lint-ignore FBOBJCUNTYPEDCOLLECTION1
|
||||
- (BOOL)canHandleNetworkingRequest:(NSDictionary *)data
|
||||
{
|
||||
return data[@"blob"] != nil;
|
||||
}
|
||||
|
||||
// @lint-ignore FBOBJCUNTYPEDCOLLECTION1
|
||||
- (NSDictionary *)handleNetworkingRequest:(NSDictionary *)data
|
||||
{
|
||||
// @lint-ignore FBOBJCUNTYPEDCOLLECTION1
|
||||
NSDictionary *blob = [RCTConvert NSDictionary:data[@"blob"]];
|
||||
|
||||
NSString *contentType = @"application/octet-stream";
|
||||
NSString *blobType = [RCTConvert NSString:blob[@"type"]];
|
||||
if (blobType != nil && blobType.length > 0) {
|
||||
contentType = blob[@"type"];
|
||||
}
|
||||
|
||||
return @{@"body": [self resolve:blob], @"contentType": contentType};
|
||||
}
|
||||
|
||||
- (BOOL)canHandleNetworkingResponse:(NSString *)responseType
|
||||
{
|
||||
return [responseType isEqualToString:@"blob"];
|
||||
}
|
||||
|
||||
- (id)handleNetworkingResponse:(NSURLResponse *)response data:(NSData *)data
|
||||
{
|
||||
// An empty body will have nil for data, in this case we need to return
|
||||
// an empty blob as per the XMLHttpRequest spec.
|
||||
data = data ?: [NSData new];
|
||||
return @{
|
||||
@"blobId": [self store:data],
|
||||
@"offset": @0,
|
||||
@"size": @(data.length),
|
||||
@"name": RCTNullIfNil([response suggestedFilename]),
|
||||
@"type": RCTNullIfNil([response MIMEType]),
|
||||
};
|
||||
}
|
||||
|
||||
#pragma mark - RCTWebSocketContentHandler methods
|
||||
|
||||
- (id)processWebsocketMessage:(id)message
|
||||
forSocketID:(NSNumber *)socketID
|
||||
withType:(NSString *__autoreleasing _Nonnull *)type
|
||||
{
|
||||
if (![message isKindOfClass:[NSData class]]) {
|
||||
*type = @"text";
|
||||
return message;
|
||||
}
|
||||
|
||||
*type = @"blob";
|
||||
return @{
|
||||
@"blobId": [self store:message],
|
||||
@"offset": @0,
|
||||
@"size": @(((NSData *)message).length),
|
||||
};
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeBlobModuleSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTBlobManagerCls(void) {
|
||||
return RCTBlobManager.class;
|
||||
}
|
41
node_modules/react-native/Libraries/Blob/RCTBlobPlugins.h
generated
vendored
Normal file
41
node_modules/react-native/Libraries/Blob/RCTBlobPlugins.h
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated by an internal plugin build system
|
||||
*/
|
||||
|
||||
#ifdef RN_DISABLE_OSS_PLUGIN_HEADER
|
||||
|
||||
// FB Internal: FBRCTBlobPlugins.h is autogenerated by the build system.
|
||||
#import <React/FBRCTBlobPlugins.h>
|
||||
|
||||
#else
|
||||
|
||||
// OSS-compatibility layer
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// RCTTurboModuleManagerDelegate should call this to resolve module classes.
|
||||
Class RCTBlobClassProvider(const char *name);
|
||||
|
||||
// Lookup functions
|
||||
Class RCTFileReaderModuleCls(void) __attribute__((used));
|
||||
Class RCTBlobManagerCls(void) __attribute__((used));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
|
33
node_modules/react-native/Libraries/Blob/RCTBlobPlugins.mm
generated
vendored
Normal file
33
node_modules/react-native/Libraries/Blob/RCTBlobPlugins.mm
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated by an internal plugin build system
|
||||
*/
|
||||
|
||||
#ifndef RN_DISABLE_OSS_PLUGIN_HEADER
|
||||
|
||||
// OSS-compatibility layer
|
||||
|
||||
#import "RCTBlobPlugins.h"
|
||||
|
||||
#import <string>
|
||||
#import <unordered_map>
|
||||
|
||||
Class RCTBlobClassProvider(const char *name) {
|
||||
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
|
||||
{"FileReaderModule", RCTFileReaderModuleCls},
|
||||
{"BlobModule", RCTBlobManagerCls},
|
||||
};
|
||||
|
||||
auto p = sCoreModuleClassMap.find(name);
|
||||
if (p != sCoreModuleClassMap.end()) {
|
||||
auto classFunc = p->second;
|
||||
return classFunc();
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
|
12
node_modules/react-native/Libraries/Blob/RCTFileReaderModule.h
generated
vendored
Normal file
12
node_modules/react-native/Libraries/Blob/RCTFileReaderModule.h
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RCTFileReaderModule : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
87
node_modules/react-native/Libraries/Blob/RCTFileReaderModule.mm
generated
vendored
Normal file
87
node_modules/react-native/Libraries/Blob/RCTFileReaderModule.mm
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
|
||||
#import <React/RCTFileReaderModule.h>
|
||||
|
||||
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTConvert.h>
|
||||
|
||||
#import <React/RCTBlobManager.h>
|
||||
|
||||
#import "RCTBlobPlugins.h"
|
||||
|
||||
@interface RCTFileReaderModule() <NativeFileReaderModuleSpec>
|
||||
@end
|
||||
|
||||
@implementation RCTFileReaderModule
|
||||
|
||||
RCT_EXPORT_MODULE(FileReaderModule)
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_METHOD(readAsText:(NSDictionary<NSString *, id> *)blob
|
||||
encoding:(NSString *)encoding
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
RCTBlobManager *blobManager = [[self bridge] moduleForClass:[RCTBlobManager class]];
|
||||
NSData *data = [blobManager resolve:blob];
|
||||
|
||||
if (data == nil) {
|
||||
reject(RCTErrorUnspecified,
|
||||
[NSString stringWithFormat:@"Unable to resolve data for blob: %@", [RCTConvert NSString:blob[@"blobId"]]], nil);
|
||||
} else {
|
||||
NSStringEncoding stringEncoding;
|
||||
|
||||
if (encoding == nil) {
|
||||
stringEncoding = NSUTF8StringEncoding;
|
||||
} else {
|
||||
stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef) encoding));
|
||||
}
|
||||
|
||||
NSString *text = [[NSString alloc] initWithData:data encoding:stringEncoding];
|
||||
|
||||
resolve(text);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(readAsDataURL:(NSDictionary<NSString *, id> *)blob
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
RCTBlobManager *blobManager = [[self bridge] moduleForClass:[RCTBlobManager class]];
|
||||
NSData *data = [blobManager resolve:blob];
|
||||
|
||||
if (data == nil) {
|
||||
reject(RCTErrorUnspecified,
|
||||
[NSString stringWithFormat:@"Unable to resolve data for blob: %@", [RCTConvert NSString:blob[@"blobId"]]], nil);
|
||||
} else {
|
||||
NSString *type = [RCTConvert NSString:blob[@"type"]];
|
||||
NSString *text = [NSString stringWithFormat:@"data:%@;base64,%@",
|
||||
type != nil && [type length] > 0 ? type : @"application/octet-stream",
|
||||
[data base64EncodedStringWithOptions:0]];
|
||||
|
||||
resolve(text);
|
||||
}
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeFileReaderModuleSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTFileReaderModuleCls(void)
|
||||
{
|
||||
return RCTFileReaderModule.class;
|
||||
}
|
49
node_modules/react-native/Libraries/Blob/React-RCTBlob.podspec
generated
vendored
Normal file
49
node_modules/react-native/Libraries/Blob/React-RCTBlob.podspec
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
folly_version = '2020.01.13.00'
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-RCTBlob"
|
||||
s.version = version
|
||||
s.summary = "An API for displaying iOS action sheets and share sheets."
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Facebook, Inc. and its affiliates"
|
||||
s.platforms = { :ios => "10.0", :tvos => "10.0" }
|
||||
s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness'
|
||||
s.source = source
|
||||
s.source_files = "*.{m,mm}"
|
||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||
s.header_dir = "RCTBlob"
|
||||
s.pod_target_xcconfig = {
|
||||
"USE_HEADERMAP" => "YES",
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++14",
|
||||
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
|
||||
s.dependency "Folly", folly_version
|
||||
s.dependency "FBReactNativeSpec", version
|
||||
s.dependency "ReactCommon/turbomodule/core", version
|
||||
s.dependency "React-jsi", version
|
||||
s.dependency "React-Core/RCTBlobHeaders", version
|
||||
s.dependency "React-Core/RCTWebSocket", version
|
||||
s.dependency "React-RCTNetwork", version
|
||||
s.dependency "React-jsi", version
|
||||
end
|
222
node_modules/react-native/Libraries/Blob/URL.js
generated
vendored
Normal file
222
node_modules/react-native/Libraries/Blob/URL.js
generated
vendored
Normal file
@ -0,0 +1,222 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Blob = require('./Blob');
|
||||
|
||||
import NativeBlobModule from './NativeBlobModule';
|
||||
|
||||
let BLOB_URL_PREFIX = null;
|
||||
|
||||
if (
|
||||
NativeBlobModule &&
|
||||
typeof NativeBlobModule.getConstants().BLOB_URI_SCHEME === 'string'
|
||||
) {
|
||||
const constants = NativeBlobModule.getConstants();
|
||||
BLOB_URL_PREFIX = constants.BLOB_URI_SCHEME + ':';
|
||||
if (typeof constants.BLOB_URI_HOST === 'string') {
|
||||
BLOB_URL_PREFIX += `//${constants.BLOB_URI_HOST}/`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To allow Blobs be accessed via `content://` URIs,
|
||||
* you need to register `BlobProvider` as a ContentProvider in your app's `AndroidManifest.xml`:
|
||||
*
|
||||
* ```xml
|
||||
* <manifest>
|
||||
* <application>
|
||||
* <provider
|
||||
* android:name="com.facebook.react.modules.blob.BlobProvider"
|
||||
* android:authorities="@string/blob_provider_authority"
|
||||
* android:exported="false"
|
||||
* />
|
||||
* </application>
|
||||
* </manifest>
|
||||
* ```
|
||||
* And then define the `blob_provider_authority` string in `res/values/strings.xml`.
|
||||
* Use a dotted name that's entirely unique to your app:
|
||||
*
|
||||
* ```xml
|
||||
* <resources>
|
||||
* <string name="blob_provider_authority">your.app.package.blobs</string>
|
||||
* </resources>
|
||||
* ```
|
||||
*/
|
||||
|
||||
// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/lib
|
||||
// The reference code bloat comes from Unicode issues with URLs, so those won't work here.
|
||||
export class URLSearchParams {
|
||||
_searchParams = [];
|
||||
|
||||
constructor(params: any) {
|
||||
if (typeof params === 'object') {
|
||||
Object.keys(params).forEach(key => this.append(key, params[key]));
|
||||
}
|
||||
}
|
||||
|
||||
append(key: string, value: string) {
|
||||
this._searchParams.push([key, value]);
|
||||
}
|
||||
|
||||
delete(name) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get(name) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
getAll(name) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
has(name) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
set(name, value) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
sort() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this._searchParams[Symbol.iterator]();
|
||||
}
|
||||
|
||||
toString() {
|
||||
if (this._searchParams.length === 0) {
|
||||
return '';
|
||||
}
|
||||
const last = this._searchParams.length - 1;
|
||||
return this._searchParams.reduce((acc, curr, index) => {
|
||||
return acc + curr.join('=') + (index === last ? '' : '&');
|
||||
}, '');
|
||||
}
|
||||
}
|
||||
|
||||
function validateBaseUrl(url: string) {
|
||||
// from this MIT-licensed gist: https://gist.github.com/dperini/729294
|
||||
return /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
|
||||
url,
|
||||
);
|
||||
}
|
||||
|
||||
export class URL {
|
||||
_searchParamsInstance = null;
|
||||
|
||||
static createObjectURL(blob: Blob) {
|
||||
if (BLOB_URL_PREFIX === null) {
|
||||
throw new Error('Cannot create URL for blob!');
|
||||
}
|
||||
return `${BLOB_URL_PREFIX}${blob.data.blobId}?offset=${
|
||||
blob.data.offset
|
||||
}&size=${blob.size}`;
|
||||
}
|
||||
|
||||
static revokeObjectURL(url: string) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
constructor(url: string, base: string) {
|
||||
let baseUrl = null;
|
||||
if (!base || validateBaseUrl(url)) {
|
||||
this._url = url;
|
||||
if (!this._url.endsWith('/')) {
|
||||
this._url += '/';
|
||||
}
|
||||
} else {
|
||||
if (typeof base === 'string') {
|
||||
baseUrl = base;
|
||||
if (!validateBaseUrl(baseUrl)) {
|
||||
throw new TypeError(`Invalid base URL: ${baseUrl}`);
|
||||
}
|
||||
} else if (typeof base === 'object') {
|
||||
baseUrl = base.toString();
|
||||
}
|
||||
if (baseUrl.endsWith('/')) {
|
||||
baseUrl = baseUrl.slice(0, baseUrl.length - 1);
|
||||
}
|
||||
if (!url.startsWith('/')) {
|
||||
url = `/${url}`;
|
||||
}
|
||||
if (baseUrl.endsWith(url)) {
|
||||
url = '';
|
||||
}
|
||||
this._url = `${baseUrl}${url}`;
|
||||
}
|
||||
}
|
||||
|
||||
get hash() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get host() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get hostname() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get href(): string {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
get origin() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get password() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get pathname() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get port() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get protocol() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get search() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
get searchParams(): URLSearchParams {
|
||||
if (this._searchParamsInstance == null) {
|
||||
this._searchParamsInstance = new URLSearchParams();
|
||||
}
|
||||
return this._searchParamsInstance;
|
||||
}
|
||||
|
||||
toJSON(): string {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
if (this._searchParamsInstance === null) {
|
||||
return this._url;
|
||||
}
|
||||
const separator = this._url.indexOf('?') > -1 ? '&' : '?';
|
||||
return this._url + separator + this._searchParamsInstance.toString();
|
||||
}
|
||||
|
||||
get username() {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
}
|
16
node_modules/react-native/Libraries/Blob/__mocks__/BlobModule.js
generated
vendored
Normal file
16
node_modules/react-native/Libraries/Blob/__mocks__/BlobModule.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
const BlobModule = {
|
||||
createFromParts() {},
|
||||
release() {},
|
||||
};
|
||||
|
||||
module.exports = BlobModule;
|
20
node_modules/react-native/Libraries/Blob/__mocks__/FileReaderModule.js
generated
vendored
Normal file
20
node_modules/react-native/Libraries/Blob/__mocks__/FileReaderModule.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
const FileReaderModule = {
|
||||
async readAsText(): Promise<string> {
|
||||
return '';
|
||||
},
|
||||
async readAsDataURL(): Promise<string> {
|
||||
return 'data:text/plain;base64,NDI=';
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = FileReaderModule;
|
Reference in New Issue
Block a user