瀏覽代碼

update cartfile

marinofaggiana 5 年之前
父節點
當前提交
abc25468ad
共有 60 個文件被更改,包括 1188 次插入388 次删除
  1. 1 1
      Cartfile
  2. 3 4
      Cartfile.resolved
  3. 4 4
      Carthage/Checkouts/CocoaLumberjack/.travis.yml
  4. 15 1
      Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md
  5. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.h
  6. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.m
  7. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.h
  8. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h
  9. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAssertMacros.h
  10. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.h
  11. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.m
  12. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog+LOGV.h
  13. 2 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.h
  14. 2 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.m
  15. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLogMacros.h
  16. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.h
  17. 2 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.h
  18. 3 3
      Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.m
  19. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h
  20. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h
  21. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h
  22. 2 2
      Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec
  23. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Info.plist
  24. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift-Info.plist
  25. 4 4
      Carthage/Checkouts/realm-cocoa/.jenkins.yml
  26. 1 1
      Carthage/Checkouts/realm-cocoa/.travis.yml
  27. 68 0
      Carthage/Checkouts/realm-cocoa/CHANGELOG.md
  28. 3 3
      Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability
  29. 155 31
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm
  30. 0 173
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift
  31. 41 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js
  32. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list
  33. 1 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/CMakeLists.txt
  34. 86 40
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.cpp
  35. 5 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.hpp
  36. 3 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object.hpp
  37. 6 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_accessor.hpp
  38. 85 3
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.cpp
  39. 2 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.hpp
  40. 25 4
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/property.hpp
  41. 15 8
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.cpp
  42. 6 3
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.hpp
  43. 1 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/schema.cpp
  44. 9 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.cpp
  45. 10 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.hpp
  46. 98 3
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp
  47. 9 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/results.cpp
  48. 116 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/schema.cpp
  49. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/transaction_log_parsing.cpp
  50. 4 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMProperty.mm
  51. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMRealm+Sync.mm
  52. 3 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h
  53. 15 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm
  54. 3 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSession.mm
  55. 162 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.h
  56. 177 13
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.mm
  57. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist
  58. 3 2
      Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m
  59. 13 50
      Carthage/Checkouts/realm-cocoa/build.sh
  60. 4 4
      Carthage/Checkouts/realm-cocoa/dependencies.list

+ 1 - 1
Cartfile

@@ -8,7 +8,7 @@ github "ealeksandrov/EAIntroView" == 2.12.0
 github "calimarkus/JDStatusBarNotification" == 1.6.0
 github "ChangbaDevs/KTVHTTPCache" == 2.0.0
 github "jdg/MBProgressHUD" == 1.1.0
-github "realm/realm-cocoa" == 3.14.1
+github "realm/realm-cocoa" == 3.15.0
 github "SVGKit/SVGKit" == 2.1.0
 github "WeTransfer/WeScan" == 1.1.0
 github "malcommac/SwiftRichString" == 3.0.0

+ 3 - 4
Cartfile.resolved

@@ -1,6 +1,6 @@
 github "AFNetworking/AFNetworking" "3.2.1"
 github "ChangbaDevs/KTVHTTPCache" "2.0.0"
-github "CocoaLumberjack/CocoaLumberjack" "3.5.2"
+github "CocoaLumberjack/CocoaLumberjack" "3.5.3"
 github "MortimerGoro/MGSwipeTableCell" "1.6.8"
 github "SVGKit/SVGKit" "2.1.0"
 github "WeTransfer/WeScan" "v1.1.0"
@@ -13,9 +13,8 @@ github "jdg/MBProgressHUD" "1.1.0"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
 github "malcommac/SwiftRichString" "3.0.0"
 github "marinofaggiana/FastScroll" "81967c2309d29bc2c330d422da612160a30bade8"
-github "marmelroy/Zip" "1.1.0"
-github "realm/realm-cocoa" "v3.14.1"
+github "realm/realm-cocoa" "v3.15.0"
 github "sgr-ksmt/PDFGenerator" "2.1"
 github "tilltue/TLPhotoPicker" "1.8.5"
 github "weichsel/ZIPFoundation" "0.9.9"
-github "yannickl/QRCodeReader.swift" "10.0.0"
+github "yannickl/QRCodeReader.swift" "10.1.0"

+ 4 - 4
Carthage/Checkouts/CocoaLumberjack/.travis.yml

@@ -1,6 +1,6 @@
 
 language: objective-c
-osx_image: xcode10
+osx_image: xcode10.2
 
 branches:
     only:
@@ -15,8 +15,8 @@ env:
 before_install:
     - env
     - locale
-    - gem install cocoapods --pre --no-rdoc --no-ri --no-document --quiet
-    - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
+    - gem install cocoapods --prerelease --no-document --quiet
+    - gem install xcpretty --no-document --quiet
     - pod --version
     - xcpretty --version
     - xcodebuild -version
@@ -51,7 +51,7 @@ script:
     - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'macOSSwiftIntegration' -configuration Release -sdk macosx | xcpretty -c
     - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'iOSFrameworkIntegration' -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Release | xcpretty -c
     - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'tvOSSwiftIntegration' -destination 'platform=tvOS Simulator,name=Apple TV 4K' -configuration Release -sdk appletvsimulator | xcpretty -c
-    - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'watchOSSwiftIntegration' -configuration Release -sdk watchsimulator -destination 'platform=iOS Simulator,name=iPhone XS Max,OS=12.0' | xcpretty -c
+    - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'watchOSSwiftIntegration' -configuration Release -sdk watchsimulator -destination 'platform=iOS Simulator,name=iPhone XS Max,OS=12.2' | xcpretty -c
 
     - echo "Run the tests"
     - xcodebuild test -skip-testing:'iOS Tests/DDFileLoggerPerformanceTests' -project Tests/Tests.xcodeproj -scheme 'iOS Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=9.3' GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c

+ 15 - 1
Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md

@@ -1,4 +1,18 @@
-## [3.5.2 - Xcode 10.1 on 15th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.2)
+## [3.5.3 - Xcode 10.2 on Apr 24th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.3)
+
+### Public
+- Additional compatibility with Swift 5 (backwards compatible with Swift 4) (#1043)
+- Fix warning building with Xcode 10.2 (#1059)
+- Set Xcode 10.2 and Swift 5.0 as a default (#1064)
+- Fix format string crash (#1066)
+
+### Internal
+- Fix warning about syntax (#1054) (#1065)
+- Remove banned APIs (#1056) (#1057)
+- Add CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER & fix warnings (#1059)
+- Use LLONG_MAX instead of LONG_LONG_MAX (#1062)
+
+## [3.5.2 - Xcode 10.1 on Mar 15th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.2)
 
 ### Public
 - Fix reusing of log files after rolling (#1042)

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.h

@@ -13,7 +13,7 @@
 //   to endorse or promote products derived from this software without specific
 //   prior written permission of Deusty, LLC.
 
-#import "DDASLLogger.h"
+#import <CocoaLumberjack/DDASLLogger.h>
 
 @protocol DDLogger;
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.m

@@ -70,7 +70,7 @@ static DDLogLevel _captureLevel = DDLogLevelVerbose;
 #if !TARGET_OS_IPHONE || (defined(TARGET_SIMULATOR) && TARGET_SIMULATOR)
     int processId = [[NSProcessInfo processInfo] processIdentifier];
     char pid[16];
-    sprintf(pid, "%d", processId);
+    snprintf(pid, sizeof(pid), "%d", processId);
     asl_set_query(query, ASL_KEY_PID, pid, ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_NUMERIC);
 #endif
 }

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 // Custom key set on messages sent to ASL
 extern const char* const kDDASLKeyDDLog;

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This class provides an abstract implementation of a database logger.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAssertMacros.h

@@ -20,7 +20,7 @@
         if (!(condition)) {                                                           \
             NSString *description = [NSString stringWithFormat:frmt, ## __VA_ARGS__]; \
             DDLogError(@"%@", description);                                           \
-            NSAssert(NO, description);                                                \
+            NSAssert(NO, @"%@", description);                                         \
         }
 #define DDAssertCondition(condition) DDAssert(condition, @"Condition not satisfied: %s", #condition)
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 NS_ASSUME_NONNULL_BEGIN
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.m

@@ -826,7 +826,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota   = 20 * 1024 * 1024; // 20
     });
     #endif
 
-    static NSTimeInterval const kDDMaxTimerDelay = LONG_LONG_MAX / NSEC_PER_SEC;
+    static NSTimeInterval const kDDMaxTimerDelay = LLONG_MAX / NSEC_PER_SEC;
     int64_t delay = (int64_t)(MIN([logFileRollingDate timeIntervalSinceNow], kDDMaxTimerDelay) * (NSTimeInterval) NSEC_PER_SEC);
     dispatch_time_t fireTime = dispatch_time(DISPATCH_TIME_NOW, delay);
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog+LOGV.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * The constant/variable/method responsible for controlling the current log level.

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.h

@@ -20,10 +20,10 @@
     #define DD_LEGACY_MACROS 1
 #endif
 // DD_LEGACY_MACROS is checked in the file itself
-#import "DDLegacyMacros.h"
+#import <CocoaLumberjack/DDLegacyMacros.h>
 
 // Names of loggers.
-#import "DDLoggerNames.h"
+#import <CocoaLumberjack/DDLoggerNames.h>
 
 #if OS_OBJECT_USE_OBJC
     #define DISPATCH_QUEUE_REFERENCE_TYPE strong

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.m

@@ -43,7 +43,7 @@
 // We maintain the NS prefix on the macros to be explicit about the fact that we're using NSLog.
 
 #ifndef DD_DEBUG
-    #define DD_DEBUG NO
+    #define DD_DEBUG 0
 #endif
 
 #define NSLogDebug(frmt, ...) do{ if(DD_DEBUG) NSLog((frmt), ##__VA_ARGS__); } while(0)
@@ -619,7 +619,7 @@ static NSUInteger _numProcessors;
 
         NSUInteger bufferSize = numClasses;
 
-        classes = numClasses ? (Class *)malloc(sizeof(Class) * bufferSize) : NULL;
+        classes = numClasses ? (Class *)calloc(bufferSize, sizeof(Class)) : NULL;
         if (classes == NULL) {
             return @[]; //no memory or classes?
         }

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLogMacros.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * The constant/variable/method responsible for controlling the current log level.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This class provides a logger for the Apple os_log facility.

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 #define LOG_CONTEXT_ALL INT_MAX
 
@@ -31,7 +31,7 @@
     static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
 #elif defined(DD_CLI) || !__has_include(<AppKit/NSColor.h>)
     // OS X CLI
-    #import "CLIColor.h"
+    #import <CocoaLumberjack/CLIColor.h>
     typedef CLIColor DDColor;
     static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
 #else

+ 3 - 3
Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.m

@@ -844,7 +844,7 @@ static DDTTYLogger *sharedInstance;
             _appLen = [_appName lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
         }
 
-        _app = (char *)malloc(_appLen + 1);
+        _app = (char *)calloc(_appLen + 1, sizeof(char));
 
         if (_app == NULL) {
             return nil;
@@ -862,7 +862,7 @@ static DDTTYLogger *sharedInstance;
         _processID = [NSString stringWithFormat:@"%i", (int)getpid()];
 
         _pidLen = [_processID lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-        _pid = (char *)malloc(_pidLen + 1);
+        _pid = (char *)calloc(_pidLen + 1, sizeof(char));
 
         if (_pid == NULL) {
             free(_app);
@@ -1211,7 +1211,7 @@ static DDTTYLogger *sharedInstance;
         const BOOL useStack = msgLen < (1024 * 4);
 
         char msgStack[useStack ? (msgLen + 1) : 1]; // Analyzer doesn't like zero-size array, hence the 1
-        char *msg = useStack ? msgStack : (char *)malloc(msgLen + 1);
+        char *msg = useStack ? msgStack : (char *)calloc(msgLen + 1, sizeof(char));
 
         if (msg == NULL) {
             return;

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This class provides a log formatter that filters log statements from a logging context not on the whitelist.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  *  Log formatter mode

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This formatter can be used to chain different formatters together.

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec

@@ -2,7 +2,7 @@
 Pod::Spec.new do |s|
 
   s.name     = 'CocoaLumberjack'
-  s.version  = '3.5.2'
+  s.version  = '3.5.3'
   s.license  = 'BSD'
   s.summary  = 'A fast & simple, yet powerful & flexible logging framework for Mac and iOS.'
   s.homepage = 'https://github.com/CocoaLumberjack/CocoaLumberjack'
@@ -23,7 +23,7 @@ Pod::Spec.new do |s|
   s.osx.deployment_target     = '10.10'
   s.watchos.deployment_target = '3.0'
   s.tvos.deployment_target    = '9.0'
-  s.swift_version = '4.2'
+  s.swift_version = '5.0'
 
   s.default_subspecs = 'Core'
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Info.plist

@@ -17,7 +17,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.5.2</string>
+	<string>3.5.3</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift-Info.plist

@@ -17,7 +17,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.5.2</string>
+	<string>3.5.3</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 4 - 4
Carthage/Checkouts/realm-cocoa/.jenkins.yml

@@ -7,7 +7,7 @@ xcode_version:
   - 9.4
   - 10.0
   - 10.1
-  - 10.2
+  - 10.2.1
 target:
   - osx
   - docs
@@ -56,8 +56,8 @@ configuration:
 # | 10.1  | Debug        | X   |      |            |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
 # | 10.1  | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    |                |                   |                      |                       |                       |                        |             |
 # | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 10.2  | Debug        | X   |      |            | X           | X         | X         | X       |               |               |                   |           | X    |                |                   |                      |                       |                       |                        |             |
-# | 10.2  | Release      | X   | X    | X          | X           | X         | X         | X       | X             | X             | X                 | X         | X    | X              | X                 |                      |                       | X                     |                        | X           |
+# | 10.2.1| Debug        | X   |      |            | X           | X         | X         | X       |               |               |                   |           | X    |                |                   |                      |                       |                       |                        |             |
+# | 10.2.1| Release      | X   | X    | X          | X           | X         | X         | X       | X             | X             | X                 | X         | X    | X              | X                 |                      |                       | X                     |                        | X           |
 # +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 exclude:
@@ -94,7 +94,7 @@ exclude:
   - xcode_version: 10.1
     target: ios-static
     configuration: Debug
-  - xcode_version: 10.2
+  - xcode_version: 10.2.1
     target: ios-static
     configuration: Debug
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/.travis.yml

@@ -1,5 +1,5 @@
 language: objective-c
-osx_image: xcode9.3
+osx_image: xcode10.2
 branches:
   only: master
 script: placeholder # workaround for https://github.com/travis-ci/travis-ci/issues/4681

+ 68 - 0
Carthage/Checkouts/realm-cocoa/CHANGELOG.md

@@ -1,3 +1,70 @@
+3.15.0 Release notes (2019-05-06)
+=============================================================
+
+The minimum version of Realm Object Server has been increased to 3.21.0 and
+attempting to connect to older versions will produce protocol mismatch errors.
+Realm Cloud has already been upgraded to this version, and users using that do
+not need to worry about this.
+
+### Enhancements
+
+* Add `createdAt`, `updatedAt`, `expiresAt` and `timeToLive` properties to
+  `RLMSyncSubscription`/`SyncSubscription`. These properties will be `nil` for
+  subscriptions created with older versions of Realm, but will be automatically
+  populated for newly-created subscriptions.
+* Add support for transient subscriptions by setting the `timeToLive` when
+  creating the subscription. The next time a subscription is created or updated
+  after that time has elapsed the subscription will be automatically removed.
+* Add support for updating existing subscriptions with a new query or limit.
+  This is done by passing `update: true` (in swift) or setting
+  `options.overwriteExisting = YES` (in obj-c) when creating the subscription,
+  which will make it update the existing subscription with the same name rather
+  than failing if one already exists with that name.
+* Add an option to include the objects from
+  `RLMLinkingObjects`/`LinkingObjects` properties in sync subscriptions,
+  similarly to how `RLMArray`/`List` automatically pull in the contained
+  objects.
+* Improve query performance for chains of OR conditions (or an IN condition) on
+  an unindexed integer or string property.
+  ([Core PR #2888](https://github.com/realm/realm-core/pull/2888) and
+  [Core PR #3250](https://github.com/realm/realm-core/pull/3250)).
+* Improve query performance for equality conditions on indexed integer properties.
+  ([Core PR #3272](https://github.com/realm/realm-core/pull/3272)).
+* Adjust the file allocation algorithm to reduce fragmentation caused by large
+  numbers of small blocks.
+* Improve file allocator logic to reduce fragmentation and improve commit
+  performance after many writes. ([Core PR #3278](https://github.com/realm/realm-core/pull/3278)).
+
+### Fixed
+
+* Making a query that compares two integer properties could cause a
+  segmentation fault on x86 (i.e. macOS only).
+  ([Core PR #3253](https://github.com/realm/realm-core/pull/3256)).
+* The `downloadable_bytes` parameter passed to sync progress callbacks reported
+  a value which correlated to the amount of data left to download, but not
+  actually the number of bytes which would be downloaded.
+
+### Compatibility
+
+* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
+* Realm Object Server: 3.21.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.1.
+
+3.14.2 Release notes (2019-04-25)
+=============================================================
+
+### Enhancements
+
+* Updating `RLMSyncManager.customRequestHeaders` will immediately update all
+  currently active sync session with the new headers rather than requiring
+  manually closing the Realm and reopening it.
+
+### Compatibility
+
+* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
+* Realm Object Server: 3.11.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.1.
+
 3.14.1 Release notes (2019-04-04)
 =============================================================
 
@@ -11,6 +78,7 @@
 
 * File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
 * Realm Object Server: 3.11.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.
 
 3.14.0 Release notes (2019-03-27)
 =============================================================

+ 3 - 3
Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability

@@ -1,8 +1,8 @@
-xcodeVersions = ['9.2', '9.3', '9.4', '10.0', '10.1', '10.2']
+xcodeVersions = ['9.2', '9.3', '9.4', '10.0', '10.1', '10.2.1']
 platforms = ['osx', 'ios', 'watchos', 'tvos']
 platformNames = ['osx': 'macOS', 'ios': 'iOS', 'watchos': 'watchOS', 'tvos': 'tvOS']
-carthageXcodeVersion = '10.2'
-docsSwiftVersion = '5.0'
+carthageXcodeVersion = '10.2.1'
+docsSwiftVersion = '5.0.1'
 
 def installationTest(platform, test, language) {
   return {

+ 155 - 31
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm

@@ -20,11 +20,14 @@
 #import "RLMTestUtils.h"
 #import "RLMSyncSessionRefreshHandle+ObjectServerTests.h"
 #import "RLMSyncUser+ObjectServerTests.h"
-#import "RLMSyncUtil_Private.h"
+
 #import "RLMRealm+Sync.h"
 #import "RLMRealmConfiguration_Private.h"
 #import "RLMRealmUtil.hpp"
 #import "RLMRealm_Dynamic.h"
+#import "RLMRealm_Private.hpp"
+#import "RLMSyncUtil_Private.h"
+#import "shared_realm.hpp"
 
 #pragma mark - Test objects
 
@@ -1446,7 +1449,6 @@
     __block NSInteger callCount = 0;
     __block NSUInteger transferred = 0;
     __block NSUInteger transferrable = 0;
-    __block BOOL hasBeenFulfilled = NO;
     // Open the Realm
     RLMRealm *realm = [self openRealmForURL:url user:user];
 
@@ -1454,24 +1456,21 @@
     RLMSyncSession *session = [user sessionForURL:url];
     XCTAssertNotNil(session);
     XCTestExpectation *ex = [self expectationWithDescription:@"streaming-upload-expectation"];
-    RLMProgressNotificationToken *token = [session addProgressNotificationForDirection:RLMSyncProgressDirectionUpload
-                                                                                  mode:RLMSyncProgressModeReportIndefinitely
-                                                                                 block:^(NSUInteger xfr, NSUInteger xfb) {
-                                                                                     // Make sure the values are
-                                                                                     // increasing, and update our
-                                                                                     // stored copies.
-                                                                                     XCTAssert(xfr >= transferred);
-                                                                                     XCTAssert(xfb >= transferrable);
-                                                                                     transferred = xfr;
-                                                                                     transferrable = xfb;
-                                                                                     callCount++;
-                                                                                     if (transferred > 0
-                                                                                         && transferred >= transferrable
-                                                                                         && !hasBeenFulfilled) {
-                                                                                         [ex fulfill];
-                                                                                         hasBeenFulfilled = YES;
-                                                                                     }
-                                                                                 }];
+    auto token = [session addProgressNotificationForDirection:RLMSyncProgressDirectionUpload
+                                                         mode:RLMSyncProgressModeReportIndefinitely
+                                                        block:^(NSUInteger xfr, NSUInteger xfb) {
+                                                            // Make sure the values are
+                                                            // increasing, and update our
+                                                            // stored copies.
+                                                            XCTAssert(xfr >= transferred);
+                                                            XCTAssert(xfb >= transferrable);
+                                                            transferred = xfr;
+                                                            transferrable = xfb;
+                                                            callCount++;
+                                                            if (transferred > 0 && transferred >= transferrable && transferrable > 1000000 * NUMBER_OF_BIG_OBJECTS) {
+                                                                [ex fulfill];
+                                                            }
+                                                        }];
     // Upload lots of data
     [realm beginWriteTransaction];
     for (NSInteger i=0; i<NUMBER_OF_BIG_OBJECTS; i++) {
@@ -1555,21 +1554,16 @@
         return;
     }
 
-    // Wait for the child process to upload everything.
-    RLMRunChildAndWait();
-
     XCTestExpectation *ex = [self expectationWithDescription:@"download-realm"];
     RLMRealmConfiguration *c = [user configurationWithURL:url fullSynchronization:true];
     XCTAssertFalse([[NSFileManager defaultManager] fileExistsAtPath:c.pathOnDisk isDirectory:nil]);
     RLMRealm *realm = [RLMRealm realmWithConfiguration:c error:nil];
     CHECK_COUNT(0, HugeSyncObject, realm);
-    [RLMRealm asyncOpenWithConfiguration:c
-                           callbackQueue:dispatch_get_main_queue()
-                                callback:^(RLMRealm * _Nullable realm, NSError * _Nullable error) {
-        XCTAssertNil(error);
-        CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
-        [ex fulfill];
-    }];
+    [realm.syncSession suspend];
+
+    // Wait for the child process to upload everything.
+    RLMRunChildAndWait();
+
     auto fileSize = ^NSUInteger(NSString *path) {
         NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
         return [(NSNumber *)attributes[NSFileSize] unsignedLongLongValue];
@@ -1577,11 +1571,22 @@
     NSUInteger sizeBefore = fileSize(c.pathOnDisk);
     XCTAssertGreaterThan(sizeBefore, 0U);
     XCTAssertNotNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
+
+    [RLMRealm asyncOpenWithConfiguration:c
+                           callbackQueue:dispatch_get_main_queue()
+                                callback:^(RLMRealm * _Nullable realm, NSError * _Nullable error) {
+        XCTAssertNil(error);
+        CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
+        [ex fulfill];
+    }];
+    [realm.syncSession resume];
     [self waitForExpectationsWithTimeout:2.0 handler:nil];
 
     XCTAssertGreaterThan(fileSize(c.pathOnDisk), sizeBefore);
     XCTAssertNotNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
     CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
+
+    (void)[realm configuration];
 }
 
 - (void)testDownloadCancelsOnAuthError {
@@ -1645,7 +1650,9 @@
 
     auto finalSize = [[fileManager attributesOfItemAtPath:path error:nil][NSFileSize] unsignedLongLongValue];
     XCTAssertLessThan(finalSize, initialSize);
-    XCTAssertLessThan(finalSize, 10000U);
+    // Immediately after compaction the file is two pages (8192 bytes), but it
+    // grows to three pages shortly later due to sync performing a write
+    XCTAssertLessThanOrEqual(finalSize, 12288U);
 }
 
 #pragma mark - Offline Client Reset
@@ -1889,6 +1896,11 @@
     [self waitForKeyPath:@"state" object:fetched value:@(RLMSyncSubscriptionStateInvalidated)];
     XCTAssertEqual(0U, realm.subscriptions.count);
     XCTAssertEqual(RLMSyncSubscriptionStateInvalidated, original.state);
+
+    // XCTKVOExpecatation retains the object and releases it sometime later on
+    // a background thread, which causes issues if the realm is closed after
+    // we reset the global state
+    realm->_realm->close();
 }
 
 - (void)testUnsubscribeUsingFetchedSubscriptionObservingFetched {
@@ -1902,6 +1914,11 @@
     [self waitForKeyPath:@"state" object:fetched value:@(RLMSyncSubscriptionStateInvalidated)];
     XCTAssertEqual(0U, realm.subscriptions.count);
     XCTAssertEqual(RLMSyncSubscriptionStateInvalidated, original.state);
+
+    // XCTKVOExpecatation retains the object and releases it sometime later on
+    // a background thread, which causes issues if the realm is closed after
+    // we reset the global state
+    realm->_realm->close();
 }
 
 - (void)testUnsubscribeUsingFetchedSubscriptionObservingOriginal {
@@ -1944,6 +1961,7 @@
 - (void)testSortAndFilterSubscriptions {
     RLMRealm *realm = [self partialRealmWithName:_cmd];
 
+    NSDate *now = NSDate.date;
     [self waitForKeyPath:@"state" object:[[PartialSyncObjectA allObjectsInRealm:realm] subscribeWithName:@"query 1"]
                    value:@(RLMSyncSubscriptionStateComplete)];
     [self waitForKeyPath:@"state" object:[[PartialSyncObjectA allObjectsInRealm:realm] subscribeWithName:@"query 2"]
@@ -1961,11 +1979,47 @@
     XCTAssertEqual(3U, ([subscriptions objectsWhere:@"status = %@", @(RLMSyncSubscriptionStateComplete)].count));
     XCTAssertEqual(1U, ([subscriptions objectsWhere:@"status = %@", @(RLMSyncSubscriptionStateError)].count));
 
+    XCTAssertEqual(4U, ([subscriptions objectsWhere:@"createdAt >= %@", now]).count);
+    XCTAssertEqual(0U, ([subscriptions objectsWhere:@"createdAt < %@", now]).count);
+    XCTAssertEqual(4U, [subscriptions objectsWhere:@"expiresAt = nil"].count);
+    XCTAssertEqual(4U, [subscriptions objectsWhere:@"timeToLive = nil"].count);
+
     XCTAssertThrows([subscriptions sortedResultsUsingKeyPath:@"name" ascending:NO]);
     XCTAssertThrows([subscriptions sortedResultsUsingDescriptors:@[]]);
     XCTAssertThrows([subscriptions distinctResultsUsingKeyPaths:@[@"name"]]);
 }
 
+- (void)testIncludeLinkingObjectsErrorHandling {
+    RLMRealm *realm = [self partialRealmWithName:_cmd];
+
+    RLMResults *objects = [PersonObject allObjectsInRealm:realm];
+    RLMSyncSubscriptionOptions *opt = [RLMSyncSubscriptionOptions new];
+
+    opt.includeLinkingObjectProperties = @[@"nonexistent"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'nonexistent': property 'PersonObject.nonexistent' does not exist.");
+
+    opt.includeLinkingObjectProperties = @[@"name"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'name': property 'PersonObject.name' is of unsupported type 'string'.");
+
+    opt.includeLinkingObjectProperties = @[@"children.name"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'children.name': property 'PersonObject.name' is of unsupported type 'string'.");
+
+    opt.includeLinkingObjectProperties = @[@"children"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'children': key path must end in a LinkingObjects property and 'PersonObject.children' is of type 'array'.");
+
+    opt.includeLinkingObjectProperties = @[@"children."];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'children.': missing property name.");
+
+    opt.includeLinkingObjectProperties = @[@""];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path '': missing property name.");
+}
+
 #pragma mark - Certificate pinning
 
 - (void)attemptLoginWithUsername:(NSString *)userName callback:(void (^)(RLMSyncUser *, NSError *))callback {
@@ -2136,4 +2190,74 @@ static NSURL *certificateURL(NSString *filename) {
     [self verifyOpenFails:[user configurationWithURL:[NSURL URLWithString:@"realms://localhost:9443/~/default"]]];
 }
 
+#pragma mark - Custom request headers
+
+- (void)testLoginFailsWithoutCustomHeader {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"register user"];
+    [RLMSyncUser logInWithCredentials:[RLMSyncTestCase basicCredentialsWithName:NSStringFromSelector(_cmd)
+                                                                       register:YES]
+                        authServerURL:[NSURL URLWithString:@"http://127.0.0.1:9081"]
+                         onCompletion:^(RLMSyncUser *user, NSError *error) {
+                             XCTAssertNil(user);
+                             XCTAssertNotNil(error);
+                             XCTAssertEqualObjects(@400, error.userInfo[@"statusCode"]);
+                             [expectation fulfill];
+                         }];
+    [self waitForExpectationsWithTimeout:4.0 handler:nil];
+}
+
+- (void)testLoginUsesCustomHeader {
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Allow-Connection": @"true"};
+    RLMSyncUser *user = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:NSStringFromSelector(_cmd)
+                                                                                       register:YES]
+                                               server:[NSURL URLWithString:@"http://127.0.0.1:9081"]];
+    XCTAssertNotNil(user);
+}
+
+- (void)testModifyCustomHeadersAfterOpeningRealm {
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Allow-Connection": @"true"};
+    RLMSyncUser *user = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:NSStringFromSelector(_cmd)
+                                                                                       register:YES]
+                                               server:[NSURL URLWithString:@"http://127.0.0.1:9081"]];
+    XCTAssertNotNil(user);
+
+    RLMSyncManager.sharedManager.customRequestHeaders = nil;
+
+    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"realm://127.0.0.1:9081/~/%@", NSStringFromSelector(_cmd)]];
+    auto c = [user configurationWithURL:url fullSynchronization:true];
+
+    // Should initially fail to connect due to the missing header
+    XCTestExpectation *ex1 = [self expectationWithDescription:@"connection failure"];
+    RLMSyncManager.sharedManager.errorHandler = ^(NSError *error, RLMSyncSession *) {
+        XCTAssertNotNil(error);
+        XCTAssertEqualObjects(@400, [error.userInfo[@"underlying_error"] userInfo][@"statusCode"]);
+        [ex1 fulfill];
+    };
+    RLMRealm *realm = [RLMRealm realmWithConfiguration:c error:nil];
+    RLMSyncSession *syncSession = realm.syncSession;
+    [self waitForExpectationsWithTimeout:4.0 handler:nil];
+    XCTAssertEqual(syncSession.connectionState, RLMSyncConnectionStateDisconnected);
+
+    // Should successfully connect once the header is set
+    RLMSyncManager.sharedManager.errorHandler = nil;
+    auto ex2 = [[XCTKVOExpectation alloc] initWithKeyPath:@"connectionState"
+                                                   object:syncSession
+                                            expectedValue:@(RLMSyncConnectionStateConnected)];
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Allow-Connection": @"true"};
+    [self waitForExpectations:@[ex2] timeout:4.0];
+
+    // Should disconnect and fail to reconnect when the wrong header is set
+    XCTestExpectation *ex3 = [self expectationWithDescription:@"reconnection failure"];
+    RLMSyncManager.sharedManager.errorHandler = ^(NSError *error, RLMSyncSession *) {
+        XCTAssertNotNil(error);
+        XCTAssertEqualObjects(@400, [error.userInfo[@"underlying_error"] userInfo][@"statusCode"]);
+        [ex3 fulfill];
+    };
+    auto ex4 = [[XCTKVOExpectation alloc] initWithKeyPath:@"connectionState"
+                                                   object:syncSession
+                                            expectedValue:@(RLMSyncConnectionStateDisconnected)];
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Other-Header": @"true"};
+    [self waitForExpectations:@[ex3, ex4] timeout:4.0];
+}
+
 @end

+ 0 - 173
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift

@@ -98,7 +98,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         }
     }
 
-#if swift(>=3.2)
     func testConnectionState() {
         let user = try! synchronouslyLogInUser(for: basicCredentials(register: true), server: authURL)
         let realm = try! synchronouslyOpenRealm(url: realmURL, user: user)
@@ -124,7 +123,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         wait(forState: .connecting)
         wait(forState: .connected)
     }
-#endif // Swift >= 3.2
 
     // MARK: - Client reset
 
@@ -430,177 +428,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         }
     }
 
-    // MARK: - Partial sync
-
-    func populateTestRealm(_ username: String) {
-        autoreleasepool {
-            let credentials = SyncCredentials.usernamePassword(username: username, password: "a", register: true)
-            let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-            let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-            try! realm.write {
-                realm.add(SwiftPartialSyncObjectA(number: 0, string: "realm"))
-                realm.add(SwiftPartialSyncObjectA(number: 1, string: ""))
-                realm.add(SwiftPartialSyncObjectA(number: 2, string: ""))
-                realm.add(SwiftPartialSyncObjectA(number: 3, string: ""))
-                realm.add(SwiftPartialSyncObjectA(number: 4, string: "realm"))
-                realm.add(SwiftPartialSyncObjectA(number: 5, string: "sync"))
-                realm.add(SwiftPartialSyncObjectA(number: 6, string: "partial"))
-                realm.add(SwiftPartialSyncObjectA(number: 7, string: "partial"))
-                realm.add(SwiftPartialSyncObjectA(number: 8, string: "partial"))
-                realm.add(SwiftPartialSyncObjectA(number: 9, string: "partial"))
-                realm.add(SwiftPartialSyncObjectB(number: 0, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 1, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 2, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 3, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 4, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 5, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 6, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 7, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 8, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 9, firstString: "", secondString: ""))
-            }
-            waitForUploads(for: realm)
-        }
-    }
-
-    func testPartialSync() {
-        populateTestRealm(#function)
-
-        let credentials = SyncCredentials.usernamePassword(username: #function, password: "a")
-        let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-        let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-        let results = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5")
-        let subscription = results.subscribe(named: "query")
-        XCTAssertEqual(subscription.state, .creating)
-        waitForState(subscription, .complete)
-
-        // Verify that we got what we're looking for
-        XCTAssertEqual(results.count, 4)
-        for object in results {
-            XCTAssertGreaterThan(object.number, 5)
-            XCTAssertEqual(object.string, "partial")
-        }
-
-        // And that we didn't get anything else.
-        XCTAssertEqual(realm.objects(SwiftPartialSyncObjectA.self).count, results.count)
-        XCTAssertTrue(realm.objects(SwiftPartialSyncObjectB.self).isEmpty)
-
-        // Re-subscribing to an existing named query may not report the query's state immediately,
-        // but it should report it eventually.
-        let subscription2 = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5").subscribe(named: "query")
-        waitForState(subscription2, .complete)
-
-        // Creating a subscription with the same name but different query should raise an error.
-        let subscription3 = realm.objects(SwiftPartialSyncObjectA.self).filter("number < 5").subscribe(named: "query")
-        waitForError(subscription3)
-
-        // Unsubscribing should move the subscription to the invalidated state.
-        subscription.unsubscribe()
-        waitForState(subscription, .invalidated)
-    }
-
-    func testPartialSyncLimit() {
-        populateTestRealm(#function)
-
-        let credentials = SyncCredentials.usernamePassword(username: #function, password: "a")
-        let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-        let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-        let results = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5")
-        waitForState(results.subscribe(named: "query", limit: 1), .complete)
-        XCTAssertEqual(results.count, 1)
-        XCTAssertEqual(realm.objects(SwiftPartialSyncObjectA.self).count, 1)
-        if let object = results.first {
-            XCTAssertGreaterThan(object.number, 5)
-            XCTAssertEqual(object.string, "partial")
-        }
-
-        let results2 = realm.objects(SwiftPartialSyncObjectA.self).sorted(byKeyPath: "number", ascending: false)
-        waitForState(results2.subscribe(named: "query2", limit: 2), .complete)
-        XCTAssertEqual(results2.count, 3)
-        XCTAssertEqual(realm.objects(SwiftPartialSyncObjectA.self).count, 3)
-        for object in results2 {
-            XCTAssertTrue(object.number == 6 || object.number >= 8,
-                          "\(object.number) == 6 || \(object.number) >= 8")
-            XCTAssertEqual(object.string, "partial")
-        }
-    }
-
-    func testPartialSyncSubscriptions() {
-        let credentials = SyncCredentials.usernamePassword(username: #function, password: "a", register: true)
-        let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-        let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-        XCTAssertEqual(realm.subscriptions().count, 0)
-        XCTAssertNil(realm.subscription(named: "query"))
-
-        let subscription = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5").subscribe(named: "query")
-        XCTAssertEqual(realm.subscriptions().count, 0)
-        XCTAssertNil(realm.subscription(named: "query"))
-        waitForState(subscription, .complete)
-
-        XCTAssertEqual(realm.subscriptions().count, 1)
-        let sub2 = realm.subscriptions().first!
-        XCTAssertEqual(sub2.name, "query")
-        XCTAssertEqual(sub2.state, .complete)
-        let sub3 = realm.subscription(named: "query")!
-        XCTAssertEqual(sub3.name, "query")
-        XCTAssertEqual(sub3.state, .complete)
-        for sub in realm.subscriptions() {
-            XCTAssertEqual(sub.name, "query")
-            XCTAssertEqual(sub.state, .complete)
-        }
-
-        XCTAssertNil(realm.subscription(named: "not query"))
-    }
-
-// Partial sync subscriptions are only available in Swift 3.2 and newer.
-#if swift(>=3.2)
-    func waitForState<T>(_ subscription: SyncSubscription<T>, _ desiredState: SyncSubscriptionState) {
-        let ex = expectation(description: "Waiting for state \(desiredState)")
-        let token = subscription.observe(\.state, options: .initial) { state in
-            if state == desiredState {
-                ex.fulfill()
-            }
-        }
-        waitForExpectations(timeout: 20.0)
-        token.invalidate()
-    }
-
-    func waitForError<T>(_ subscription: SyncSubscription<T>) {
-        let ex = expectation(description: "Waiting for error state")
-        let token = subscription.observe(\.state, options: .initial) { state in
-            if case .error(_) = state {
-                ex.fulfill()
-            }
-        }
-        waitForExpectations(timeout: 20.0)
-        token.invalidate()
-    }
-#else
-    func waitForState<T>(_ subscription: SyncSubscription<T>, _ desiredState: SyncSubscriptionState) {
-        for _ in 0..<20 {
-            if subscription.state == desiredState {
-                return
-            }
-            RunLoop.current.run(until: Date().addingTimeInterval(1.0))
-        }
-        XCTFail("waitForState(\(subscription), \(desiredState)) timed out")
-    }
-
-    func waitForError<T>(_ subscription: SyncSubscription<T>) {
-        for _ in 0..<20 {
-            if case .error(_) = subscription.state {
-                return
-            }
-            RunLoop.current.run(until: Date().addingTimeInterval(1.0))
-        }
-        XCTFail("waitForError(\(subscription)) timed out")
-    }
-#endif // Swift >= 3.2
-
     // MARK: - Certificate Pinning
 
     func testSecureConnectionToLocalhostWithDefaultSecurity() {

+ 41 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js

@@ -1,5 +1,7 @@
 const ROS = require('realm-object-server');
 const fs = require('fs');
+const http = require('http');
+const httpProxy = require('http-proxy');
 const os = require('os');
 const path = require('path');
 
@@ -46,6 +48,44 @@ class PasswordEmailHandler {
     }
 }
 
+// A simple proxy server that runs in front of ROS and validates custom headers
+class HeaderValidationProxy {
+    constructor(listenPort, targetPort) {
+        this.proxy = httpProxy.createProxyServer({target: `http://127.0.0.1:${targetPort}`, ws: true});
+        this.proxy.on('error', e => {
+            console.log('proxy error', e);
+        });
+        this.server = http.createServer((req, res) => {
+            if (this.validate(req)) {
+                this.proxy.web(req, res);
+            }
+            else {
+                res.writeHead(400);
+                res.end('Missing X-Allow-Connection header');
+            }
+        });
+        this.server.on('upgrade', (req, socket, head) => {
+            if (this.validate(req)) {
+                this.proxy.ws(req, socket, head);
+            }
+            else {
+                socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
+            }
+        });
+        this.server.listen(listenPort);
+    }
+
+    stop() {
+        this.server.close();
+        this.proxy.close();
+    }
+
+    validate(req) {
+        return !!req.headers['x-allow-connection'];
+    }
+}
+
+
 const server = new ROS.BasicServer();
 server.start({
     // The desired logging threshold. Can be one of: all, trace, debug, detail, info, warn, error, fatal, off)
@@ -78,3 +118,4 @@ server.start({
 }).catch(err => {
     console.error(`Error starting Realm Object Server: ${err.message}`)
 });
+new HeaderValidationProxy(9081, 9080);

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list

@@ -1,4 +1,4 @@
-REALM_CORE_VERSION=5.12.7
-REALM_SYNC_VERSION=3.14.12
+REALM_CORE_VERSION=5.19.1
+REALM_SYNC_VERSION=4.4.2
 ANDROID_OPENSSL_VERSION=1.0.2k
 REALM_CORE_PACKAGING=2

+ 1 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/CMakeLists.txt

@@ -28,6 +28,7 @@ set(HEADERS
     execution_context_id.hpp
     feature_checks.hpp
     index_set.hpp
+    keypath_helpers.hpp
     list.hpp
     object.hpp
     object_accessor.hpp

+ 86 - 40
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.cpp

@@ -76,7 +76,7 @@ std::shared_ptr<RealmCoordinator> RealmCoordinator::get_existing_coordinator(Str
     return it == s_coordinators_per_path.end() ? nullptr : it->second.lock();
 }
 
-void RealmCoordinator::create_sync_session()
+void RealmCoordinator::create_sync_session(bool force_client_reset)
 {
 #if REALM_ENABLE_SYNC
     if (m_sync_session)
@@ -94,7 +94,7 @@ void RealmCoordinator::create_sync_session()
 
     auto sync_config = *m_config.sync_config;
     sync_config.validate_sync_history = false;
-    m_sync_session = SyncManager::shared().get_session(m_config.path, sync_config);
+    m_sync_session = SyncManager::shared().get_session(m_config.path, sync_config, force_client_reset);
 
     std::weak_ptr<RealmCoordinator> weak_self = shared_from_this();
     SyncSession::Internal::set_sync_transact_callback(*m_sync_session,
@@ -106,6 +106,8 @@ void RealmCoordinator::create_sync_session()
                 self->m_notifier->notify_others();
         }
     });
+#else
+    static_cast<void>(force_client_reset);
 #endif
 }
 
@@ -183,6 +185,34 @@ void RealmCoordinator::set_config(const Realm::Config& config)
     }
 }
 
+std::shared_ptr<Realm> RealmCoordinator::get_cached_realm(Realm::Config const& config)
+{
+    if (!config.cache)
+        return nullptr;
+    AnyExecutionContextID execution_context(config.execution_context);
+    for (auto& cached_realm : m_weak_realm_notifiers) {
+        if (!cached_realm.is_cached_for_execution_context(execution_context))
+            continue;
+        // can be null if we jumped in between ref count hitting zero and
+        // unregister_realm() getting the lock
+        if (auto realm = cached_realm.realm()) {
+            // If the file is uninitialized and was opened without a schema,
+            // do the normal schema init
+            if (realm->schema_version() == ObjectStore::NotVersioned)
+                break;
+
+            // Otherwise if we have a realm schema it needs to be an exact
+            // match (even having the same properties but in different
+            // orders isn't good enough)
+            if (config.schema && realm->schema() != *config.schema)
+                throw MismatchedConfigException("Realm at path '%1' already opened on current thread with different schema.", config.path);
+
+            return realm;
+        }
+    }
+    return nullptr;
+}
+
 std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
 {
     // realm must be declared before lock so that the mutex is released before
@@ -190,8 +220,16 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
     // to acquire the same lock
     std::shared_ptr<Realm> realm;
     std::unique_lock<std::mutex> lock(m_realm_mutex);
+    do_get_realm(std::move(config), realm, lock);
+    return realm;
+}
 
+void RealmCoordinator::do_get_realm(Realm::Config config, std::shared_ptr<Realm>& realm,
+                                    std::unique_lock<std::mutex>& realm_lock)
+{
     set_config(config);
+    if ((realm = get_cached_realm(config)))
+        return;
 
     auto schema = std::move(config.schema);
     auto migration_function = std::move(config.migration_function);
@@ -199,57 +237,65 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
     auto audit_factory = std::move(config.audit_factory);
     config.schema = {};
 
-    if (config.cache) {
-        AnyExecutionContextID execution_context(config.execution_context);
-        for (auto& cached_realm : m_weak_realm_notifiers) {
-            if (!cached_realm.is_cached_for_execution_context(execution_context))
-                continue;
-            // can be null if we jumped in between ref count hitting zero and
-            // unregister_realm() getting the lock
-            if ((realm = cached_realm.realm())) {
-                // If the file is uninitialized and was opened without a schema,
-                // do the normal schema init
-                if (realm->schema_version() == ObjectStore::NotVersioned)
-                    break;
-
-                // Otherwise if we have a realm schema it needs to be an exact
-                // match (even having the same properties but in different
-                // orders isn't good enough)
-                if (schema && realm->schema() != *schema)
-                    throw MismatchedConfigException("Realm at path '%1' already opened on current thread with different schema.", config.path);
-
-                return realm;
-            }
+    bool should_initialize_notifier = !config.immutable() && config.automatic_change_notifications;
+    realm = Realm::make_shared_realm(std::move(config), shared_from_this());
+    if (!m_notifier && should_initialize_notifier) {
+        try {
+            m_notifier = std::make_unique<ExternalCommitHelper>(*this);
         }
-    }
-
-    if (!realm) {
-        bool should_initialize_notifier = !config.immutable() && config.automatic_change_notifications;
-        realm = Realm::make_shared_realm(std::move(config), shared_from_this());
-        if (!m_notifier && should_initialize_notifier) {
-            try {
-                m_notifier = std::make_unique<ExternalCommitHelper>(*this);
-            }
-            catch (std::system_error const& ex) {
-                throw RealmFileException(RealmFileException::Kind::AccessError, get_path(), ex.code().message(), "");
-            }
+        catch (std::system_error const& ex) {
+            throw RealmFileException(RealmFileException::Kind::AccessError, get_path(), ex.code().message(), "");
         }
-        m_weak_realm_notifiers.emplace_back(realm, realm->config().cache);
     }
+    m_weak_realm_notifiers.emplace_back(realm, realm->config().cache);
 
     if (realm->config().sync_config)
-        create_sync_session();
+        create_sync_session(false);
 
     if (!m_audit_context && audit_factory)
         m_audit_context = audit_factory();
 
     if (schema) {
-        lock.unlock();
+        realm_lock.unlock();
         realm->update_schema(std::move(*schema), config.schema_version, std::move(migration_function),
                              std::move(initialization_function));
     }
+}
 
-    return realm;
+void RealmCoordinator::get_realm(Realm::Config config,
+                                 std::function<void(std::shared_ptr<Realm>, std::exception_ptr)> callback)
+{
+#if REALM_ENABLE_SYNC
+    if (config.sync_config) {
+        std::unique_lock<std::mutex> lock(m_realm_mutex);
+        set_config(config);
+        create_sync_session(!File::exists(m_config.path));
+        m_sync_session->wait_for_download_completion([callback, self = shared_from_this()](std::error_code ec) {
+            if (ec)
+                callback(nullptr, std::make_exception_ptr(std::system_error(ec)));
+            else {
+                std::shared_ptr<Realm> realm;
+                try {
+                    realm = self->get_realm();
+                }
+                catch (...) {
+                    return callback(nullptr, std::current_exception());
+                }
+                callback(realm, nullptr);
+            }
+        });
+        return;
+    }
+#endif
+
+    std::shared_ptr<Realm> realm;
+    try {
+        realm = get_realm(std::move(config));
+    }
+    catch (...) {
+        return callback(nullptr, std::current_exception());
+    }
+    callback(realm, nullptr);
 }
 
 std::shared_ptr<Realm> RealmCoordinator::get_realm()
@@ -925,7 +971,7 @@ void RealmCoordinator::process_available_async(Realm& realm)
 
 void RealmCoordinator::set_transaction_callback(std::function<void(VersionID, VersionID)> fn)
 {
-    create_sync_session();
+    create_sync_session(false);
     m_transaction_callback = std::move(fn);
 }
 

+ 5 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.hpp

@@ -58,6 +58,7 @@ public:
     // configuration is compatible with the existing one
     std::shared_ptr<Realm> get_realm(Realm::Config config);
     std::shared_ptr<Realm> get_realm();
+    void get_realm(Realm::Config config, std::function<void(std::shared_ptr<Realm>, std::exception_ptr)> callback);
 
     Realm::Config get_config() const { return m_config; }
 
@@ -192,7 +193,10 @@ private:
     void pin_version(VersionID version);
 
     void set_config(const Realm::Config&);
-    void create_sync_session();
+    void create_sync_session(bool force_client_reset);
+    void do_get_realm(Realm::Config config, std::shared_ptr<Realm>& realm,
+                      std::unique_lock<std::mutex>& realm_lock);
+    std::shared_ptr<Realm> get_cached_realm(Realm::Config const& config);
 
     void run_async_notifiers();
     void open_helper_shared_group();

+ 3 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object.hpp

@@ -70,6 +70,9 @@ public:
     template<typename ValueType, typename ContextType>
     ValueType get_property_value(ContextType& ctx, StringData prop_name);
 
+    template<typename ValueType, typename ContextType>
+    ValueType get_property_value(ContextType& ctx, const Property& property);
+
     // create an Object from a native representation
     template<typename ValueType, typename ContextType>
     static Object create(ContextType& ctx, std::shared_ptr<Realm> const& realm,

+ 6 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_accessor.hpp

@@ -56,6 +56,12 @@ void Object::set_property_value(ContextType& ctx, StringData prop_name, ValueTyp
     set_property_value_impl(ctx, property, value, try_update, false, false);
 }
 
+template <typename ValueType, typename ContextType>
+ValueType Object::get_property_value(ContextType& ctx, const Property& property)
+{
+    return get_property_value_impl<ValueType>(ctx, property);
+}
+
 template <typename ValueType, typename ContextType>
 ValueType Object::get_property_value(ContextType& ctx, StringData prop_name)
 {

+ 85 - 3
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.cpp

@@ -93,7 +93,8 @@ ObjectSchema::ObjectSchema(Group const& group, StringData name, size_t index) :
     set_primary_key_property();
 }
 
-Property *ObjectSchema::property_for_name(StringData name) {
+Property *ObjectSchema::property_for_name(StringData name)
+{
     for (auto& prop : persisted_properties) {
         if (StringData(prop.name) == name) {
             return &prop;
@@ -107,11 +108,36 @@ Property *ObjectSchema::property_for_name(StringData name) {
     return nullptr;
 }
 
-const Property *ObjectSchema::property_for_name(StringData name) const {
+Property *ObjectSchema::property_for_public_name(StringData public_name)
+{
+    // If no `public_name` is defined, the internal `name` is also considered the public name.
+    for (auto& prop : persisted_properties) {
+        if (prop.public_name == public_name || (prop.public_name.empty() && prop.name == public_name))
+            return &prop;
+    }
+
+    // Computed properties are not persisted, so creating a public name for such properties
+    // are a bit pointless since the internal name is already the "public name", but since
+    // this distinction isn't visible in the Property struct we allow it anyway.
+    for (auto& prop : computed_properties) {
+        if ((prop.public_name.empty() ? StringData(prop.name) :  StringData(prop.public_name)) == public_name)
+            return &prop;
+    }
+    return nullptr;
+}
+
+const Property *ObjectSchema::property_for_public_name(StringData public_name) const
+{
+    return const_cast<ObjectSchema *>(this)->property_for_public_name(public_name);
+}
+
+const Property *ObjectSchema::property_for_name(StringData name) const
+{
     return const_cast<ObjectSchema *>(this)->property_for_name(name);
 }
 
-bool ObjectSchema::property_is_computed(Property const& property) const {
+bool ObjectSchema::property_is_computed(Property const& property) const
+{
     auto end = computed_properties.end();
     return std::find(computed_properties.begin(), end, property) != end;
 }
@@ -214,6 +240,62 @@ static void validate_property(Schema const& schema,
 
 void ObjectSchema::validate(Schema const& schema, std::vector<ObjectSchemaValidationException>& exceptions) const
 {
+    std::vector<StringData> public_property_names;
+    std::vector<StringData> internal_property_names;
+    internal_property_names.reserve(persisted_properties.size() + computed_properties.size());
+    auto gather_names = [&](auto const &properties) {
+        for (auto const &prop : properties) {
+            internal_property_names.push_back(prop.name);
+            if (!prop.public_name.empty())
+                public_property_names.push_back(prop.public_name);
+        }
+    };
+    gather_names(persisted_properties);
+    gather_names(computed_properties);
+    std::sort(public_property_names.begin(), public_property_names.end());
+    std::sort(internal_property_names.begin(), internal_property_names.end());
+
+    // Check that property names and aliases are unique
+    auto for_each_duplicate = [](auto &&container, auto &&fn) {
+        auto end = container.end();
+        for (auto it = std::adjacent_find(container.begin(), end); it != end; it = std::adjacent_find(it + 2, end))
+            fn(*it);
+    };
+    for_each_duplicate(public_property_names, [&](auto public_property_name) {
+        exceptions.emplace_back("Alias '%1' appears more than once in the schema for type '%2'.",
+                                public_property_name, name);
+    });
+    for_each_duplicate(internal_property_names, [&](auto internal_name) {
+        exceptions.emplace_back("Property '%1' appears more than once in the schema for type '%2'.",
+                                internal_name, name);
+    });
+
+    // Check that no aliases conflict with property names
+    struct ErrorWriter {
+        ObjectSchema const &os;
+        std::vector<ObjectSchemaValidationException> &exceptions;
+
+        struct Proxy {
+            ObjectSchema const &os;
+            std::vector<ObjectSchemaValidationException> &exceptions;
+
+            Proxy &operator=(StringData name) {
+                exceptions.emplace_back(
+                        "Property '%1.%2' has an alias '%3' that conflicts with a property of the same name.",
+                        os.name, os.property_for_public_name(name)->name, name);
+                return *this;
+            }
+        };
+
+        Proxy operator*() { return Proxy{os, exceptions}; }
+        ErrorWriter &operator=(const ErrorWriter &) { return *this; }
+        ErrorWriter &operator++() { return *this; }
+        ErrorWriter &operator++(int) { return *this; }
+    } writer{*this, exceptions};
+    std::set_intersection(public_property_names.begin(), public_property_names.end(),
+                          internal_property_names.begin(), internal_property_names.end(), writer);
+
+    // Validate all properties
     const Property *primary = nullptr;
     for (auto const& prop : persisted_properties) {
         validate_property(schema, name, prop, &primary, exceptions);

+ 2 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.hpp

@@ -49,6 +49,8 @@ public:
     std::vector<Property> computed_properties;
     std::string primary_key;
 
+    Property *property_for_public_name(StringData public_name);
+    const Property *property_for_public_name(StringData public_name) const;
     Property *property_for_name(StringData name);
     const Property *property_for_name(StringData name) const;
     Property *primary_key_property() {

+ 25 - 4
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/property.hpp

@@ -62,7 +62,24 @@ struct Property {
     using IsPrimary = util::TaggedBool<class IsPrimaryTag>;
     using IsIndexed = util::TaggedBool<class IsIndexedTag>;
 
+    // The internal column name used in the Realm file.
     std::string name;
+
+    // The public name used by the binding to represent the internal column name in the Realm file. Bindings can use
+    // this to expose a different name in the binding API, e.g. to map between different naming conventions.
+    //
+    // Public names are only ever user defined, they are not persisted on disk, so reading the schema from the file
+    // will leave this field empty. If `public_name` is empty, the internal and public name are considered to be the same.
+    //
+    // ObjectStore will ensure that no conflicts occur between persisted properties and the public name, so
+    // the public name is just as unique an identifier as the internal name in the file.
+    //
+    // In order to respect public names bindings should use `ObjectSchema::property_for_public_name()` in the schema
+    // and `Object::value_for_property()` in the Object accessor for reading fields defined by the public name.
+    //
+    // For queries, bindings should provide an appropriate `KeyPathMapping` definition. Bindings are responsible
+    // for creating this.
+    std::string public_name;
     PropertyType type = PropertyType::Int;
     std::string object_type;
     std::string link_origin_property_name;
@@ -73,10 +90,10 @@ struct Property {
 
     Property() = default;
 
-    Property(std::string name, PropertyType type, IsPrimary primary = false, IsIndexed indexed = false);
+    Property(std::string name, PropertyType type, IsPrimary primary = false, IsIndexed indexed = false, std::string public_name = "");
 
     Property(std::string name, PropertyType type, std::string object_type,
-             std::string link_origin_property_name = "");
+             std::string link_origin_property_name = "", std::string public_name = "");
 
     Property(Property const&) = default;
     Property(Property&&) = default;
@@ -196,8 +213,10 @@ static const char *string_for_property_type(PropertyType type)
 }
 
 inline Property::Property(std::string name, PropertyType type,
-                          IsPrimary primary, IsIndexed indexed)
+                          IsPrimary primary, IsIndexed indexed,
+                          std::string public_name)
 : name(std::move(name))
+, public_name(std::move(public_name))
 , type(type)
 , is_primary(primary)
 , is_indexed(indexed)
@@ -206,8 +225,10 @@ inline Property::Property(std::string name, PropertyType type,
 
 inline Property::Property(std::string name, PropertyType type,
                           std::string object_type,
-                          std::string link_origin_property_name)
+                          std::string link_origin_property_name,
+                          std::string public_name)
 : name(std::move(name))
+, public_name(std::move(public_name))
 , type(type)
 , object_type(std::move(object_type))
 , link_origin_property_name(std::move(link_origin_property_name))

+ 15 - 8
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.cpp

@@ -627,14 +627,21 @@ Results Results::apply_ordering(DescriptorOrdering&& ordering)
     DescriptorOrdering new_order = m_descriptor_ordering;
     for (size_t i = 0; i < ordering.size(); ++i) {
         auto desc = ordering[i];
-        if (auto sort = dynamic_cast<const SortDescriptor*>(desc))
-            new_order.append_sort(std::move(*sort));
-        else if (auto distinct = dynamic_cast<const DistinctDescriptor*>(desc))
-            new_order.append_distinct(std::move(*distinct));
-        else if (auto limit = dynamic_cast<const LimitDescriptor*>(desc))
-            new_order.append_limit(std::move(*limit));
-        else
-            REALM_COMPILER_HINT_UNREACHABLE();
+        DescriptorType desc_type = ordering.get_type(i);
+        switch (desc_type) {
+            case DescriptorType::Sort:
+                new_order.append_sort(std::move(*dynamic_cast<const SortDescriptor*>(desc)));
+                break;
+            case DescriptorType::Distinct:
+                new_order.append_distinct(std::move(*dynamic_cast<const DistinctDescriptor*>(desc)));
+                break;
+            case DescriptorType::Limit:
+                new_order.append_limit(std::move(*dynamic_cast<const LimitDescriptor*>(desc)));
+                break;
+            case DescriptorType::Include:
+                new_order.append_include(std::move(*dynamic_cast<const IncludeDescriptor*>(desc)));
+                break;
+        }
     }
     return Results(m_realm, get_query(), std::move(new_order));
 }

+ 6 - 3
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.hpp

@@ -345,10 +345,13 @@ void Results::set_property_value(ContextType& ctx, StringData prop_name, ValueTy
         throw ModifyPrimaryKeyException(m_object_schema->name, prop->name);
     }
 
-    // Update all objects in this ResultSets
-    size_t size = this->size();
+    // Update all objects in this ResultSets. Use snapshot to avoid correctness problems if the
+    // object is removed from the TableView after the property update as well as avoiding to
+    // re-evaluating the query too many times.
+    auto snapshot = this->snapshot();
+    size_t size = snapshot.size();
     for (size_t i = 0; i < size; ++i) {
-        Object obj(m_realm, *m_object_schema, get(i));
+        Object obj(m_realm, *m_object_schema, snapshot.get(i));
         obj.set_property_value_impl(ctx, *prop, value, true, false, false);
     }
 }

+ 1 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/schema.cpp

@@ -80,6 +80,7 @@ void Schema::validate() const
 {
     std::vector<ObjectSchemaValidationException> exceptions;
 
+    // As the types are added sorted by name, we can detect duplicates by just looking at the following element.
     auto find_next_duplicate = [&](const_iterator start) {
         return std::adjacent_find(start, cend(), [](ObjectSchema const& lft, ObjectSchema const& rgt) {
             return lft.name == rgt.name;

+ 9 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.cpp

@@ -182,8 +182,9 @@ void Realm::open_with_config(const Config& config,
             SharedGroupOptions options;
             options.durability = config.in_memory ? SharedGroupOptions::Durability::MemOnly :
                                                     SharedGroupOptions::Durability::Full;
-
-            options.temp_dir = util::normalize_dir(config.fifo_files_fallback_path);
+            if (!config.fifo_files_fallback_path.empty()) {
+                options.temp_dir = util::normalize_dir(config.fifo_files_fallback_path);
+            }
             options.encryption_key = config.encryption_key.data();
             options.allow_file_format_upgrade = !config.disable_format_upgrade &&
                                                 config.schema_mode != SchemaMode::ResetFile;
@@ -271,6 +272,12 @@ SharedRealm Realm::get_shared_realm(Config config)
     return coordinator->get_realm(std::move(config));
 }
 
+void Realm::get_shared_realm(Config config, std::function<void(SharedRealm, std::exception_ptr)> callback)
+{
+    auto coordinator = RealmCoordinator::get_coordinator(config.path);
+    coordinator->get_realm(std::move(config), callback);
+}
+
 void Realm::set_schema(Schema const& reference, Schema schema)
 {
     m_dynamic_schema = false;

+ 10 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.hpp

@@ -261,6 +261,16 @@ public:
     // encryption key will raise an exception.
     static SharedRealm get_shared_realm(Config config);
 
+    // Open a Realm and then pass it to the callback.
+    //
+    // If SyncConfig is set, the callback will not be invoked until the latest
+    // Realm state has been fully downloaded. This will result in the callback
+    // being invoked on a different thread. The calling code should normally
+    // dispatch back to the desired thread and obtain a new reference to the
+    // Realm, only using the reference passed to the callback to keep the file
+    // open while this is happening.
+    static void get_shared_realm(Config config, std::function<void(SharedRealm, std::exception_ptr)> callback);
+
     // Updates a Realm to a given schema, using the Realm's pre-set schema mode.
     void update_schema(Schema schema, uint64_t version=0,
                        MigrationFunction migration_function=nullptr,

+ 98 - 3
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp

@@ -33,6 +33,7 @@
 #include "impl/realm_coordinator.hpp"
 
 #include <realm/group.hpp>
+#include <realm/util/scope_exit.hpp>
 
 namespace realm {
 class TestHelper {
@@ -175,10 +176,7 @@ TEST_CASE("SharedRealm: get_shared_realm()") {
         realm::util::remove_dir(config.path + ".note");
         realm::util::remove_dir_recursive(fallback_dir);
     }
-#endif
 
-// Windows doesn't use fifos
-#ifndef _WIN32
     SECTION("automatically append dir separator to end of fallback path") {
         std::string fallback_dir = tmp_dir() + "/fallback";
         realm::util::try_make_dir(fallback_dir);
@@ -446,6 +444,103 @@ TEST_CASE("SharedRealm: get_shared_realm()") {
     }
 }
 
+TEST_CASE("SharedRealm: get_shared_realm() with callback") {
+    TestFile local_config;
+    local_config.schema_version = 1;
+    local_config.schema = Schema{
+        {"object", {
+            {"value", PropertyType::Int}
+        }},
+    };
+
+    SECTION("immediately invokes callback for non-sync realms") {
+        bool called = false;
+        Realm::get_shared_realm(local_config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+        });
+        REQUIRE(called);
+    }
+
+#if REALM_ENABLE_SYNC
+    if (!util::EventLoop::has_implementation())
+        return;
+
+    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
+    SyncManager::shared().configure(tmp_dir(), SyncManager::MetadataMode::NoEncryption);
+
+    SyncServer server;
+    SyncTestFile config(server, "default");
+    config.cache = false;
+    config.schema = Schema{
+        {"object", {
+            {"value", PropertyType::Int},
+        }},
+    };
+    SyncTestFile config2(server, "default");
+    config2.cache = false;
+    config2.schema = config.schema;
+
+    SECTION("can open synced Realms that don't already exist") {
+        std::atomic<bool> called{false};
+        Realm::get_shared_realm(config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+
+            REQUIRE(realm->read_group().get_table("class_object"));
+        });
+        util::EventLoop::main().run_until([&]{ return called.load(); });
+        REQUIRE(called);
+    }
+
+    SECTION("downloads Realms which exist on the server") {
+        {
+            auto realm = Realm::get_shared_realm(config2);
+            realm->begin_transaction();
+            sync::create_object(realm->read_group(), *realm->read_group().get_table("class_object"));
+            realm->commit_transaction();
+            wait_for_upload(*realm);
+        }
+
+        std::atomic<bool> called{false};
+        Realm::get_shared_realm(config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+
+            REQUIRE(realm->read_group().get_table("class_object")->size() == 1);
+        });
+        util::EventLoop::main().run_until([&]{ return called.load(); });
+        REQUIRE(called);
+    }
+
+    SECTION("downloads latest state for Realms which already exist locally") {
+        wait_for_upload(*Realm::get_shared_realm(config));
+
+        {
+            auto realm = Realm::get_shared_realm(config2);
+            realm->begin_transaction();
+            sync::create_object(realm->read_group(), *realm->read_group().get_table("class_object"));
+            realm->commit_transaction();
+            wait_for_upload(*realm);
+        }
+
+        std::atomic<bool> called{false};
+        Realm::get_shared_realm(config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+
+            REQUIRE(realm->read_group().get_table("class_object")->size() == 1);
+        });
+        util::EventLoop::main().run_until([&]{ return called.load(); });
+        REQUIRE(called);
+    }
+#endif
+}
+
 TEST_CASE("SharedRealm: notifications") {
     if (!util::EventLoop::has_implementation())
         return;

+ 9 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/results.cpp

@@ -2888,6 +2888,15 @@ TEST_CASE("results: set property value on all objects", "[batch_updates]") {
         realm->cancel_transaction();
     }
 
+    SECTION("set property values removes object from Results") {
+        realm->begin_transaction();
+        Results results(realm, table->where().equal(2,0));
+        CHECK(results.size() == 2);
+        r.set_property_value(ctx, "int", util::Any(INT64_C(42)));
+        CHECK(results.size() == 0);
+        realm->cancel_transaction();
+    }
+
     SECTION("set property value") {
         realm->begin_transaction();
 

+ 116 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/schema.cpp

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////////////
 
 #include "catch.hpp"
+#include "util/test_file.hpp"
 
 #include "object_schema.hpp"
 #include "object_store.hpp"
@@ -84,6 +85,33 @@ struct StringMaker<SchemaChange> {
     REQUIRE_THROWS_WITH(expr, Catch::Matchers::Contains(msg))
 
 TEST_CASE("ObjectSchema") {
+
+    SECTION("Aliases are still present in schema returned from the Realm") {
+        TestFile config;
+        config.schema_version = 1;
+        config.schema = Schema{
+                {"object", {
+                   {"value", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "alias"}
+               }},
+        };
+
+        auto realm = Realm::get_shared_realm(config);
+        REQUIRE(realm->schema().find("object")->property_for_name("value")->public_name == "alias");
+    }
+
+    SECTION("looking up properties by alias matches name if alias is not set") {
+        auto schema = Schema{
+            {"object", {
+               {"value", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "alias"},
+               {"other_value", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}}
+            }},
+        };
+
+        REQUIRE(schema.find("object")->property_for_public_name("value") == nullptr);
+        REQUIRE(schema.find("object")->property_for_public_name("alias")->name == "value");
+        REQUIRE(schema.find("object")->property_for_public_name("other_value")->name == "other_value");
+    }
+
     SECTION("from a Group") {
         Group g;
         TableRef pk = g.add_table("pk");
@@ -531,6 +559,94 @@ TEST_CASE("Schema") {
                 "- Type 'object1' appears more than once in the schema.\n"
                 "- Type 'object2' appears more than once in the schema.");
         }
+
+        SECTION("rejects properties with the same name") {
+            Schema schema = {
+                {"object", {
+                    {"child", PropertyType::Object|PropertyType::Nullable, "object"},
+                    {"parent", PropertyType::Int},
+                    {"field1", PropertyType::Int},
+                    {"field2", PropertyType::String},
+                    {"field1", PropertyType::String},
+                    {"field2", PropertyType::String},
+                    {"field1", PropertyType::Int},
+                }, {
+                    {"parent", PropertyType::Array|PropertyType::LinkingObjects, "object", "child"}
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                  "- Property 'field1' appears more than once in the schema for type 'object'.\n"
+                  "- Property 'field2' appears more than once in the schema for type 'object'.\n"
+                  "- Property 'parent' appears more than once in the schema for type 'object'.");
+        }
+
+        SECTION("rejects schema if all properties have the same name") {
+            Schema schema = {
+                {"object", {
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                    "- Property 'field' appears more than once in the schema for type 'object'.\n"
+                    "- Property 'otherField' appears more than once in the schema for type 'object'.");
+        }
+
+        SECTION("rejects properties with the same alias") {
+            Schema schema = {
+                {"object", {
+                    {"child", PropertyType::Object|PropertyType::Nullable, "object"},
+
+                    // Alias == Name on computed property
+                    {"parentA", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "_parent"},
+
+                    // Name == Alias on other property
+                    {"fieldA", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field1"},
+                    {"fieldB", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field2"},
+                    {"fieldC", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field1"},
+                    {"fieldD", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field2"},
+                    {"fieldE", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field1"},
+
+                    // Name == Alias
+                    {"fieldF", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "fieldF"},
+                }, {
+                    // Computed property alias == name on persisted property
+                    {"parentB", PropertyType::Array|PropertyType::LinkingObjects, "object", "child", "_parent"}
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                  "- Alias '_field1' appears more than once in the schema for type 'object'.\n"
+                  "- Alias '_field2' appears more than once in the schema for type 'object'.\n"
+                  "- Alias '_parent' appears more than once in the schema for type 'object'.");
+        }
+
+        SECTION("rejects properties whose name conflicts with an alias for another property") {
+            Schema schema = {
+                {"object", {
+                    {"child", PropertyType::Object|PropertyType::Nullable, "object"},
+                    {"field1", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "field2"},
+                    {"field2", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "parent"},
+                }, {
+                    {"parent", PropertyType::Array|PropertyType::LinkingObjects, "object", "child", "field1"}
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                  "- Property 'object.parent' has an alias 'field1' that conflicts with a property of the same name.\n"
+                  "- Property 'object.field1' has an alias 'field2' that conflicts with a property of the same name.\n"
+                  "- Property 'object.field2' has an alias 'parent' that conflicts with a property of the same name.");
+        }
     }
 
     SECTION("compare()") {

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/transaction_log_parsing.cpp

@@ -67,7 +67,7 @@ public:
         }
 
         validate(c);
-        return c;
+        return std::move(c);
     }
 
     explicit operator bool() const { return m_realm->is_in_transaction(); }

+ 4 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMProperty.mm

@@ -92,6 +92,10 @@ static bool rawTypeShouldBeTreatedAsComputedProperty(NSString *rawType) {
     if (is_array(prop.type)) {
         ret->_array = true;
     }
+    if (!prop.public_name.empty()) {
+        ret->_columnName = ret->_name;
+        ret->_name = @(prop.public_name.c_str());
+    }
     return ret;
 }
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMRealm+Sync.mm

@@ -47,7 +47,7 @@ using namespace realm;
 
         Holder(partial_sync::Subscription&& s) : subscription(std::move(s)) { }
     };
-    auto state = std::make_shared<Holder>(partial_sync::subscribe(Results(_realm, std::move(q)), util::none));
+    auto state = std::make_shared<Holder>(partial_sync::subscribe(Results(_realm, std::move(q)), {}));
     state->token = state->subscription.add_notification_callback([=]() mutable {
         if (!callback) {
             return;

+ 3 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h

@@ -110,6 +110,9 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable)
 
 /**
  Extra HTTP headers to append to every request to a Realm Object Server.
+
+ Modifying this property while sync sessions are active will result in all
+ sessions disconnecting and reconnecting using the new headers.
  */
 @property (nullable, nonatomic, copy) NSDictionary<NSString *, NSString *> *customRequestHeaders;
 

+ 15 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm

@@ -138,6 +138,21 @@ static RLMSyncManager *s_sharedManager = nil;
     _userAgent = userAgent;
 }
 
+- (void)setCustomRequestHeaders:(NSDictionary<NSString *,NSString *> *)customRequestHeaders {
+    _customRequestHeaders = customRequestHeaders.copy;
+
+    for (auto&& user : SyncManager::shared().all_logged_in_users()) {
+        for (auto&& session : user->all_sessions()) {
+            auto config = session->config();
+            config.custom_http_headers.clear();;
+            for (NSString *key in customRequestHeaders) {
+                config.custom_http_headers.emplace(key.UTF8String, customRequestHeaders[key].UTF8String);
+            }
+            session->update_configuration(std::move(config));
+        }
+    }
+}
+
 #pragma mark - Passthrough properties
 
 - (RLMSyncLogLevel)logLevel {

+ 3 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSession.mm

@@ -109,7 +109,9 @@ static RLMSyncConnectionState convertConnectionState(SyncSession::ConnectionStat
         // No need to save the token as RLMSyncSession always outlives the
         // underlying SyncSession
         session->register_connection_change_callback([=](auto, auto newState) {
-            self.connectionState = convertConnectionState(newState);
+            dispatch_async(dispatch_get_main_queue(), ^{
+                self.connectionState = convertConnectionState(newState);
+            });
         });
         return self;
     }

+ 162 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.h

@@ -92,6 +92,63 @@ typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
  */
 @property (nonatomic, readonly, nullable) NSError *error;
 
+/**
+ The raw query which this subscription is running on the server.
+
+ This string is a serialized representation of the RLMResults which the
+ subscription was created from. This representation does *not* use NSPredicate
+ syntax, and is not guaranteed to remain consistent between versions of Realm.
+ Any use of this other than manual inspection when debugging is likely to be
+ incorrect.
+
+ This is `nil` while the subscription is in the Creating state.
+ */
+@property (nonatomic, readonly, nullable) NSString *query;
+
+/**
+ When this subscription was first created.
+
+ This value will be `nil` for subscriptions created with older versions of Realm
+ which did not store the creation date. Newly created subscriptions should
+ always have a non-nil creation date.
+ */
+@property (nonatomic, readonly, nullable) NSDate *createdAt;
+
+/**
+ When this subscription was last updated.
+
+ This value will be `nil` for subscriptions created with older versions of Realm
+ which did not store the update date. Newly created subscriptions should
+ always have a non-nil update date.
+
+ The update date is the time when the subscription was last updated by a call
+ to `-[RLMResults subscribeWithOptions:]`, and not when the set of objects which
+ match the subscription last changed.
+ */
+@property (nonatomic, readonly, nullable) NSDate *updatedAt;
+
+/**
+ When this subscription will be automatically removed.
+
+ If the `timeToLive` parameter is set when creating a sync subscription, the
+ subscription will be automatically removed the first time that any subscription
+ is created, modified, or deleted after that time has elapsed.
+
+ This property will be `nil` if the `timeToLive` option was not enabled.
+ */
+@property (nonatomic, readonly, nullable) NSDate *expiresAt;
+
+/**
+ How long this subscription will persist after last being updated.
+
+ If the `timeToLive` parameter is set when creating a sync subscription, the
+ subscription will be automatically removed the first time that any subscription
+ is created, modified, or deleted after that time has elapsed.
+
+ This property will be NaN if the `timeToLive` option was not enabled.
+ */
+@property (nonatomic, readonly) NSTimeInterval timeToLive;
+
 /**
  Remove this subscription.
 
@@ -121,6 +178,82 @@ typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
 
 @end
 
+/**
+ Configuration options for query-based sync subscriptions.
+ */
+@interface RLMSyncSubscriptionOptions : NSObject
+/**
+ The name of the subscription.
+
+ Naming a subscription makes it possible to look up a subscription by name
+ (using `-[RLMRealm subscriptionWithName:]`) or update an existing
+ subscription rather than creating a new one.
+ */
+@property (nonatomic, copy, nullable) NSString *name;
+
+/**
+ Whether this should update an existing subscription with the same name.
+
+ By default trying to create a subscription with a name that's already in use
+ will fail unless the new subscription is an exact match for the existing one.
+ If this is set to YES, instead the existing subscription will be updated using
+ the query and options from the new subscription. This only works if the new
+ subscription is for the same type of objects as the existing subscription.
+ Trying to overwrite a subscription with a subscription of a different type of
+ objects will fail.
+
+ The `updatedAt` and (if `timeToLive` is used) `expiresAt` properties are
+ updated whenever a subscription is overwritten even if nothing else has changed.
+ */
+@property (nonatomic) BOOL overwriteExisting;
+
+/**
+ How long (in seconds) a subscription should persist after being created.
+
+ By default subscriptions are persistent, and last until they are explicitly
+ removed by calling `unsubscribe()`. Subscriptions can instead be made temporary
+ by setting the time to live to how long the subscription should remain. After
+ that time has elapsed the subscription will be automatically removed.
+
+ A time to live of 0 or less disables subscription expiration.
+ */
+@property (nonatomic) NSTimeInterval timeToLive;
+
+/**
+ The maximum number of top-level matches to include in this subscription.
+
+ If more top-level objects than the limit match the query, only the first
+ `limit` objects will be included. This respects the sort and distinct order of
+ the query being subscribed to for the determination of what the "first" objects
+ are.
+
+ The limit does not count or apply to objects which are added indirectly due to
+ being linked to by the objects in the subscription or due to being listed in
+ `includeLinkingObjectProperties`. If the limit is larger than the number of
+ objects which match the query, all objects will be included. A limit of zero is
+ treated as unlimited.
+ */
+@property (nonatomic) NSUInteger limit;
+
+/**
+ Which RLMLinkingObjects properties should be included in the subscription.
+
+ Outgoing links (i.e. `RLMArray` and `RLMObject` properties) are automatically
+ included in sync subscriptions. That is, if you subscribe to a query which
+ matches one object, every object which is reachable via links from that object
+ are also included in the subscription.
+
+ By default, RLMLinkingObjects properties do not work this way. Instead, they
+ only report objects which happen to be included in a subscription. By naming
+ a RLMLinkingObjects property in this array, it can instead be treated as if
+ it was a RLMArray and include all objects which link to this object.
+
+ Any keypath which ends in a RLMLinkingObject property can be included in this
+ array, including ones involving intermediate links.
+ */
+@property (nonatomic, copy, nullable) NSArray<NSString *> *includeLinkingObjectProperties;
+@end
+
 /**
  Support for subscribing to the results of object queries in a synced Realm.
  */
@@ -214,6 +347,35 @@ typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
  @see RLMSyncSubscription
  */
 - (RLMSyncSubscription *)subscribeWithName:(nullable NSString *)subscriptionName limit:(NSUInteger)limit;
+
+/**
+ Subscribe to a subset of the query represented by this `RLMResults`.
+
+ Subscribing to a query asks the server to synchronize all objects to the
+ client which match the query, along with all objects which are reachable
+ from those objects via links. This happens asynchronously, and the local
+ client Realm may not immediately have all objects which match the query.
+ Observe the `state` property of the returned subscription object to be
+ notified of when the subscription has been processed by the server and
+ all objects matching the query are available.
+
+ Creating a new subscription with the same name and query as an existing
+ subscription will not create a new subscription, but instead will return
+ an object referring to the existing sync subscription. This means that
+ performing the same subscription twice followed by removing it once will
+ result in no subscription existing.
+
+ The newly created subscription will not be reported by
+ `-[RLMRealm subscriptions]` or `-[RLMRealm subscriptionWithName:]` until
+ `state` has transitioned from `RLMSyncSubscriptionStateCreating` to any of the
+ other states.
+
+ @param options The additional configuration options for the subscription.
+ @return The subscription.
+
+ @see RLMSyncSubscription
+ */
+- (RLMSyncSubscription *)subscribeWithOptions:(RLMSyncSubscriptionOptions *)options;
 @end
 
 /**

+ 177 - 13
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.mm

@@ -30,25 +30,94 @@
 
 using namespace realm;
 
+@implementation RLMSyncSubscriptionOptions
+@end
+
 @interface RLMSyncSubscription ()
 @property (nonatomic, readwrite) RLMSyncSubscriptionState state;
 @property (nonatomic, readwrite, nullable) NSError *error;
+@property (nonatomic, readwrite) NSString *query;
+@property (nonatomic, readwrite, nullable) NSDate *createdAt;
+@property (nonatomic, readwrite, nullable) NSDate *updatedAt;
+@property (nonatomic, readwrite, nullable) NSDate *expiresAt;
+@property (nonatomic, readwrite) NSTimeInterval timeToLive;
 @end
 
 @implementation RLMSyncSubscription {
     partial_sync::SubscriptionNotificationToken _token;
     util::Optional<partial_sync::Subscription> _subscription;
+    Object _obj;
     RLMRealm *_realm;
 }
 
-- (instancetype)initWithName:(NSString *)name results:(Results const&)results realm:(RLMRealm *)realm {
+static std::vector<LinkPathPart> parseKeypath(StringData keypath, Group const& group,
+                                              Schema const& schema, const ObjectSchema *objectSchema) {
+    auto check = [&](bool condition, const char* fmt, auto... args) {
+        if (!condition) {
+            throw std::invalid_argument(util::format("Invalid LinkingObjects inclusion from key path '%1': %2.",
+                                                     keypath, util::format(fmt, args...)));
+        }
+    };
+
+    const char* begin = keypath.data();
+    const char* end = keypath.data() + keypath.size();
+    check(begin != end, "missing property name");
+
+    std::vector<LinkPathPart> ret;
+    while (begin != end) {
+        auto sep = std::find(begin, end, '.');
+        check(sep != begin && sep + 1 != end, "missing property name");
+        StringData key(begin, sep - begin);
+        begin = sep + (sep != end);
+
+        auto prop = objectSchema->property_for_name(key);
+        check(prop, "property '%1.%2' does not exist", objectSchema->name, key);
+        check(prop->type == PropertyType::Object || prop->type == PropertyType::LinkingObjects,
+              "property '%1.%2' is of unsupported type '%3'",
+              objectSchema->name, key, string_for_property_type(prop->type));
+
+        objectSchema = &*schema.find(prop->object_type);
+
+        if (prop->type == PropertyType::Object) {
+            check(begin != end, "key path must end in a LinkingObjects property and '%1.%2' is of type '%3'",
+                  objectSchema->name, key, string_for_property_type(prop->type));
+            ret.emplace_back(prop->table_column);
+        }
+        else {
+            ret.emplace_back(objectSchema->property_for_name(prop->link_origin_property_name)->table_column,
+                             ObjectStore::table_for_object_type(group, objectSchema->name));
+        }
+    }
+    return ret;
+}
+
+- (instancetype)initWithOptions:(RLMSyncSubscriptionOptions *)options results:(Results const&)results realm:(RLMRealm *)realm {
     if (!(self = [super init]))
         return nil;
 
-    _name = [name copy];
+    _name = [options.name copy];
+    _timeToLive = NAN;
     _realm = realm;
+    _createdAt = _updatedAt = NSDate.date;
     try {
-        _subscription = partial_sync::subscribe(results, name ? util::make_optional<std::string>(name.UTF8String) : util::none);
+        partial_sync::SubscriptionOptions opt;
+        if (options.name) {
+            opt.user_provided_name = std::string(RLMStringDataWithNSString(options.name));
+        }
+        if (options.timeToLive > 0) {
+            opt.time_to_live_ms = options.timeToLive * 1000;
+        }
+        opt.update = options.overwriteExisting;
+        if (options.includeLinkingObjectProperties) {
+            std::vector<std::vector<LinkPathPart>> keypaths;
+            for (NSString *keyPath in options.includeLinkingObjectProperties) {
+                keypaths.push_back(parseKeypath(keyPath.UTF8String, realm.group,
+                                                realm->_realm->schema(),
+                                                &results.get_object_schema()));
+            }
+            opt.inclusions = IncludeDescriptor{*ObjectStore::table_for_object_type(realm.group, results.get_object_type()), keypaths};
+        }
+        _subscription = partial_sync::subscribe(options.limit ? results.limit(options.limit) : results, std::move(opt));
     }
     catch (std::exception const& e) {
         @throw RLMException(e);
@@ -56,9 +125,12 @@ using namespace realm;
     self.state = (RLMSyncSubscriptionState)_subscription->state();
     __weak auto weakSelf = self;
     _token = _subscription->add_notification_callback([weakSelf] {
-        auto self = weakSelf;
-        if (!self)
-            return;
+        RLMSyncSubscription *self;
+        @autoreleasepool {
+            self = weakSelf;
+            if (!self)
+                return;
+        }
 
         // Retrieve the current error and status. Update our properties only if the values have changed,
         // since clients use KVO to observe these properties.
@@ -91,6 +163,22 @@ using namespace realm;
                 self.state = status;
             }
         }
+
+        if (status != RLMSyncSubscriptionStateComplete) {
+            return;
+        }
+
+        auto obj = self->_subscription->result_set_object();
+        if (obj && obj->is_valid()) {
+            _obj = std::move(*obj);
+            _token = {};
+            _token.result_sets_token = _obj.add_notification_callback([weakSelf](CollectionChangeSet const&, std::exception_ptr) {
+                @autoreleasepool {
+                    [weakSelf updateFromRow];
+                }
+            });
+            [self updateFromRow];
+        }
     });
 
     return self;
@@ -99,6 +187,36 @@ using namespace realm;
 - (void)unsubscribe {
     partial_sync::unsubscribe(*_subscription);
 }
+
+- (void)updateFromRow {
+    // We only want to call the setter if the value actually changed because of KVO
+#define REALM_SET_IF_CHANGED(prop, value) do { \
+    auto newValue = value; \
+    if (prop != newValue) { \
+        prop = newValue; \
+    } \
+} while (0)
+
+    if (!_obj.is_valid()) {
+        REALM_SET_IF_CHANGED(self.state, RLMSyncSubscriptionStateInvalidated);
+        return;
+    }
+
+    auto row = _obj.row();
+    REALM_SET_IF_CHANGED(self.query, RLMStringDataToNSString(row.get_string(row.get_column_index("query"))));
+    REALM_SET_IF_CHANGED(self.createdAt, RLMTimestampToNSDate(row.get_timestamp(row.get_column_index("created_at"))));
+    REALM_SET_IF_CHANGED(self.updatedAt, RLMTimestampToNSDate(row.get_timestamp(row.get_column_index("updated_at"))));
+    REALM_SET_IF_CHANGED(self.expiresAt, RLMTimestampToNSDate(row.get_timestamp(row.get_column_index("expires_at"))));
+#undef REALM_SET_IF_CHANGED
+
+    auto ttl = row.get<util::Optional<int64_t>>(row.get_column_index("time_to_live"));
+    if (ttl && _timeToLive != *ttl / 1000.0) {
+        self.timeToLive = *ttl / 1000.0;
+    }
+    else if (!ttl && !isnan(_timeToLive)) {
+        self.timeToLive = NAN;
+    }
+}
 @end
 
 @interface RLMSyncSubscriptionObject : RLMObjectBase
@@ -112,6 +230,10 @@ using namespace realm;
     return _row.is_attached() ? RLMStringDataToNSString(_row.get_string(_row.get_column_index("name"))) : nil;
 }
 
+- (NSString *)query {
+    return _row.is_attached() ? RLMStringDataToNSString(_row.get_string(_row.get_column_index("query"))) : nil;
+}
+
 - (RLMSyncSubscriptionState)state {
     if (!_row.is_attached()) {
         return RLMSyncSubscriptionStateInvalidated;
@@ -132,6 +254,29 @@ using namespace realm;
                            userInfo:@{NSLocalizedDescriptionKey: RLMStringDataToNSString(err)}];
 }
 
+- (NSDate *)createdAt {
+    return _row.is_attached() ? RLMTimestampToNSDate(_row.get_timestamp(_row.get_column_index("created_at"))) : nil;
+}
+
+- (NSDate *)updatedAt {
+    return _row.is_attached() ? RLMTimestampToNSDate(_row.get_timestamp(_row.get_column_index("updated_at"))) : nil;
+}
+
+- (NSDate *)expiresAt {
+    return _row.is_attached() ? RLMTimestampToNSDate(_row.get_timestamp(_row.get_column_index("expires_at"))) : nil;
+}
+
+- (NSTimeInterval)timeToLive {
+    if (!_row.is_attached()) {
+        return NAN;
+    }
+    auto columnIndex = _row.get_column_index("time_to_live");
+    if (_row.is_null(columnIndex)) {
+        return NAN;
+    }
+    return _row.get_int(columnIndex) / 1000.0;
+}
+
 - (NSString *)descriptionWithMaxDepth:(NSUInteger)depth {
     if (depth == 0) {
         return @"<Maximum depth exceeded>";
@@ -139,10 +284,10 @@ using namespace realm;
 
     auto objectType = _row.get_string(_row.get_column_index("matches_property"));
     objectType = objectType.substr(0, objectType.size() - strlen("_matches"));
-    return [NSString stringWithFormat:@"RLMSyncSubscription {\n\tname = %@\n\tobjectType = %@\n\tquery = %@\n\tstatus = %@\n\terror = %@\n}",
+    return [NSString stringWithFormat:@"RLMSyncSubscription {\n\tname = %@\n\tobjectType = %@\n\tquery = %@\n\tstatus = %@\n\terror = %@\n\tcreatedAt = %@\n\tupdatedAt = %@\n\texpiresAt = %@\n\ttimeToLive = %@\n}",
             self.name, RLMStringDataToNSString(objectType),
             RLMStringDataToNSString(_row.get_string(_row.get_column_index("query"))),
-            @(self.state), self.error];
+            @(self.state), self.error, self.createdAt, self.updatedAt, self.expiresAt, @(self.timeToLive)];
 }
 
 - (void)unsubscribe {
@@ -183,12 +328,22 @@ using namespace realm;
 }
 @end
 
+static ObjectSchema& addPublicNames(ObjectSchema& os) {
+    using namespace partial_sync;
+    os.property_for_name(property_created_at)->public_name    = "createdAt";
+    os.property_for_name(property_updated_at)->public_name    = "updatedAt";
+    os.property_for_name(property_expires_at)->public_name    = "expiresAt";
+    os.property_for_name(property_time_to_live)->public_name  = "timeToLive";
+    os.property_for_name(property_error_message)->public_name = "error";
+    return os;
+}
+
 // RLMClassInfo stores pointers into the schema rather than owning the objects
 // it points to, so for a ClassInfo that's not part of the schema we need a
 // wrapper object that owns them
 RLMResultsSetInfo::RLMResultsSetInfo(__unsafe_unretained RLMRealm *const realm)
-: osObjectSchema(ObjectSchema(realm->_realm->read_group(), partial_sync::result_sets_type_name))
-, rlmObjectSchema([RLMObjectSchema objectSchemaForObjectStoreSchema:osObjectSchema])
+: osObjectSchema(realm->_realm->read_group(), partial_sync::result_sets_type_name)
+, rlmObjectSchema([RLMObjectSchema objectSchemaForObjectStoreSchema:addPublicNames(osObjectSchema)])
 , info(realm, rlmObjectSchema, &osObjectSchema)
 {
     rlmObjectSchema.accessorClass = [RLMSyncSubscriptionObject class];
@@ -231,15 +386,24 @@ RLMClassInfo& RLMResultsSetInfo::get(__unsafe_unretained RLMRealm *const realm)
 
 @implementation RLMResults (SyncSubscription)
 - (RLMSyncSubscription *)subscribe {
-    return [[RLMSyncSubscription alloc] initWithName:nil results:_results realm:self.realm];
+    return [[RLMSyncSubscription alloc] initWithOptions:nil results:_results realm:self.realm];
 }
 
 - (RLMSyncSubscription *)subscribeWithName:(NSString *)subscriptionName {
-    return [[RLMSyncSubscription alloc] initWithName:subscriptionName results:_results realm:self.realm];
+    auto options = [[RLMSyncSubscriptionOptions alloc] init];
+    options.name = subscriptionName;
+    return [[RLMSyncSubscription alloc] initWithOptions:options results:_results realm:self.realm];
 }
 
 - (RLMSyncSubscription *)subscribeWithName:(NSString *)subscriptionName limit:(NSUInteger)limit {
-    return [[RLMSyncSubscription alloc] initWithName:subscriptionName results:_results.limit(limit) realm:self.realm];
+    auto options = [[RLMSyncSubscriptionOptions alloc] init];
+    options.name = subscriptionName;
+    options.limit = limit;
+    return [[RLMSyncSubscription alloc] initWithOptions:options results:_results realm:self.realm];
+}
+
+- (RLMSyncSubscription *)subscribeWithOptions:(RLMSyncSubscriptionOptions *)options {
+    return [[RLMSyncSubscription alloc] initWithOptions:options results:_results realm:self.realm];
 }
 @end
 

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist

@@ -17,11 +17,11 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.14.1</string>
+	<string>3.15.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>3.14.1</string>
+	<string>3.15.0</string>
 	<key>NSHumanReadableCopyright</key>
 	<string>Copyright © 2014 Realm. All rights reserved.</string>
 	<key>NSPrincipalClass</key>

+ 3 - 2
Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m

@@ -118,8 +118,9 @@
 
 - (void)testCompactOnLaunchFailSilently {
     if (self.isParent) {
-        [[RLMRealm defaultRealm] transactionWithBlock:^{}];
+        RLMRealm *realm  = [RLMRealm defaultRealm];
         RLMRunChildAndWait(); // runs the event loop
+        (void)[realm configuration]; // ensure the Realm stays open while the child process runs
     } else {
         unsigned long long (^fileSize)(NSString *) = ^unsigned long long(NSString *path) {
             NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
@@ -136,7 +137,7 @@
         unsigned long long sizeBefore = fileSize(config.fileURL.path);
         RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
         unsigned long long sizeAfter = fileSize(config.fileURL.path);
-        XCTAssertEqual(sizeBefore, sizeAfter);
+        XCTAssertLessThanOrEqual(sizeBefore, sizeAfter);
         XCTAssertTrue(realm.isEmpty);
         XCTAssertTrue(blockCalled);
     }

+ 13 - 50
Carthage/Checkouts/realm-cocoa/build.sh

@@ -126,7 +126,7 @@ xc() {
 }
 
 xctest() {
-  xc "$@" build
+  xc "$@" build-for-testing
   xc "$@" test
 }
 
@@ -157,11 +157,7 @@ build_combined() {
         fi
     elif [[ "$os" == "appletvos"  ]]; then
         os_name="tvos"
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
     fi
 
     # Derive build paths
@@ -227,17 +223,7 @@ move_to_clean_dir() {
 
 test_ios_static() {
     destination="$1"
-    xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' build"
-    if (( $(xcode_version_major) < 9 )); then
-        xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'"
-    fi
-
-    # Xcode's depending tracking is lacking and it doesn't realize that the Realm static framework's static library
-    # needs to be recreated when the active architectures change. Help Xcode out by removing the static library.
-    settings=$(xcode "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' -showBuildSettings")
-    path=$(echo "$settings" | awk '/CONFIGURATION_BUILD_DIR/ { cbd = $3; } /EXECUTABLE_PATH/ { ep = $3; } END { printf "%s/%s\n", cbd, ep; }')
-    rm "$path"
-
+    xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' build-for-testing"
     xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' test"
 }
 
@@ -612,19 +598,13 @@ case "$COMMAND" in
         ;;
 
     "test-ios-dynamic")
-        xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build"
-        if (( $(xcode_version_major) < 9 )); then
-            xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'"
-        fi
+        xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build-for-testing"
         xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test"
         exit 0
         ;;
 
     "test-ios-swift")
-        xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build"
-        if (( $(xcode_version_major) < 9 )); then
-            xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'"
-        fi
+        xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build-for-testing"
         xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test"
         exit 0
         ;;
@@ -648,21 +628,13 @@ case "$COMMAND" in
         ;;
 
     "test-tvos")
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
         xctest "-scheme Realm -configuration $CONFIGURATION -sdk appletvsimulator -destination 'name=$destination'"
         exit $?
         ;;
 
     "test-tvos-swift")
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
         xctest "-scheme RealmSwift -configuration $CONFIGURATION -sdk appletvsimulator -destination 'name=$destination'"
         exit $?
         ;;
@@ -766,7 +738,6 @@ case "$COMMAND" in
 
     "verify-osx")
         sh build.sh test-osx
-        sh build.sh analyze-osx
         sh build.sh examples-osx
 
         (
@@ -910,11 +881,7 @@ case "$COMMAND" in
 
     "examples-tvos")
         workspace="examples/tvos/objc/RealmExamples.xcworkspace"
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
 
         xc "-workspace $workspace -scheme DownloadCache -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
         xc "-workspace $workspace -scheme PreloadedData -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
@@ -927,12 +894,7 @@ case "$COMMAND" in
             workspace="${workspace/swift/swift-$REALM_XCODE_VERSION}"
         fi
 
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
-
+        destination="Apple TV"
         xc "-workspace $workspace -scheme DownloadCache -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
         xc "-workspace $workspace -scheme PreloadedData -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
         exit 0
@@ -1228,7 +1190,7 @@ EOM
 
     package-*-swift)
         PLATFORM=$(echo $COMMAND | cut -d - -f 2)
-        for version in 9.2 9.3 9.4 10.0 10.1 10.2; do
+        for version in 9.2 9.3 9.4 10.0 10.1 10.2.1; do
             REALM_XCODE_VERSION=$version
             REALM_SWIFT_VERSION=
             set_xcode_and_swift_versions
@@ -1237,7 +1199,7 @@ EOM
         done
 
         cd build/$PLATFORM
-        zip --symlinks -r realm-swift-framework-$PLATFORM.zip swift-9.2 swift-9.2 swift-9.4 swift-10.0 swift-10.1 swift-10.2
+        zip --symlinks -r realm-swift-framework-$PLATFORM.zip swift-9.2 swift-9.2 swift-9.4 swift-10.0 swift-10.1 swift-10.2.1
         ;;
 
     package-*-swift-*)
@@ -1441,8 +1403,9 @@ x.y.z Release notes (yyyy-MM-dd)
 
 ### Compatibility
 * File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
-* Realm Object Server: 3.11.0 or later.
+* Realm Object Server: 3.21.0 or later.
 * APIs are backwards compatible with all previous releases in the 3.x.y series.
+* Carthage release for Swift is built with Xcode 10.2.1.
 EOS)
         changelog=$(cat CHANGELOG.md)
         echo "$empty_section" > CHANGELOG.md

+ 4 - 4
Carthage/Checkouts/realm-cocoa/dependencies.list

@@ -1,4 +1,4 @@
-VERSION=3.14.1
-REALM_CORE_VERSION=5.14.0
-REALM_SYNC_VERSION=3.15.1
-REALM_OBJECT_SERVER_VERSION=3.13.1
+VERSION=3.15.0
+REALM_CORE_VERSION=5.19.1
+REALM_SYNC_VERSION=4.4.2
+REALM_OBJECT_SERVER_VERSION=3.21.1