From 3e989b65191cdf97b03fe2461e008dec915e5b0c Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Fri, 19 Jul 2019 12:02:19 -0700 Subject: [PATCH] Add NativeModule Spec for AsyncStorage Summary: Two NativeModules (SQLiteDBStorage on Android and AsyncLocalStorage on iOS) implement the AsyncStorage interface. So, I created one spec file for both. Reviewed By: fkgozali Differential Revision: D15804415 fbshipit-source-id: 0c922352378fbdb460839527db3c21387ab16b87 --- .../FBReactNativeSpec-generated.mm | 91 +++++++++++ .../FBReactNativeSpec/FBReactNativeSpec.h | 153 ++++++++++++++++++ Libraries/Storage/AsyncStorage.js | 16 +- Libraries/Storage/NativeAsyncStorage.js | 44 +++++ 4 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 Libraries/Storage/NativeAsyncStorage.js diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm index ffb28154981..65ff935e232 100644 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm +++ b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm @@ -434,6 +434,97 @@ namespace facebook { + } + + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiGetCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiGetCallbackErrorsElement:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiSetCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiSetCallbackErrorsElement:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeAsyncStorage_SpecClearCallbackError) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecClearCallbackError:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeAsyncStorage_SpecGetAllKeysCallbackError) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecGetAllKeysCallbackError:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + + static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiGet(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiGet", @selector(multiGet:callback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiSet(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiSet", @selector(multiSet:callback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiMerge(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiMerge", @selector(multiMerge:callback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiRemove(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiRemove", @selector(multiRemove:callback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_clear(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "clear", @selector(clear:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_getAllKeys(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getAllKeys", @selector(getAllKeys:), args, count); + } + + + NativeAsyncStorageSpecJSI::NativeAsyncStorageSpecJSI(id instance, std::shared_ptr jsInvoker) + : ObjCTurboModule("AsyncStorage", instance, jsInvoker) { + + methodMap_["multiGet"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiGet}; + + + methodMap_["multiSet"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiSet}; + + + methodMap_["multiMerge"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiMerge}; + + + methodMap_["multiRemove"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiRemove}; + + + methodMap_["clear"] = MethodMetadata {1, __hostFunction_NativeAsyncStorageSpecJSI_clear}; + + + methodMap_["getAllKeys"] = MethodMetadata {1, __hostFunction_NativeAsyncStorageSpecJSI_getAllKeys}; + + + } } // namespace react diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h index cf72ed17a52..b8e16f32f23 100644 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +++ b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h @@ -405,6 +405,129 @@ namespace facebook { } // namespace react } // namespace facebook +namespace JS { + namespace NativeAsyncStorage { + struct SpecMultiGetCallbackErrorsElement { + NSString *message() const; + + SpecMultiGetCallbackErrorsElement(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiGetCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiGetCallbackErrorsElement:(id)json; +@end + +namespace JS { + namespace NativeAsyncStorage { + struct SpecMultiSetCallbackErrorsElement { + NSString *message() const; + + SpecMultiSetCallbackErrorsElement(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiSetCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiSetCallbackErrorsElement:(id)json; +@end + +namespace JS { + namespace NativeAsyncStorage { + struct SpecMultiMergeCallbackErrorsElement { + NSString *message() const; + + SpecMultiMergeCallbackErrorsElement(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement:(id)json; +@end + +namespace JS { + namespace NativeAsyncStorage { + struct SpecMultiRemoveCallbackErrorsElement { + NSString *message() const; + + SpecMultiRemoveCallbackErrorsElement(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement:(id)json; +@end + +namespace JS { + namespace NativeAsyncStorage { + struct SpecClearCallbackError { + NSString *message() const; + + SpecClearCallbackError(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeAsyncStorage_SpecClearCallbackError) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecClearCallbackError:(id)json; +@end + +namespace JS { + namespace NativeAsyncStorage { + struct SpecGetAllKeysCallbackError { + NSString *message() const; + + SpecGetAllKeysCallbackError(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeAsyncStorage_SpecGetAllKeysCallbackError) ++ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecGetAllKeysCallbackError:(id)json; +@end +@protocol NativeAsyncStorageSpec + +- (void)multiGet:(NSArray *)keys + callback:(RCTResponseSenderBlock)callback; +- (void)multiSet:(NSArray *)kvPairs + callback:(RCTResponseSenderBlock)callback; +- (void)multiMerge:(NSArray *)kvPairs + callback:(RCTResponseSenderBlock)callback; +- (void)multiRemove:(NSArray *)keys + callback:(RCTResponseSenderBlock)callback; +- (void)clear:(RCTResponseSenderBlock)callback; +- (void)getAllKeys:(RCTResponseSenderBlock)callback; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'AsyncStorage' + */ + + class JSI_EXPORT NativeAsyncStorageSpecJSI : public ObjCTurboModule { + public: + NativeAsyncStorageSpecJSI(id instance, std::shared_ptr jsInvoker); + + }; + } // namespace react +} // namespace facebook + namespace JS { namespace NativeBlobModule { struct Constants { @@ -2044,6 +2167,36 @@ inline JS::NativeAppState::Constants::Builder::Builder(const Input i) : _factory inline JS::NativeAppState::Constants::Builder::Builder(Constants i) : _factory(^{ return i.unsafeRawValue(); }) {} +inline NSString *JS::NativeAsyncStorage::SpecMultiGetCallbackErrorsElement::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} +inline NSString *JS::NativeAsyncStorage::SpecMultiSetCallbackErrorsElement::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} +inline NSString *JS::NativeAsyncStorage::SpecMultiMergeCallbackErrorsElement::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} +inline NSString *JS::NativeAsyncStorage::SpecMultiRemoveCallbackErrorsElement::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} +inline NSString *JS::NativeAsyncStorage::SpecClearCallbackError::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} +inline NSString *JS::NativeAsyncStorage::SpecGetAllKeysCallbackError::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} inline JS::NativeBlobModule::Constants::Builder::Builder(const Input i) : _factory(^{ NSMutableDictionary *d = [NSMutableDictionary new]; auto BLOB_URI_SCHEME = i.BLOB_URI_SCHEME.get(); diff --git a/Libraries/Storage/AsyncStorage.js b/Libraries/Storage/AsyncStorage.js index 5341eacbe4b..5c749a93805 100644 --- a/Libraries/Storage/AsyncStorage.js +++ b/Libraries/Storage/AsyncStorage.js @@ -12,11 +12,11 @@ 'use strict'; -const NativeModules = require('../BatchedBridge/NativeModules'); +import NativeAsyncStorage from './NativeAsyncStorage'; +import invariant from 'invariant'; // Use SQLite if available, otherwise file storage. -const RCTAsyncStorage = - NativeModules.AsyncSQLiteDBStorage || NativeModules.AsyncLocalStorage; +const RCTAsyncStorage = NativeAsyncStorage; /** * `AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value @@ -39,6 +39,7 @@ const AsyncStorage = { key: string, callback?: ?(error: ?Error, result: ?string) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiGet([key], function(errors, result) { // Unpack result to get value from [[key,value]] @@ -64,6 +65,7 @@ const AsyncStorage = { value: string, callback?: ?(error: ?Error) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiSet([[key, value]], function(errors) { const errs = convertErrors(errors); @@ -86,6 +88,7 @@ const AsyncStorage = { key: string, callback?: ?(error: ?Error) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiRemove([key], function(errors) { const errs = convertErrors(errors); @@ -112,6 +115,7 @@ const AsyncStorage = { value: string, callback?: ?(error: ?Error) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiMerge([[key, value]], function(errors) { const errs = convertErrors(errors); @@ -133,6 +137,7 @@ const AsyncStorage = { * See http://facebook.github.io/react-native/docs/asyncstorage.html#clear */ clear: function(callback?: ?(error: ?Error) => void): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.clear(function(error) { callback && callback(convertError(error)); @@ -153,6 +158,7 @@ const AsyncStorage = { getAllKeys: function( callback?: ?(error: ?Error, keys: ?Array) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.getAllKeys(function(error, keys) { callback && callback(convertError(error), keys); @@ -187,6 +193,7 @@ const AsyncStorage = { this._getRequests = []; this._getKeys = []; + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); RCTAsyncStorage.multiGet(getKeys, function(errors, result) { // Even though the runtime complexity of this is theoretically worse vs if we used a map, // it's much, much faster in practice for the data sets we deal with (we avoid @@ -264,6 +271,7 @@ const AsyncStorage = { keyValuePairs: Array>, callback?: ?(errors: ?Array) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiSet(keyValuePairs, function(errors) { const error = convertErrors(errors); @@ -286,6 +294,7 @@ const AsyncStorage = { keys: Array, callback?: ?(errors: ?Array) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiRemove(keys, function(errors) { const error = convertErrors(errors); @@ -311,6 +320,7 @@ const AsyncStorage = { keyValuePairs: Array>, callback?: ?(errors: ?Array) => void, ): Promise { + invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiMerge(keyValuePairs, function(errors) { const error = convertErrors(errors); diff --git a/Libraries/Storage/NativeAsyncStorage.js b/Libraries/Storage/NativeAsyncStorage.js new file mode 100644 index 00000000000..a1c4e51ff9b --- /dev/null +++ b/Libraries/Storage/NativeAsyncStorage.js @@ -0,0 +1,44 @@ +/** + * 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: () => {||}; + +multiGet: ( + keys: Array, + callback: ( + errors: ?Array<{|message: string|}>, + kvPairs: ?Array>, + ) => void, + ) => void; + +multiSet: ( + kvPairs: Array>, + callback: (errors: ?Array<{|message: string|}>) => void, + ) => void; + +multiMerge: ( + kvPairs: Array>, + callback: (errors: ?Array<{|message: string|}>) => void, + ) => void; + +multiRemove: ( + keys: Array, + callback: (errors: ?Array<{|message: string|}>) => void, + ) => void; + +clear: (callback: (error: {|message: string|}) => void) => void; + +getAllKeys: ( + callback: (error: ?{|message: string|}, allKeys: ?Array) => void, + ) => void; +} + +export default TurboModuleRegistry.get('AsyncSQLiteDBStorage') || + TurboModuleRegistry.get('AsyncLocalStorage');