@react-native-firebase/database 26.3.3 → 27.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/RNFBDatabase.podspec +10 -2
- package/android/build.gradle +7 -0
- package/android/src/main/java/io/invertase/firebase/database/DatabaseAbortable.java +22 -0
- package/android/src/main/java/io/invertase/firebase/database/DatabaseQueryHandle.java +24 -0
- package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseKeepSyncedRegistry.java +106 -0
- package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseListenerRegistry.kt +133 -0
- package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseQueryRegistry.kt +76 -0
- package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseTransactionRegistry.kt +67 -0
- package/android/src/main/java/io/invertase/firebase/database/UniversalFirebaseDatabaseOnDisconnectModule.java +102 -9
- package/android/src/reactnative/java/io/invertase/firebase/database/NativeRNFBTurboDatabaseOnDisconnect.java +6 -11
- package/android/src/reactnative/java/io/invertase/firebase/database/NativeRNFBTurboDatabaseQuery.java +111 -24
- package/android/src/reactnative/java/io/invertase/firebase/database/NativeRNFBTurboDatabaseTransaction.java +12 -25
- package/android/src/reactnative/java/io/invertase/firebase/database/ReactNativeFirebaseDatabaseQuery.java +30 -33
- package/android/src/reactnative/java/io/invertase/firebase/database/ReactNativeFirebaseDatabaseTransactionHandler.java +3 -3
- package/android/src/reactnative/java/io/invertase/firebase/database/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboDatabaseQuerySpec.java +4 -0
- package/android/src/reactnative/java/io/invertase/firebase/database/generated/jni/RNFBDatabaseTurboModules-generated.cpp +6 -0
- package/android/src/reactnative/java/io/invertase/firebase/database/generated/jni/react/renderer/components/RNFBDatabaseTurboModules/RNFBDatabaseTurboModulesJSI.h +12 -0
- package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseKeepSyncedRegistryTest.java +174 -0
- package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseListenerRegistryTest.java +191 -0
- package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseQueryRegistryTest.java +489 -0
- package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseTransactionRegistryTest.java +199 -0
- package/android/src/test/java/io/invertase/firebase/database/UniversalFirebaseDatabaseOnDisconnectCancelErrorTest.java +137 -0
- package/dist/module/DatabaseQuery.js +52 -1
- package/dist/module/DatabaseQuery.js.map +1 -1
- package/dist/module/DatabaseSyncTree.js +1 -1
- package/dist/module/DatabaseSyncTree.js.map +1 -1
- package/dist/module/index.js +1 -2
- package/dist/module/index.js.map +1 -1
- package/dist/module/modular/query.js +1 -1
- package/dist/module/modular/query.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/module/web/RNFBDatabaseModule.js +7 -0
- package/dist/module/web/RNFBDatabaseModule.js.map +1 -1
- package/dist/typescript/lib/DatabaseQuery.d.ts +25 -0
- package/dist/typescript/lib/DatabaseQuery.d.ts.map +1 -1
- package/dist/typescript/lib/index.d.ts +1 -1
- package/dist/typescript/lib/types/internal.d.ts +2 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/dist/typescript/lib/web/RNFBDatabaseModule.d.ts.map +1 -1
- package/ios/RNFBDatabase/RNFBDatabaseListenerRegistry.h +37 -0
- package/ios/RNFBDatabase/RNFBDatabaseListenerRegistry.m +91 -0
- package/ios/RNFBDatabase/RNFBDatabaseListenerRegistryStorage.swift +81 -0
- package/ios/RNFBDatabase/RNFBDatabaseNullSentinelDecoder.h +36 -0
- package/ios/RNFBDatabase/RNFBDatabaseNullSentinelDecoder.m +48 -0
- package/ios/RNFBDatabase/RNFBDatabaseOnDisconnectHelper.m +29 -26
- package/ios/RNFBDatabase/RNFBDatabaseQuery.h +3 -2
- package/ios/RNFBDatabase/RNFBDatabaseQuery.m +14 -13
- package/ios/RNFBDatabase/RNFBDatabaseQueryHelper.h +7 -0
- package/ios/RNFBDatabase/RNFBDatabaseQueryHelper.m +44 -21
- package/ios/RNFBDatabase/RNFBDatabaseQueryModule.mm +14 -0
- package/ios/RNFBDatabase/RNFBDatabaseQueryRegistry.h +37 -0
- package/ios/RNFBDatabase/RNFBDatabaseQueryRegistry.m +79 -0
- package/ios/RNFBDatabase/RNFBDatabaseQueryRegistryStorage.swift +104 -0
- package/ios/RNFBDatabase/RNFBDatabaseReferenceHelper.m +14 -12
- package/ios/RNFBDatabase/RNFBDatabaseTransactionHelper.m +3 -1
- package/ios/RNFBDatabase.xcodeproj/project.pbxproj +12 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseListenerRegistryStorageTests.swift +86 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseListenerRegistryTests.m +90 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseNullSentinelDecodeTests.m +118 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseQueryRegistryStorageTests.swift +181 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseQueryRegistryTests.m +390 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseUnitTests.xcodeproj/project.pbxproj +303 -0
- package/ios/RNFBDatabaseUnitTests/RNFBDatabaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBDatabaseUnitTests.xcscheme +69 -0
- package/ios/generated/RNFBDatabaseTurboModules/RNFBDatabaseTurboModules-generated.mm +7 -0
- package/ios/generated/RNFBDatabaseTurboModules/RNFBDatabaseTurboModules.h +6 -0
- package/ios/generated/RNFBDatabaseTurboModulesJSI.h +12 -0
- package/lib/DatabaseQuery.ts +56 -0
- package/lib/DatabaseSyncTree.ts +1 -1
- package/lib/index.ts +1 -1
- package/lib/modular/query.ts +1 -1
- package/lib/types/internal.ts +2 -0
- package/lib/version.ts +1 -1
- package/lib/web/RNFBDatabaseModule.ts +13 -0
- package/package.json +5 -4
- package/specs/NativeRNFBTurboDatabaseQuery.ts +1 -0
|
@@ -76,6 +76,20 @@ RCT_EXPORT_MODULE(NativeRNFBTurboDatabaseQuery);
|
|
|
76
76
|
reject:reject];
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
- (void)get:(NSString *)app
|
|
80
|
+
dbURL:(NSString *)dbURL
|
|
81
|
+
path:(NSString *)path
|
|
82
|
+
modifiers:(NSArray *)modifiers
|
|
83
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
84
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
85
|
+
[RNFBDatabaseQueryHelper get:app
|
|
86
|
+
dbURL:dbURL
|
|
87
|
+
path:path
|
|
88
|
+
modifiers:modifiers
|
|
89
|
+
resolve:resolve
|
|
90
|
+
reject:reject];
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
- (void)on:(NSString *)app dbURL:(NSString *)dbURL props:(NSDictionary *)props {
|
|
80
94
|
[RNFBDatabaseQueryHelper on:app dbURL:dbURL props:props];
|
|
81
95
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <Foundation/Foundation.h>
|
|
19
|
+
|
|
20
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Cached query map. Unique `put`; callers `take`, `takeIfIdle`, or `removeAll` then
|
|
24
|
+
* `removeAllEventListeners` outside the HandleMap lock. Stored values are expected to respond to
|
|
25
|
+
* `removeAllEventListeners` and `hasListeners`.
|
|
26
|
+
*/
|
|
27
|
+
@interface RNFBDatabaseQueryRegistry : NSObject
|
|
28
|
+
|
|
29
|
+
- (BOOL)put:(id)key value:(id)value error:(NSError *_Nullable *_Nullable)error;
|
|
30
|
+
- (nullable id)get:(id)key;
|
|
31
|
+
- (nullable id)take:(id)key;
|
|
32
|
+
- (nullable id)takeIfIdle:(id)key;
|
|
33
|
+
- (void)removeAll;
|
|
34
|
+
|
|
35
|
+
@end
|
|
36
|
+
|
|
37
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import "RNFBDatabaseQueryRegistry.h"
|
|
19
|
+
|
|
20
|
+
#if __has_include("RNFBHandleMap.h")
|
|
21
|
+
#import "RNFBHandleMap.h"
|
|
22
|
+
#else
|
|
23
|
+
#import "RNFBApp/RNFBHandleMap.h"
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
#if __has_include(<RNFBDatabase/RNFBDatabase-Swift.h>)
|
|
27
|
+
#import <RNFBDatabase/RNFBDatabase-Swift.h>
|
|
28
|
+
#elif __has_include("RNFBDatabase-Swift.h")
|
|
29
|
+
#import "RNFBDatabase-Swift.h"
|
|
30
|
+
#elif __has_include("RNFBHandleMapStorage-Swift.inc")
|
|
31
|
+
#import "RNFBHandleMapStorage-Swift.inc"
|
|
32
|
+
#else
|
|
33
|
+
#error "RNFBDatabaseQueryRegistryStorage Swift interface not found"
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
@interface RNFBDatabaseQueryRegistry ()
|
|
37
|
+
@property(nonatomic, strong) RNFBDatabaseQueryRegistryStorage *storage;
|
|
38
|
+
@end
|
|
39
|
+
|
|
40
|
+
@implementation RNFBDatabaseQueryRegistry
|
|
41
|
+
|
|
42
|
+
- (instancetype)init {
|
|
43
|
+
self = [super init];
|
|
44
|
+
if (self) {
|
|
45
|
+
_storage = [[RNFBDatabaseQueryRegistryStorage alloc] init];
|
|
46
|
+
}
|
|
47
|
+
return self;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
- (BOOL)put:(id)key value:(id)value error:(NSError **)error {
|
|
51
|
+
if ([self.storage putIfAbsent:key value:value]) {
|
|
52
|
+
return YES;
|
|
53
|
+
}
|
|
54
|
+
if (error != nil) {
|
|
55
|
+
NSString *message = [NSString stringWithFormat:@"Handle id already registered: %@", key];
|
|
56
|
+
*error = [NSError errorWithDomain:RNFBHandleMapErrorDomain
|
|
57
|
+
code:RNFBHandleMapErrorCollision
|
|
58
|
+
userInfo:@{NSLocalizedDescriptionKey : message}];
|
|
59
|
+
}
|
|
60
|
+
return NO;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- (id)get:(id)key {
|
|
64
|
+
return [self.storage get:key];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (id)take:(id)key {
|
|
68
|
+
return [self.storage take:key];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
- (id)takeIfIdle:(id)key {
|
|
72
|
+
return [self.storage takeIfIdle:key];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
- (void)removeAll {
|
|
76
|
+
[self.storage removeAll];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import Foundation
|
|
18
|
+
|
|
19
|
+
#if canImport(RNFBApp)
|
|
20
|
+
import RNFBApp
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
/// Cached query map storage. Composes `RNFBHandleMapStorage`.
|
|
24
|
+
/// Unique `put` collision errors stay on the ObjC façade.
|
|
25
|
+
/// `takeIfIdle` reads `hasListeners` outside the HandleMap lock (avoids nesting).
|
|
26
|
+
@objc(RNFBDatabaseQueryRegistryStorage)
|
|
27
|
+
public final class RNFBDatabaseQueryRegistryStorage: NSObject {
|
|
28
|
+
private static let hasListenersSelector = Selector(("hasListeners"))
|
|
29
|
+
private static let removeAllEventListenersSelector = Selector(("removeAllEventListeners"))
|
|
30
|
+
|
|
31
|
+
private let storage = RNFBHandleMapStorage()
|
|
32
|
+
|
|
33
|
+
private func removeAllEventListeners(_ query: AnyObject?) {
|
|
34
|
+
guard let query = query, query.responds(to: Self.removeAllEventListenersSelector) else {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
_ = query.perform(Self.removeAllEventListenersSelector)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Calls `-hasListeners` via IMP (avoids Swift protocol cast requiring formal conformance).
|
|
41
|
+
/// Returns `nil` when the selector is absent.
|
|
42
|
+
private func queryHasListeners(_ query: AnyObject) -> Bool? {
|
|
43
|
+
typealias HasListenersIMP = @convention(c) (AnyObject, Selector) -> Bool
|
|
44
|
+
let sel = Self.hasListenersSelector
|
|
45
|
+
guard query.responds(to: sel), let method = class_getInstanceMethod(type(of: query), sel)
|
|
46
|
+
else {
|
|
47
|
+
return nil
|
|
48
|
+
}
|
|
49
|
+
let fn = unsafeBitCast(method_getImplementation(method), to: HasListenersIMP.self)
|
|
50
|
+
return fn(query, sel)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// First-wins store. Used by façade `put`.
|
|
54
|
+
@objc(putIfAbsent:value:)
|
|
55
|
+
public func putIfAbsent(_ key: AnyObject, value: AnyObject) -> Bool {
|
|
56
|
+
storage.putIfAbsent(key, value: value)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc(get:)
|
|
60
|
+
public func get(_ key: AnyObject) -> AnyObject? {
|
|
61
|
+
storage.get(key)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc(take:)
|
|
65
|
+
public func take(_ key: AnyObject) -> AnyObject? {
|
|
66
|
+
storage.take(key)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Idle-only take. `hasListeners` is read outside the HandleMap lock; identity-take then
|
|
70
|
+
/// put-back (or orphan cleanup) if listeners appear after the outside check.
|
|
71
|
+
@objc(takeIfIdle:)
|
|
72
|
+
public func takeIfIdle(_ key: AnyObject) -> AnyObject? {
|
|
73
|
+
guard let query = storage.get(key) else {
|
|
74
|
+
return nil
|
|
75
|
+
}
|
|
76
|
+
guard let hasListeners = queryHasListeners(query) else {
|
|
77
|
+
return nil
|
|
78
|
+
}
|
|
79
|
+
if hasListeners {
|
|
80
|
+
return nil
|
|
81
|
+
}
|
|
82
|
+
guard let taken = storage.takeIf(key, when: { $0 === query }) else {
|
|
83
|
+
return nil
|
|
84
|
+
}
|
|
85
|
+
if queryHasListeners(taken) == true {
|
|
86
|
+
// Prefer put-back so an active query stays registered. If a concurrent put claimed the
|
|
87
|
+
// slot, putIfAbsent fails and this taken query would be an orphan with listeners — clear
|
|
88
|
+
// them so SDK callbacks are not left attached outside the registry.
|
|
89
|
+
if !storage.putIfAbsent(key, value: taken) {
|
|
90
|
+
removeAllEventListeners(taken)
|
|
91
|
+
}
|
|
92
|
+
return nil
|
|
93
|
+
}
|
|
94
|
+
return taken
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Snapshot then clear; `removeAllEventListeners` on each value that responds.
|
|
98
|
+
@objc
|
|
99
|
+
public func removeAll() {
|
|
100
|
+
for query in storage.takeAll() {
|
|
101
|
+
removeAllEventListeners(query)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
#import "RNFBApp/RCTConvert+FIRApp.h"
|
|
26
26
|
#import "RNFBDatabaseCommon.h"
|
|
27
|
+
#import "RNFBDatabaseNullSentinelDecoder.h"
|
|
27
28
|
#import "RNFBDatabaseReferenceHelper.h"
|
|
28
29
|
|
|
29
30
|
@implementation RNFBDatabaseReferenceHelper
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
FIRDatabaseReference *firDatabaseReference =
|
|
40
41
|
[RNFBDatabaseCommon getReferenceForDatabase:firDatabase path:path];
|
|
41
42
|
|
|
42
|
-
[firDatabaseReference setValue:[props
|
|
43
|
+
[firDatabaseReference setValue:[RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props]
|
|
43
44
|
withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
|
|
44
45
|
if (error != nil) {
|
|
45
46
|
[RNFBDatabaseCommon promiseRejectDatabaseException:reject error:error];
|
|
@@ -60,14 +61,15 @@
|
|
|
60
61
|
FIRDatabaseReference *firDatabaseReference =
|
|
61
62
|
[RNFBDatabaseCommon getReferenceForDatabase:firDatabase path:path];
|
|
62
63
|
|
|
63
|
-
[firDatabaseReference
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
[firDatabaseReference
|
|
65
|
+
updateChildValues:[RNFBDatabaseNullSentinelDecoder decodedValuesFromProps:props]
|
|
66
|
+
withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
|
|
67
|
+
if (error != nil) {
|
|
68
|
+
[RNFBDatabaseCommon promiseRejectDatabaseException:reject error:error];
|
|
69
|
+
} else {
|
|
70
|
+
resolve([NSNull null]);
|
|
71
|
+
}
|
|
72
|
+
}];
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
+ (void)setWithPriority:(NSString *)app
|
|
@@ -81,8 +83,8 @@
|
|
|
81
83
|
FIRDatabaseReference *firDatabaseReference =
|
|
82
84
|
[RNFBDatabaseCommon getReferenceForDatabase:firDatabase path:path];
|
|
83
85
|
|
|
84
|
-
[firDatabaseReference setValue:[props
|
|
85
|
-
andPriority:[props
|
|
86
|
+
[firDatabaseReference setValue:[RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props]
|
|
87
|
+
andPriority:[RNFBDatabaseNullSentinelDecoder decodedPriorityFromProps:props]
|
|
86
88
|
withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
|
|
87
89
|
if (error != nil) {
|
|
88
90
|
[RNFBDatabaseCommon promiseRejectDatabaseException:reject error:error];
|
|
@@ -123,7 +125,7 @@
|
|
|
123
125
|
FIRDatabaseReference *firDatabaseReference =
|
|
124
126
|
[RNFBDatabaseCommon getReferenceForDatabase:firDatabase path:path];
|
|
125
127
|
|
|
126
|
-
[firDatabaseReference setPriority:[props
|
|
128
|
+
[firDatabaseReference setPriority:[RNFBDatabaseNullSentinelDecoder decodedPriorityFromProps:props]
|
|
127
129
|
withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
|
|
128
130
|
if (error != nil) {
|
|
129
131
|
[RNFBDatabaseCommon promiseRejectDatabaseException:reject error:error];
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
#import "RNFBApp/RCTConvert+FIRApp.h"
|
|
26
26
|
#import "RNFBApp/RNFBSharedUtils.h"
|
|
27
27
|
#import "RNFBDatabaseCommon.h"
|
|
28
|
+
#import "RNFBDatabaseNullSentinelDecoder.h"
|
|
28
29
|
#import "RNFBDatabaseTransactionHelper.h"
|
|
29
30
|
#import "RNFBRCTEventEmitter.h"
|
|
30
31
|
|
|
@@ -163,7 +164,8 @@ static NSString *const RNFB_DATABASE_TRANSACTION_EVENT = @"database_transaction_
|
|
|
163
164
|
if (abort) {
|
|
164
165
|
[transactionState setValue:@true forKey:@"abort"];
|
|
165
166
|
} else {
|
|
166
|
-
id newValue =
|
|
167
|
+
id newValue =
|
|
168
|
+
[RNFBDatabaseNullSentinelDecoder decodedTransactionValue:[updates valueForKey:@"value"]];
|
|
167
169
|
[transactionState setValue:newValue forKey:@"value"];
|
|
168
170
|
}
|
|
169
171
|
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
8B9DD3C622A11F4F00A16945 /* RNFBDatabaseReferenceModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B9DD3C522A11F4F00A16945 /* RNFBDatabaseReferenceModule.mm */; };
|
|
15
15
|
8B9DD3C922A1258B00A16945 /* RNFBDatabaseQueryModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B9DD3C822A1258B00A16945 /* RNFBDatabaseQueryModule.mm */; };
|
|
16
16
|
8B9DD3CE22A43D1400A16945 /* RNFBDatabaseTransactionModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B9DD3CD22A43D1400A16945 /* RNFBDatabaseTransactionModule.mm */; };
|
|
17
|
+
RNFBDB000000000000000001 /* RNFBDatabaseListenerRegistryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBDB000000000000000002 /* RNFBDatabaseListenerRegistryStorage.swift */; };
|
|
18
|
+
RNFBDB000000000000000003 /* RNFBDatabaseQueryRegistryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBDB000000000000000004 /* RNFBDatabaseQueryRegistryStorage.swift */; };
|
|
17
19
|
/* End PBXBuildFile section */
|
|
18
20
|
|
|
19
21
|
/* Begin PBXCopyFilesBuildPhase section */
|
|
@@ -44,6 +46,8 @@
|
|
|
44
46
|
8B9DD3CA22A1259F00A16945 /* RNFBDatabaseQueryModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFBDatabaseQueryModule.h; sourceTree = "<group>"; };
|
|
45
47
|
8B9DD3CC22A43D0300A16945 /* RNFBDatabaseTransactionModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFBDatabaseTransactionModule.h; sourceTree = "<group>"; };
|
|
46
48
|
8B9DD3CD22A43D1400A16945 /* RNFBDatabaseTransactionModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNFBDatabaseTransactionModule.mm; sourceTree = "<group>"; };
|
|
49
|
+
RNFBDB000000000000000002 /* RNFBDatabaseListenerRegistryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBDatabaseListenerRegistryStorage.swift; path = RNFBDatabase/RNFBDatabaseListenerRegistryStorage.swift; sourceTree = SOURCE_ROOT; };
|
|
50
|
+
RNFBDB000000000000000004 /* RNFBDatabaseQueryRegistryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBDatabaseQueryRegistryStorage.swift; path = RNFBDatabase/RNFBDatabaseQueryRegistryStorage.swift; sourceTree = SOURCE_ROOT; };
|
|
47
51
|
/* End PBXFileReference section */
|
|
48
52
|
|
|
49
53
|
/* Begin PBXFrameworksBuildPhase section */
|
|
@@ -70,6 +74,8 @@
|
|
|
70
74
|
children = (
|
|
71
75
|
2744B98421F45429004F8E3F /* RNFBDatabaseModule.h */,
|
|
72
76
|
2744B98521F45429004F8E3F /* RNFBDatabaseModule.mm */,
|
|
77
|
+
RNFBDB000000000000000002 /* RNFBDatabaseListenerRegistryStorage.swift */,
|
|
78
|
+
RNFBDB000000000000000004 /* RNFBDatabaseQueryRegistryStorage.swift */,
|
|
73
79
|
8B9DD3B822A03C6700A16945 /* RNFBDatabaseQuery.h */,
|
|
74
80
|
8B9DD3B922A03C7900A16945 /* RNFBDatabaseQuery.m */,
|
|
75
81
|
8B9DD3BC22A05CEB00A16945 /* RNFBDatabaseOnDisconnectModule.mm */,
|
|
@@ -153,6 +159,8 @@
|
|
|
153
159
|
isa = PBXSourcesBuildPhase;
|
|
154
160
|
buildActionMask = 2147483647;
|
|
155
161
|
files = (
|
|
162
|
+
RNFBDB000000000000000001 /* RNFBDatabaseListenerRegistryStorage.swift in Sources */,
|
|
163
|
+
RNFBDB000000000000000003 /* RNFBDatabaseQueryRegistryStorage.swift in Sources */,
|
|
156
164
|
8B9DD3BD22A05CEB00A16945 /* RNFBDatabaseOnDisconnectModule.mm in Sources */,
|
|
157
165
|
8B9DD3C922A1258B00A16945 /* RNFBDatabaseQueryModule.mm in Sources */,
|
|
158
166
|
8B9DD3CE22A43D1400A16945 /* RNFBDatabaseTransactionModule.mm in Sources */,
|
|
@@ -185,6 +193,7 @@
|
|
|
185
193
|
CODE_SIGN_STYLE = Automatic;
|
|
186
194
|
COPY_PHASE_STRIP = NO;
|
|
187
195
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
196
|
+
DEFINES_MODULE = YES;
|
|
188
197
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
|
189
198
|
GCC_DYNAMIC_NO_PIC = NO;
|
|
190
199
|
GCC_OPTIMIZATION_LEVEL = 0;
|
|
@@ -201,6 +210,7 @@
|
|
|
201
210
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
202
211
|
SDKROOT = iphoneos;
|
|
203
212
|
SKIP_INSTALL = YES;
|
|
213
|
+
SWIFT_VERSION = 5.10;
|
|
204
214
|
TARGETED_DEVICE_FAMILY = "1,2";
|
|
205
215
|
};
|
|
206
216
|
name = Debug;
|
|
@@ -224,6 +234,7 @@
|
|
|
224
234
|
CODE_SIGN_STYLE = Automatic;
|
|
225
235
|
COPY_PHASE_STRIP = NO;
|
|
226
236
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
237
|
+
DEFINES_MODULE = YES;
|
|
227
238
|
ENABLE_NS_ASSERTIONS = NO;
|
|
228
239
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
|
229
240
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
@@ -235,6 +246,7 @@
|
|
|
235
246
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
236
247
|
SDKROOT = iphoneos;
|
|
237
248
|
SKIP_INSTALL = YES;
|
|
249
|
+
SWIFT_VERSION = 5.10;
|
|
238
250
|
TARGETED_DEVICE_FAMILY = "1,2";
|
|
239
251
|
VALIDATE_PRODUCT = YES;
|
|
240
252
|
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import XCTest
|
|
18
|
+
|
|
19
|
+
final class RNFBDatabaseListenerRegistryStorageTests: XCTestCase {
|
|
20
|
+
private var storage: RNFBDatabaseListenerRegistryStorage!
|
|
21
|
+
|
|
22
|
+
override func setUp() {
|
|
23
|
+
super.setUp()
|
|
24
|
+
storage = RNFBDatabaseListenerRegistryStorage()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func testPutIfAbsent_storesWhenFree_andIncrementsOccupancy() {
|
|
28
|
+
let handle = 7 as NSNumber
|
|
29
|
+
XCTAssertTrue(storage.putIfAbsent("k" as NSString, value: handle))
|
|
30
|
+
XCTAssertTrue(storage.get("k" as NSString) === handle)
|
|
31
|
+
XCTAssertTrue(storage.hasListeners)
|
|
32
|
+
XCTAssertTrue(storage.hasEventListener("k" as NSString))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func testPutIfAbsent_collision_keepsExistingWithoutOccupancyBump() {
|
|
36
|
+
let first = 1 as NSNumber
|
|
37
|
+
let second = 2 as NSNumber
|
|
38
|
+
XCTAssertTrue(storage.putIfAbsent("k" as NSString, value: first))
|
|
39
|
+
XCTAssertFalse(storage.putIfAbsent("k" as NSString, value: second))
|
|
40
|
+
XCTAssertTrue(storage.get("k" as NSString) === first)
|
|
41
|
+
XCTAssertTrue(storage.hasListeners)
|
|
42
|
+
XCTAssertEqual(storage.takeAll().count, 1)
|
|
43
|
+
XCTAssertFalse(storage.hasListeners)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func testGet_whenFree_isNil() {
|
|
47
|
+
XCTAssertNil(storage.get("missing" as NSString))
|
|
48
|
+
XCTAssertFalse(storage.hasEventListener("missing" as NSString))
|
|
49
|
+
XCTAssertFalse(storage.hasListeners)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func testTake_removesAndDecrementsOccupancy() {
|
|
53
|
+
let handle = 7 as NSNumber
|
|
54
|
+
XCTAssertTrue(storage.putIfAbsent("k" as NSString, value: handle))
|
|
55
|
+
XCTAssertTrue(storage.take("k" as NSString) === handle)
|
|
56
|
+
XCTAssertNil(storage.get("k" as NSString))
|
|
57
|
+
XCTAssertFalse(storage.hasListeners)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func testTake_whenFree_isNoOp() {
|
|
61
|
+
XCTAssertNil(storage.take("missing" as NSString))
|
|
62
|
+
XCTAssertFalse(storage.hasListeners)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func testTakeAll_snapshotAndLeavesEmpty() {
|
|
66
|
+
XCTAssertTrue(storage.putIfAbsent("a" as NSString, value: 1 as NSNumber))
|
|
67
|
+
XCTAssertTrue(storage.putIfAbsent("b" as NSString, value: 2 as NSNumber))
|
|
68
|
+
let remaining = storage.takeAll()
|
|
69
|
+
XCTAssertEqual(remaining.count, 2)
|
|
70
|
+
XCTAssertFalse(storage.hasListeners)
|
|
71
|
+
XCTAssertNil(storage.get("a" as NSString))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
func testTakeAll_empty_isNoOp() {
|
|
75
|
+
XCTAssertEqual(storage.takeAll().count, 0)
|
|
76
|
+
XCTAssertFalse(storage.hasListeners)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
func testPut_afterTake_allowsReuse() {
|
|
80
|
+
XCTAssertTrue(storage.putIfAbsent("k" as NSString, value: 1 as NSNumber))
|
|
81
|
+
XCTAssertEqual(storage.take("k" as NSString) as? NSNumber, 1)
|
|
82
|
+
XCTAssertTrue(storage.putIfAbsent("k" as NSString, value: 2 as NSNumber))
|
|
83
|
+
XCTAssertEqual(storage.get("k" as NSString) as? NSNumber, 2)
|
|
84
|
+
XCTAssertTrue(storage.hasListeners)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <XCTest/XCTest.h>
|
|
19
|
+
|
|
20
|
+
#import "RNFBDatabaseListenerRegistry.h"
|
|
21
|
+
#import "RNFBHandleMap.h"
|
|
22
|
+
|
|
23
|
+
@interface RNFBDatabaseListenerRegistryTests : XCTestCase
|
|
24
|
+
@property(nonatomic, strong) RNFBDatabaseListenerRegistry *registry;
|
|
25
|
+
@end
|
|
26
|
+
|
|
27
|
+
@implementation RNFBDatabaseListenerRegistryTests
|
|
28
|
+
|
|
29
|
+
- (void)setUp {
|
|
30
|
+
[super setUp];
|
|
31
|
+
self.registry = [[RNFBDatabaseListenerRegistry alloc] init];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (void)testPutGetTake_happyPath {
|
|
35
|
+
NSNumber *handle = @7;
|
|
36
|
+
NSError *error = nil;
|
|
37
|
+
XCTAssertTrue([self.registry put:@"k" value:handle error:&error]);
|
|
38
|
+
XCTAssertNil(error);
|
|
39
|
+
XCTAssertEqual(handle, [self.registry get:@"k"]);
|
|
40
|
+
XCTAssertEqual(handle, [self.registry take:@"k"]);
|
|
41
|
+
XCTAssertNil([self.registry get:@"k"]);
|
|
42
|
+
XCTAssertFalse([self.registry hasListeners]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (void)testPut_occupiedId_returnsCollision {
|
|
46
|
+
XCTAssertTrue([self.registry put:@"k" value:@1 error:nil]);
|
|
47
|
+
NSError *error = nil;
|
|
48
|
+
XCTAssertFalse([self.registry put:@"k" value:@2 error:&error]);
|
|
49
|
+
XCTAssertEqual(error.code, RNFBHandleMapErrorCollision);
|
|
50
|
+
XCTAssertEqualObjects([self.registry get:@"k"], @1);
|
|
51
|
+
XCTAssertTrue([self.registry hasListeners]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)testPut_occupiedId_nilErrorOut_returnsNo {
|
|
55
|
+
XCTAssertTrue([self.registry put:@"k" value:@1 error:nil]);
|
|
56
|
+
XCTAssertFalse([self.registry put:@"k" value:@2 error:nil]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (void)testTake_missingKey_isNoOp {
|
|
60
|
+
XCTAssertNil([self.registry take:@"missing"]);
|
|
61
|
+
XCTAssertFalse([self.registry hasListeners]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
- (void)testTakeAll_snapshotAndLeavesEmpty {
|
|
65
|
+
XCTAssertTrue([self.registry put:@"a" value:@1 error:nil]);
|
|
66
|
+
XCTAssertTrue([self.registry put:@"b" value:@2 error:nil]);
|
|
67
|
+
NSArray *remaining = [self.registry takeAll];
|
|
68
|
+
XCTAssertEqual(remaining.count, 2);
|
|
69
|
+
XCTAssertFalse([self.registry hasListeners]);
|
|
70
|
+
XCTAssertNil([self.registry get:@"a"]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
- (void)testTakeAll_empty_isNoOp {
|
|
74
|
+
XCTAssertEqual([self.registry takeAll].count, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (void)testHasEventListener {
|
|
78
|
+
XCTAssertFalse([self.registry hasEventListener:@"k"]);
|
|
79
|
+
XCTAssertTrue([self.registry put:@"k" value:@1 error:nil]);
|
|
80
|
+
XCTAssertTrue([self.registry hasEventListener:@"k"]);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
- (void)testPut_afterTake_allowsReuse {
|
|
84
|
+
XCTAssertTrue([self.registry put:@"k" value:@1 error:nil]);
|
|
85
|
+
XCTAssertEqualObjects([self.registry take:@"k"], @1);
|
|
86
|
+
XCTAssertTrue([self.registry put:@"k" value:@2 error:nil]);
|
|
87
|
+
XCTAssertEqualObjects([self.registry get:@"k"], @2);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import <XCTest/XCTest.h>
|
|
19
|
+
|
|
20
|
+
#import "RNFBDatabaseNullSentinelDecoder.h"
|
|
21
|
+
|
|
22
|
+
@interface RNFBDatabaseNullSentinelDecodeTests : XCTestCase
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
@implementation RNFBDatabaseNullSentinelDecodeTests
|
|
26
|
+
|
|
27
|
+
- (NSDictionary *)nullSentinel {
|
|
28
|
+
return @{@"__rnfbNull" : @YES};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
- (NSDictionary *)serverTimestamp {
|
|
32
|
+
return @{@".sv" : @"timestamp"};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#pragma mark - Reference helper seams
|
|
36
|
+
|
|
37
|
+
- (void)testReferenceSet_topLevelNullSentinel_becomesNSNull {
|
|
38
|
+
NSDictionary *props = @{@"value" : [self nullSentinel]};
|
|
39
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props],
|
|
40
|
+
[NSNull null]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
- (void)testReferenceUpdate_childNullSentinel_becomesNSNull {
|
|
44
|
+
NSDictionary *props = @{@"values" : @{@"a" : [self nullSentinel], @"b" : @1}};
|
|
45
|
+
NSDictionary *decoded = [RNFBDatabaseNullSentinelDecoder decodedValuesFromProps:props];
|
|
46
|
+
XCTAssertEqualObjects(decoded[@"a"], [NSNull null]);
|
|
47
|
+
XCTAssertEqualObjects(decoded[@"b"], @1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
- (void)testReferenceSetWithPriority_valueAndPrioritySentinels_becomeNSNull {
|
|
51
|
+
NSDictionary *props = @{
|
|
52
|
+
@"value" : [self nullSentinel],
|
|
53
|
+
@"priority" : [self nullSentinel],
|
|
54
|
+
};
|
|
55
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props],
|
|
56
|
+
[NSNull null]);
|
|
57
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedPriorityFromProps:props],
|
|
58
|
+
[NSNull null]);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)testReferenceSetPriority_sentinel_becomesNSNull {
|
|
62
|
+
NSDictionary *props = @{@"priority" : [self nullSentinel]};
|
|
63
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedPriorityFromProps:props],
|
|
64
|
+
[NSNull null]);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (void)testReference_serverTimestampDictionary_unchanged {
|
|
68
|
+
NSDictionary *props = @{@"value" : [self serverTimestamp]};
|
|
69
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props],
|
|
70
|
+
[self serverTimestamp]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#pragma mark - OnDisconnect helper seams
|
|
74
|
+
|
|
75
|
+
- (void)testOnDisconnectSet_topLevelNullSentinel_becomesNSNull {
|
|
76
|
+
NSDictionary *props = @{@"value" : [self nullSentinel]};
|
|
77
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props],
|
|
78
|
+
[NSNull null]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
- (void)testOnDisconnectSetWithPriority_valueAndPrioritySentinels_becomeNSNull {
|
|
82
|
+
NSDictionary *props = @{
|
|
83
|
+
@"value" : [self nullSentinel],
|
|
84
|
+
@"priority" : [self nullSentinel],
|
|
85
|
+
};
|
|
86
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props],
|
|
87
|
+
[NSNull null]);
|
|
88
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedPriorityFromProps:props],
|
|
89
|
+
[NSNull null]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
- (void)testOnDisconnectUpdate_childNullSentinel_becomesNSNull {
|
|
93
|
+
NSDictionary *props = @{@"values" : @{@"gone" : [self nullSentinel]}};
|
|
94
|
+
NSDictionary *decoded = [RNFBDatabaseNullSentinelDecoder decodedValuesFromProps:props];
|
|
95
|
+
XCTAssertEqualObjects(decoded[@"gone"], [NSNull null]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (void)testOnDisconnect_serverTimestampDictionary_unchanged {
|
|
99
|
+
NSDictionary *props = @{@"value" : [self serverTimestamp]};
|
|
100
|
+
XCTAssertEqualObjects([RNFBDatabaseNullSentinelDecoder decodedValueFromProps:props],
|
|
101
|
+
[self serverTimestamp]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
#pragma mark - Transaction helper seam
|
|
105
|
+
|
|
106
|
+
- (void)testTransactionTryCommit_valueSentinel_becomesNSNull {
|
|
107
|
+
id decoded = [RNFBDatabaseNullSentinelDecoder decodedTransactionValue:[self nullSentinel]];
|
|
108
|
+
XCTAssertEqualObjects(decoded, [NSNull null]);
|
|
109
|
+
XCTAssertFalse([decoded isKindOfClass:[NSDictionary class]]);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
- (void)testTransactionTryCommit_serverTimestamp_unchanged {
|
|
113
|
+
XCTAssertEqualObjects(
|
|
114
|
+
[RNFBDatabaseNullSentinelDecoder decodedTransactionValue:[self serverTimestamp]],
|
|
115
|
+
[self serverTimestamp]);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@end
|