diff --git a/.github/workflows/pr-realm-js.yml b/.github/workflows/pr-realm-js.yml index 47c8c1b0b9..760c762e8c 100644 --- a/.github/workflows/pr-realm-js.yml +++ b/.github/workflows/pr-realm-js.yml @@ -67,26 +67,6 @@ jobs: if: ${{ runner.os == 'Windows' }} uses: ilammy/msvc-dev-cmd@v1 - - name: Get vcpkg submodule commit sha - if: ${{ runner.os == 'Windows' }} - id: vcpkg_cache_key - working-directory: vendor/realm-core/tools/vcpkg/ports - shell: bash - run: echo "::set-output name=commit::$(git rev-parse HEAD)" - - - name: Setup Vcpkg - if: ${{ runner.os == 'Windows' }} - uses: friendlyanon/setup-vcpkg@v1 - with: - path: vendor/realm-core/tools/vcpkg/ports - cache-key: vcpkg-windows-${{ matrix.variant.arch }}-${{ steps.vcpkg_cache_key.outputs.commit }}-${{ hashFiles('./vendor/realm-core/tools/vcpkg/vcpkg.json') }} - cache-restore-keys: vcpkg-windows-${{ matrix.variant.arch }}-${{ steps.vcpkg_cache_key.outputs.commit }}-${{ hashFiles('./vendor/realm-core/tools/vcpkg/vcpkg.json') }} - - - name: Refetch Vcpkg - if: ${{ runner.os == 'Windows' }} - run: git fetch --unshallow - working-directory: vendor/realm-core/tools/vcpkg/ports - # ninja-build is used by default if available and results in faster build times # On linux, electron requires a connected display. We fake this by giving it a headless environment using xvfb # Relevant issue: https://github.com/juliangruber/browser-run/issues/147 diff --git a/CHANGELOG.md b/CHANGELOG.md index 07ee5a3db0..e36a4a9b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ ## vNext (TBD) ### Enhancements -* None +* Converting flexible sync Realms to bundled and local realms is now supported. ([realm/realm-core#6076](https://github.com/realm/realm-core/pull/6076)) ### Fixed -* ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?) -* None +* Fixed possible segfault in sync client where async callback was using object after being deallocated. ([realm/realm-core#6053](https://github.com/realm/realm-core/issues/6053), since v10.11.0) +* Fixed crash when using client reset with recovery and flexible sync with a single subscription ([#6070](https://github.com/realm/realm-core/issues/6070), since v10.19.5) ### Compatibility * React Native >= v0.70.0 @@ -14,12 +14,11 @@ * File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms). ### Internal -* Unpin Xcode version when building locally and upgrade the Xcode version used by GHA. +* Upgraded Realm Core from v13.1.1 to v13.2.0. ([#5174](https://github.com/realm/realm-js/issues/5174) and [#5244](https://github.com/realm/realm-js/issues/5244)) +* Unpin Xcode version when building locally and upgrade the Xcode version used by Github Actions. * Enable tests for notifications on dictionary. -* Automate releasing package on GHA - - - +* Automate releasing package on Github Actions. +* Upgrade OpenSSL v1.1.1n to v3.0.7. ([realm/realm-core#6097](https://github.com/realm/realm-core/pull/6097)) ## 11.4.0 (2023-01-23) @@ -476,7 +475,7 @@ realm.write(() => { ### Internal * Updated ccache build scripts to be location agnostic. ([#4764](https://github.com/realm/realm-js/pull/4764)) -* Upgraded Realm Core from v12.3.0 to v12.5.1. ([#4753](https://github.com/realm/realm-js/issues/4753 and [[#4763](https://github.com/realm/realm-js/issues/4763)) +* Upgraded Realm Core from v12.3.0 to v12.5.1. ([#4753](https://github.com/realm/realm-js/issues/4753) and [[#4763](https://github.com/realm/realm-js/issues/4763)) * Upgraded React Native integration tests app to React Native v0.68.2. ([#4583](https://github.com/realm/realm-js/pull/4583)) * Upgrading `react-native-fs` to avoid a peer dependency failure. ([#4709](https://github.com/realm/realm-js/pull/4709)) * Upgraded React Native integration tests app to React Native v0.69.1. ([#4713](https://github.com/realm/realm-js/pull/4713)) diff --git a/CMakeLists.txt b/CMakeLists.txt index 298d4cc50f..e6b63d5a0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,6 @@ include(CheckCXXCompilerFlag) # compiling for Node.js, need to set up toolchains before project() call if(DEFINED CMAKE_JS_VERSION) if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/vendor/realm-core/tools/vcpkg/ports/scripts/buildsystems/vcpkg.cmake") - set(VCPKG_MANIFEST_DIR "${CMAKE_SOURCE_DIR}/vendor/realm-core/tools/vcpkg") - if(NODE_ARCH STREQUAL "ia32") set(VCPKG_TARGET_TRIPLET "x86-windows-static" CACHE STRING "") elseif(NODE_ARCH STREQUAL "x64") diff --git a/dependencies.list b/dependencies.list index dff095c62f..724df8560b 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js VERSION=11.4.0 -REALM_CORE_VERSION=13.1.2 +REALM_CORE_VERSION=13.2.0 NAPI_VERSION=5 MDBREALM_TEST_SERVER_TAG=2022-06-10 diff --git a/lib/utils.js b/lib/utils.js index 970c002b20..df26f58ca2 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -134,29 +134,76 @@ module.exports = { }, /** + * + * References: + * - https://github.com/facebook/react-native/blob/main/Libraries/Utilities/Platform.ios.js + * - https://github.com/facebook/react-native/blob/main/Libraries/Utilities/NativePlatformConstantsAndroid.js + * * @returns An object with names and versions of the various components making up the context. */ getVersions() { const packageJson = require("../package.json"); - const packageVersion = packageJson.version; + const sdkVersion = packageJson.version; const environment = this.getEnvironment(); + const sdk = "JS"; + try { if (environment === "reactnative") { const { Platform } = require("react-native"); + let deviceName = "unknown"; + let deviceVersion = "unknown"; + if (Platform.OS === "ios") { + if (Platform.isPad()) { + deviceName = "iPad"; + } else if (Platform.isTV()) { + deviceName = "AppleTV"; + } else { + // RN doesn't support Apple Watch + deviceName = "iPhone"; + } + deviceVersion = "unknown"; + } else if (Platform.OS === "android") { + deviceName = `${Platform.constants.Manufacturer}:${Platform.constants.Brand}`; + deviceVersion = `${Platform.Model}`; + } + return { - packageVersion, - platformContext: environment, - platformOs: Platform.OS, + sdk, + sdkVersion, + + platform: Platform.OS, // Android reports a number ... platformVersion: `${Platform.Version}`, + + deviceName, + deviceVersion, + + cpuArch: "unknown", // Detecting CPU architecture on Android and iOS is done by seperate methods in platform.{mm, cpp) + + frameworkName: "react-native", + frameworkVersion: Object.values(Platform.constants.reactNativeVersion).join("."), }; } else if (environment === "node.js" || environment === "electron") { + const frameworkName = environment.chatAt(0).toUpperCase() + environment.slice(1); + const platform = os.type(); // eslint-disable-line + const platformVersion = os.release(); // eslint-disable-line + const cpuArch = os.arch(); // eslint-disable-line + return { - packageVersion, - platformContext: environment, - platformOs: process.platform, - platformVersion: process.versions.electron || process.version, + sdk, + sdkVersion, + + platform, + platformVersion, + + deviceName: "unknown", + deviceVersion: "unknown", + + cpuArch, + + frameworkName, + frameworkVersion: process.versions.electron || process.version, }; } } catch (err) { @@ -164,10 +211,15 @@ module.exports = { } return { - packageVersion, - platformContext: environment, - platformOs: "unknown", + platform: "unknown", platformVersion: "?.?.?", + sdkVersion: "?.?.?", + sdk: "unknown", + cpuArch: "unknown", + deviceName: "unknown", + deviceVersion: "?.?.?", + frameworkName: "unknown", + frameworkVersion: "?.?.?", }; }, }; diff --git a/src/android/CMakeLists.txt b/src/android/CMakeLists.txt index 308e570716..ab9563f725 100644 --- a/src/android/CMakeLists.txt +++ b/src/android/CMakeLists.txt @@ -100,6 +100,7 @@ if(REALM_JS_BUILD_CORE_FROM_SOURCE AND TARGET ObjectStore) target_compile_definitions(ObjectStore PUBLIC REALM_PLATFORM=Android REALM_ANDROID=1 + REALM_ANDROID_ABI=${ANDROID_ABI} ) endif() diff --git a/src/android/platform.cpp b/src/android/platform.cpp index cc0c126325..d1079a7485 100644 --- a/src/android/platform.cpp +++ b/src/android/platform.cpp @@ -114,4 +114,20 @@ void print(const char* fmt, ...) __android_log_vprint(ANDROID_LOG_INFO, "RealmJS", fmt, vl); va_end(vl); } + +std::string get_cpu_arch() +{ +#if defined(__arm__) + return "armeabi-v7a"; +#elif defined(__aarch64__) + return "arm64-v8a"; +#elif defined(__i386__) + return "x86"; +#elif defined(__x86_64__) + return "x86_64"; +#else + return "unknown"; +#endif +} + } // namespace realm diff --git a/src/ios/platform.mm b/src/ios/platform.mm index ebf674fa1e..72e15affd9 100644 --- a/src/ios/platform.mm +++ b/src/ios/platform.mm @@ -20,17 +20,19 @@ #include -#include #include #include +#include #import +#include +#include static NSString *error_description(NSError *error) { - if (NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]) { - return underlyingError.localizedDescription; - } - return error.localizedDescription; + if (NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]) { + return underlyingError.localizedDescription; + } + return error.localizedDescription; } namespace realm { @@ -151,15 +153,33 @@ void remove_directory(const std::string &path) remove_file(path); // works for directories too } - -void print(const char* fmt, ...) -{ - va_list vl; - va_start(vl, fmt); - std::string format(fmt); - format.append("\n"); - vprintf(format.c_str(), vl); - va_end(vl); +void print(const char *fmt, ...) { + va_list vl; + va_start(vl, fmt); + std::string format(fmt); + format.append("\n"); + vprintf(format.c_str(), vl); + va_end(vl); } +std::string get_cpu_arch() { + std::size_t size; + cpu_type_t type; + size = sizeof(type); + sysctlbyname("hw.cputype", &type, &size, NULL, 0); + + // values for cputype and cpusubtype defined in mach/machine.h + switch (type) { + case CPU_TYPE_X86: + return "x86"; + case CPU_TYPE_X86_64: + return "x86_64"; + case CPU_TYPE_ARM: + return "armeabi-armv7"; + case CPU_TYPE_ARM64: + return "arm64"; + default: + return "unknown"; + } +} } diff --git a/src/js_app.hpp b/src/js_app.hpp index abc88f51ea..5ef5661286 100644 --- a/src/js_app.hpp +++ b/src/js_app.hpp @@ -27,6 +27,7 @@ #include +#include "platform.hpp" #include "js_notifications.hpp" #include "js_user.hpp" #include "js_app_credentials.hpp" @@ -34,6 +35,7 @@ #include "js_email_password_auth.hpp" #include "realm/object-store/sync/subscribable.hpp" + using SharedApp = std::shared_ptr; using SharedUser = std::shared_ptr; using AppToken = realm::Subscribable::Token; @@ -89,11 +91,16 @@ class AppClass : public ClassDefinition> { return std::make_unique(ctx, std::move(eld)); }; - // These values are overridden at runtime - static inline std::string package_version = "?.?.?"; - static inline std::string platform_context = "unknown-context"; - static inline std::string platform_os = "unknown-os"; + // These values are overridden at runtime - from app.hpp + static inline std::string platform = "unknown"; static inline std::string platform_version = "?.?.?"; + static inline std::string sdk_version = "?.?.?"; + static inline std::string sdk = "unknown"; + static inline std::string cpu_arch = "unknown"; + static inline std::string device_name = "unknown"; + static inline std::string device_version = "?.?.?"; + static inline std::string framework_name = "unknown"; + static inline std::string framework_version = "?.?.?"; static void constructor(ContextType, ObjectType, Arguments&); static FunctionType create_constructor(ContextType); @@ -221,9 +228,15 @@ void AppClass::constructor(ContextType ctx, ObjectType this_object, Arguments config.transport = AppClass::transport_generator(Protected(Context::get_global_context(ctx)), NetworkTransport::make_dispatcher()); - config.platform = platform_os; - config.platform_version = platform_version; - config.sdk_version = "RealmJS/" + package_version; + config.device_info.platform = platform; + config.device_info.platform_version = platform_version; + config.device_info.sdk = sdk; + config.device_info.sdk_version = sdk_version; + config.device_info.cpu_arch = cpu_arch; + config.device_info.device_name = device_name; + config.device_info.device_version = device_version; + config.device_info.framework_name = framework_name; + config.device_info.framework_version = framework_version; auto realm_file_directory = default_realm_file_directory(); ensure_directory_exists_for_file(realm_file_directory); @@ -241,8 +254,7 @@ void AppClass::constructor(ContextType ctx, ObjectType this_object, Arguments template std::string AppClass::get_user_agent() { - return "RealmJS/" + package_version + " (" + platform_context + ", " + platform_os + ", v" + platform_version + - ")"; + return "RealmJS/" + sdk_version + " (" + platform + ", v" + platform_version + ")"; } template @@ -380,11 +392,23 @@ void AppClass::set_versions(ContextType ctx, ObjectType this_object, Argument { args.validate_count(1); auto versions = Value::validated_to_object(ctx, args[0]); - AppClass::package_version = Object::validated_get_string(ctx, versions, "packageVersion"); - AppClass::platform_context = Object::validated_get_string(ctx, versions, "platformContext"); - AppClass::platform_os = Object::validated_get_string(ctx, versions, "platformOs"); + + AppClass::platform = Object::validated_get_string(ctx, versions, "platform"); AppClass::platform_version = Object::validated_get_string(ctx, versions, "platformVersion"); + AppClass::sdk = Object::validated_get_string(ctx, versions, "sdk"); + AppClass::sdk_version = Object::validated_get_string(ctx, versions, "sdkVersion"); + AppClass::cpu_arch = Object::validated_get_string(ctx, versions, "cpuArch"); + AppClass::device_name = Object::validated_get_string(ctx, versions, "deviceName"); + AppClass::device_version = Object::validated_get_string(ctx, versions, "deviceVersion"); + AppClass::framework_name = Object::validated_get_string(ctx, versions, "frameworkName"); + AppClass::framework_version = Object::validated_get_string(ctx, versions, "frameworkVersion"); + + // we are likely on iOS or Android + if (AppClass::cpu_arch == "unknown") { + AppClass::cpu_arch = get_cpu_arch(); + } } + /** * @brief Registers an event listener on the SharedApp that fires on various app events. * This includes login, logout, switching users, linking users and refreshing custom data. diff --git a/src/js_sync.hpp b/src/js_sync.hpp index af1f92882a..2c573031bf 100644 --- a/src/js_sync.hpp +++ b/src/js_sync.hpp @@ -45,7 +45,7 @@ #include #include -#include +#include #include #if REALM_PLATFORM_NODE @@ -495,7 +495,7 @@ class SSLVerifyCallbackSyncThreadFunctor { } // This function is called on the sync client's event loop thread. - bool operator()(const std::string& server_address, util::network::Endpoint::port_type server_port, + bool operator()(const std::string& server_address, sync::network::Endpoint::port_type server_port, const char* pem_data, size_t pem_size, int preverify_ok, int depth) { const std::string pem_certificate{pem_data, pem_size}; @@ -525,7 +525,7 @@ class SSLVerifyCallbackSyncThreadFunctor { // main_loop_handler calls the user callback (m_func) and sends the return value // back to the sync client's event loop thread through a condition variable. static void main_loop_handler(SSLVerifyCallbackSyncThreadFunctor* this_object, - const std::string& server_address, util::network::Endpoint::port_type server_port, + const std::string& server_address, sync::network::Endpoint::port_type server_port, const std::string& pem_certificate, int preverify_ok, int depth) { const Protected& ctx = this_object->m_ctx; @@ -562,7 +562,7 @@ class SSLVerifyCallbackSyncThreadFunctor { const Protected m_ctx; const Protected m_func; util::EventLoopDispatcher* this_object, - const std::string& server_address, util::network::Endpoint::port_type server_port, + const std::string& server_address, sync::network::Endpoint::port_type server_port, const std::string& pem_certificate, int preverify_ok, int depth)> m_event_loop_dispatcher; bool m_ssl_certificate_callback_done = false; diff --git a/src/node/platform.cpp b/src/node/platform.cpp index 4642fd3ce0..c05e6e04f6 100644 --- a/src/node/platform.cpp +++ b/src/node/platform.cpp @@ -208,4 +208,10 @@ void print(const char* fmt, ...) va_end(vl); } +// this should never be called +std::string get_cpu_arch() +{ + return "unknown"; +} + } // namespace realm diff --git a/src/platform.hpp b/src/platform.hpp index f4c87e3a25..ffea18ee7c 100644 --- a/src/platform.hpp +++ b/src/platform.hpp @@ -50,4 +50,7 @@ void remove_directory(const std::string& path); // print something void print(const char* fmt, ...); +// the CPU architecture +std::string get_cpu_arch(); + } // namespace realm diff --git a/tests/js/session-tests.js b/tests/js/session-tests.js index 7235e889a5..c5d062c8d6 100644 --- a/tests/js/session-tests.js +++ b/tests/js/session-tests.js @@ -1465,7 +1465,7 @@ module.exports = { }, "'sync' property must be an object"); TestCase.assertThrowsContaining(() => { realm.writeCopyTo({ path: "output", sync: { flexible: true, user } }); - }, "Realm cannot be converted if flexible sync is enabled"); + }, "Realm cannot be converted to a flexible sync realm unless flexible sync is already enabled"); /* * Test 2: check that `writeCopyTo` can only be called at the right time */ diff --git a/vendor/realm-core b/vendor/realm-core index ce2fc5eac8..1ad79b24e4 160000 --- a/vendor/realm-core +++ b/vendor/realm-core @@ -1 +1 @@ -Subproject commit ce2fc5eac8ae4c65fb0a8c067f1704fab5f286ef +Subproject commit 1ad79b24e4f460ddf9e04275b70534817af3fb42