From 4c1eaf8ac481f50ce9d98b011dfb6045636203c0 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Mon, 24 Sep 2018 17:41:58 +0300 Subject: [PATCH] upgrade realm-js to 2.16.1 --- ci/mobile.groovy | 1 - mobile_files/package-lock.json | 71 +- mobile_files/package.json | 4 +- patches/js_realm.hpp | 1193 -------------------------------- 4 files changed, 49 insertions(+), 1220 deletions(-) delete mode 100644 patches/js_realm.hpp diff --git a/ci/mobile.groovy b/ci/mobile.groovy index 4e754039a7..d11336f5c3 100644 --- a/ci/mobile.groovy +++ b/ci/mobile.groovy @@ -48,7 +48,6 @@ def prep(type = 'nightly') { sh 'cp .env.jenkins .env'; break } common.installJSDeps('mobile') - sh 'cp patches/js_realm.hpp node_modules/realm/src/js_realm.hpp' /* install ruby dependencies */ sh 'bundle install --quiet' /* install Maven dependencies */ diff --git a/mobile_files/package-lock.json b/mobile_files/package-lock.json index ea418ec8ce..de33cc0011 100644 --- a/mobile_files/package-lock.json +++ b/mobile_files/package-lock.json @@ -2384,9 +2384,9 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" }, "cipher-base": { "version": "1.0.4", @@ -2537,9 +2537,9 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { "delayed-stream": "1.0.0" } @@ -2776,7 +2776,7 @@ "requires": { "file-type": "5.2.0", "is-stream": "1.1.0", - "tar-stream": "1.6.1" + "tar-stream": "1.6.2" } }, "decompress-tarbz2": { @@ -2788,7 +2788,7 @@ "file-type": "6.2.0", "is-stream": "1.1.0", "seek-bzip": "1.0.5", - "unbzip2-stream": "1.2.5" + "unbzip2-stream": "1.3.0" }, "dependencies": { "file-type": { @@ -3154,6 +3154,14 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "eth-phishing-detect": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/eth-phishing-detect/-/eth-phishing-detect-1.1.13.tgz", + "integrity": "sha512-1KQcKvAQIjJgFMVwxaw2+BlzM9Momzl0e+/torPdMjg7WGq6LmCIS7ddg84diH5zIQp9quGyRVIEawCCuErgVQ==", + "requires": { + "fast-levenshtein": "2.0.6" + } + }, "event-target-shim": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-1.1.1.tgz", @@ -3272,6 +3280,11 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, "fb-watchman": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", @@ -3438,6 +3451,16 @@ "asynckit": "0.4.0", "combined-stream": "1.0.6", "mime-types": "2.1.20" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + } } }, "fragment-cache": { @@ -5610,9 +5633,9 @@ } }, "needle": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.2.tgz", - "integrity": "sha512-mW7W8dKuVYefCpNzE3Z7xUmPI9wSrSL/1qH31YGMxmSOAnjatS3S9Zv3cmiHrhx3Jkp1SrWWBdOFXjfF48Uq3A==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", + "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "requires": { "debug": "2.6.9", "iconv-lite": "0.4.23", @@ -5668,7 +5691,7 @@ "requires": { "detect-libc": "1.0.3", "mkdirp": "0.5.1", - "needle": "2.2.2", + "needle": "2.2.4", "nopt": "4.0.1", "npm-packlist": "1.1.11", "npmlog": "4.1.2", @@ -6412,7 +6435,7 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, "react-native": { - "version": "github:status-im/react-native#8f592d9c1e52fc0d5623f38d21426b83db39f3c3", + "version": "github:status-im/react-native#aa51c6e7a17776f7277f7f2124467fc0d41d6841", "requires": { "absolute-path": "0.0.0", "art": "0.10.3", @@ -6931,9 +6954,9 @@ } }, "realm": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/realm/-/realm-2.15.3.tgz", - "integrity": "sha512-F1wIYI8YTc3fJQnHtr+QFZKHyezszFQApdOildtyZZl8HAn+kRWnINEl/iasbkw4SaQGTzWT4cMMYcCEBNzS/A==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/realm/-/realm-2.16.1.tgz", + "integrity": "sha512-OoN1SVu0BtiKkU6svEEr9/twfCIdVjq98lWXASccGL8Qm4DLhu0NUTP0W5Iv5Rb5jjgiwYGWghPD6yoQu2143A==", "requires": { "command-line-args": "4.0.7", "decompress": "4.2.0", @@ -7094,7 +7117,7 @@ "aws-sign2": "0.7.0", "aws4": "1.8.0", "caseless": "0.12.0", - "combined-stream": "1.0.6", + "combined-stream": "1.0.7", "extend": "3.0.2", "forever-agent": "0.6.1", "form-data": "2.3.2", @@ -8095,7 +8118,7 @@ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.6.tgz", "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", "requires": { - "chownr": "1.0.1", + "chownr": "1.1.1", "fs-minipass": "1.2.5", "minipass": "2.3.4", "minizlib": "1.1.0", @@ -8112,9 +8135,9 @@ } }, "tar-stream": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", - "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "requires": { "bl": "1.2.2", "buffer-alloc": "1.2.0", @@ -8393,9 +8416,9 @@ "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" }, "unbzip2-stream": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", - "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.0.tgz", + "integrity": "sha512-kE2WkurNnPUMcryNioS68DDbhoPB8Qxsd8btHSj+sd5Pjh2GsjmeHLzMSqV9HHziAo8FzVxVCJl9ZYhk7yY1pA==", "requires": { "buffer": "3.6.0", "through": "2.3.8" diff --git a/mobile_files/package.json b/mobile_files/package.json index c77901d9e9..e0de32d709 100644 --- a/mobile_files/package.json +++ b/mobile_files/package.json @@ -53,6 +53,7 @@ "react-native-os": "https://github.com/status-im/react-native-os.git#1.1.0-1", "react-native-qrcode": "0.2.7", "react-native-randombytes": "3.5.0", + "react-native-safe-area-view": "0.9.0", "react-native-securerandom": "https://github.com/status-im/react-native-securerandom#0.1.1-1", "react-native-splash-screen": "3.1.1", "react-native-svg": "6.5.2", @@ -61,8 +62,7 @@ "react-native-udp": "https://github.com/status-im/react-native-udp.git#2.3.1-1", "react-native-webview-bridge": "git+https://github.com/status-im/react-native-webview-bridge.git#0.33.16-1", "react-navigation": "^2.12.1", - "react-native-safe-area-view": "0.9.0", - "realm": "2.15.3", + "realm": "2.16.1", "rn-snoopy": "https://github.com/status-im/rn-snoopy.git", "string_decoder": "0.10.31", "text-encoding": "^0.6.4", diff --git a/patches/js_realm.hpp b/patches/js_realm.hpp deleted file mode 100644 index 6e22ded64e..0000000000 --- a/patches/js_realm.hpp +++ /dev/null @@ -1,1193 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include -#include -#include - -#include "js_class.hpp" -#include "js_types.hpp" -#include "js_util.hpp" -#include "js_realm_object.hpp" -#include "js_list.hpp" -#include "js_results.hpp" -#include "js_schema.hpp" -#include "js_observable.hpp" - -#if REALM_ENABLE_SYNC -#include "js_sync.hpp" -#include "sync/sync_config.hpp" -#include "sync/sync_manager.hpp" -#endif - -#include "shared_realm.hpp" -#include "binding_context.hpp" -#include "object_accessor.hpp" -#include "platform.hpp" -#include "results.hpp" - -#include - -namespace realm { -namespace js { - -static std::string normalize_realm_path(std::string path) { -#if defined(WIN32) && WIN32 - if (path.size() > 1 && path[0] != '\\' && path[1] != ':') { - path = default_realm_file_directory() + "\\" + path; - } - std::replace(path.begin(), path.end(), '/', '\\'); -#else - if (path.size() && path[0] != '/' && path[0] != '.') { - path = default_realm_file_directory() + "/" + path; - } -#endif - return path; -} - -template -class RealmClass; - -template -class RealmDelegate : public BindingContext { - public: - using GlobalContextType = typename T::GlobalContext; - using FunctionType = typename T::Function; - using ObjectType = typename T::Object; - using ValueType = typename T::Value; - using Value = js::Value; - - using ObjectDefaultsMap = typename Schema::ObjectDefaultsMap; - using ConstructorMap = typename Schema::ConstructorMap; - - virtual void did_change(std::vector const& observers, std::vector const& invalidated, bool version_changed) { - notify("change"); - } - - virtual void schema_did_change(realm::Schema const& schema) { - schema_notify("schema", schema); - } - - RealmDelegate(std::weak_ptr realm, GlobalContextType ctx) : m_context(ctx), m_realm(realm) {} - - ~RealmDelegate() { - // All protected values need to be unprotected while the context is retained. - m_defaults.clear(); - m_constructors.clear(); - m_notifications.clear(); - m_schema_notifications.clear(); - } - - void add_notification(FunctionType notification) { - for (auto &handler : m_notifications) { - if (handler == notification) { - return; - } - } - m_notifications.emplace_back(m_context, notification); - } - - void remove_notification(FunctionType notification) { - for (auto iter = m_notifications.begin(); iter != m_notifications.end(); ++iter) { - if (*iter == notification) { - m_notifications.erase(iter); - return; - } - } - } - - void remove_all_notifications() { - m_notifications.clear(); - } - - void add_schema_notification(FunctionType notification) { - SharedRealm realm = m_realm.lock(); - realm->read_group(); // to get the schema change handler going - for (auto &handler : m_schema_notifications) { - if (handler == notification) { - return; - } - } - m_schema_notifications.emplace_back(m_context, notification); - } - - void remove_schema_notification(FunctionType notification) { - for (auto iter = m_schema_notifications.begin(); iter != m_schema_notifications.end(); ++iter) { - if (*iter == notification) { - m_schema_notifications.erase(iter); - return; - } - } - } - - void remove_all_schema_notifications() { - m_schema_notifications.clear(); - } - - ObjectDefaultsMap m_defaults; - ConstructorMap m_constructors; - - private: - Protected m_context; - std::list> m_notifications; - std::list> m_schema_notifications; - std::weak_ptr m_realm; - - void notify(const char *notification_name) { - HANDLESCOPE - - SharedRealm realm = m_realm.lock(); - if (!realm) { - throw std::runtime_error("Realm no longer exists"); - } - - ObjectType realm_object = create_object>(m_context, new SharedRealm(realm)); - ValueType arguments[] = {realm_object, Value::from_string(m_context, notification_name)}; - - std::list> notifications_copy(m_notifications); - for (auto &callback : notifications_copy) { - Function::callback(m_context, callback, realm_object, 2, arguments); - } - } - - void schema_notify(const char *notification_name, realm::Schema const& schema) { - HANDLESCOPE - - SharedRealm realm = m_realm.lock(); - if (!realm) { - throw std::runtime_error("Realm no longer exists"); - } - - ObjectType realm_object = create_object>(m_context, new SharedRealm(realm)); - ObjectType schema_object = Schema::object_for_schema(m_context, schema); - ValueType arguments[] = {realm_object, Value::from_string(m_context, notification_name), schema_object}; - - std::list> notifications_copy(m_schema_notifications); - for (auto &callback : notifications_copy) { - Function::callback(m_context, callback, realm_object, 3, arguments); - } - } - - friend class RealmClass; -}; - -std::string default_path(); -void set_default_path(std::string path); -void delete_all_realms(); -void clear_test_state(); - -template -class RealmClass : public ClassDefinition> { - using GlobalContextType = typename T::GlobalContext; - using ContextType = typename T::Context; - using FunctionType = typename T::Function; - using ObjectType = typename T::Object; - using ValueType = typename T::Value; - using Arguments = js::Arguments; - using String = js::String; - using Object = js::Object; - using Value = js::Value; - using ReturnValue = js::ReturnValue; - using NativeAccessor = realm::js::NativeAccessor; - -public: - using ObjectDefaultsMap = typename Schema::ObjectDefaultsMap; - using ConstructorMap = typename Schema::ConstructorMap; - - using WaitHandler = void(std::error_code); - using ProgressHandler = void(uint64_t transferred_bytes, uint64_t transferrable_bytes); - - - static FunctionType create_constructor(ContextType); - - // methods - static void objects(ContextType, ObjectType, Arguments, ReturnValue &); - static void object_for_primary_key(ContextType, ObjectType, Arguments, ReturnValue &); - static void create(ContextType, ObjectType, Arguments, ReturnValue &); - static void delete_one(ContextType, ObjectType, Arguments, ReturnValue &); - static void delete_all(ContextType, ObjectType, Arguments, ReturnValue &); - static void write(ContextType, ObjectType, Arguments, ReturnValue &); - static void begin_transaction(ContextType, ObjectType, Arguments, ReturnValue&); - static void commit_transaction(ContextType, ObjectType, Arguments, ReturnValue&); - static void cancel_transaction(ContextType, ObjectType, Arguments, ReturnValue&); - static void add_listener(ContextType, ObjectType, Arguments, ReturnValue &); - static void wait_for_download_completion(ContextType, ObjectType, Arguments, ReturnValue &); - static void remove_listener(ContextType, ObjectType, Arguments, ReturnValue &); - static void remove_all_listeners(ContextType, ObjectType, Arguments, ReturnValue &); - static void close(ContextType, ObjectType, Arguments, ReturnValue &); - static void compact(ContextType, ObjectType, Arguments, ReturnValue &); - static void writeCopyTo(ContextType, ObjectType, Arguments, ReturnValue &); - static void delete_model(ContextType, ObjectType, Arguments, ReturnValue &); - static void object_for_object_id(ContextType, ObjectType, Arguments, ReturnValue&); - static void privileges(ContextType, ObjectType, Arguments, ReturnValue&); - - // properties - static void get_empty(ContextType, ObjectType, ReturnValue &); - static void get_path(ContextType, ObjectType, ReturnValue &); - static void get_schema_version(ContextType, ObjectType, ReturnValue &); - static void get_schema(ContextType, ObjectType, ReturnValue &); - static void get_in_memory(ContextType, ObjectType, ReturnValue &); - static void get_read_only(ContextType, ObjectType, ReturnValue &); - static void get_is_in_transaction(ContextType, ObjectType, ReturnValue &); - static void get_is_closed(ContextType, ObjectType, ReturnValue &); -#if REALM_ENABLE_SYNC - static void get_sync_session(ContextType, ObjectType, ReturnValue &); -#endif - - // static methods - static void constructor(ContextType, ObjectType, size_t, const ValueType[]); - static SharedRealm create_shared_realm(ContextType, realm::Realm::Config, bool, ObjectDefaultsMap &&, ConstructorMap &&); - - static void schema_version(ContextType, ObjectType, Arguments, ReturnValue &); - static void clear_test_state(ContextType, ObjectType, Arguments, ReturnValue &); - static void copy_bundled_realm_files(ContextType, ObjectType, Arguments, ReturnValue &); - static void delete_file(ContextType, ObjectType, Arguments, ReturnValue &); - - // static properties - static void get_default_path(ContextType, ObjectType, ReturnValue &); - static void set_default_path(ContextType, ObjectType, ValueType value); - - std::string const name = "Realm"; - - MethodMap const static_methods = { - {"schemaVersion", wrap}, - {"clearTestState", wrap}, - {"copyBundledRealmFiles", wrap}, - {"deleteFile", wrap}, - }; - - PropertyMap const static_properties = { - {"defaultPath", {wrap, wrap}}, - }; - - MethodMap const methods = { - {"objects", wrap}, - {"objectForPrimaryKey", wrap}, - {"create", wrap}, - {"delete", wrap}, - {"deleteAll", wrap}, - {"write", wrap}, - {"beginTransaction", wrap}, - {"commitTransaction", wrap}, - {"cancelTransaction", wrap}, - {"addListener", wrap}, - {"removeListener", wrap}, - {"removeAllListeners", wrap}, - {"close", wrap}, - {"compact", wrap}, - {"writeCopyTo", wrap}, - {"deleteModel", wrap}, - {"privileges", wrap}, - {"_objectForObjectId", wrap}, - #if REALM_ENABLE_SYNC - {"_waitForDownload", wrap}, - #endif - }; - - PropertyMap const properties = { - {"empty", {wrap, nullptr}}, - {"path", {wrap, nullptr}}, - {"schemaVersion", {wrap, nullptr}}, - {"schema", {wrap, nullptr}}, - {"inMemory", {wrap, nullptr}}, - {"readOnly", {wrap, nullptr}}, - {"isInTransaction", {wrap, nullptr}}, - {"isClosed", {wrap, nullptr}}, -#if REALM_ENABLE_SYNC - {"syncSession", {wrap, nullptr}}, -#endif - }; - - private: - static void handleRealmFileException(ContextType ctx, realm::Realm::Config config, const RealmFileException& ex) { - switch (ex.kind()) { - case RealmFileException::Kind::IncompatibleSyncedRealm: { - ObjectType configuration = Object::create_empty(ctx); - Object::set_property(ctx, configuration, "path", Value::from_string(ctx, ex.path())); - Object::set_property(ctx, configuration, "readOnly", Value::from_boolean(ctx, true)); - if (!config.encryption_key.empty()) { - Object::set_property(ctx, configuration, "encryption_key", Value::from_binary(ctx, BinaryData(&config.encryption_key[0], 64))); - } - - ObjectType object = Object::create_empty(ctx); - Object::set_property(ctx, object, "name", Value::from_string(ctx, "IncompatibleSyncedRealmError")); - Object::set_property(ctx, object, "configuration", configuration); - throw Exception(ctx, object); - } - default: - throw; - } - } - - static std::string validated_notification_name(ContextType ctx, const ValueType &value) { - std::string name = Value::validated_to_string(ctx, value, "notification name"); - if (name == "change" || name == "schema") { - return name; - } - throw std::runtime_error("Only the 'change' and 'schema' notification names are supported."); - } - - static const ObjectSchema& validated_object_schema_for_value(ContextType ctx, const SharedRealm &realm, const ValueType &value) { - std::string object_type; - if (Value::is_constructor(ctx, value)) { - FunctionType constructor = Value::to_constructor(ctx, value); - - auto delegate = get_delegate(realm.get()); - for (auto &pair : delegate->m_constructors) { - if (FunctionType(pair.second) == constructor) { - object_type = pair.first; - break; - } - } - - if (object_type.empty()) { - throw std::runtime_error("Constructor was not registered in the schema for this Realm"); - } - } - else { - object_type = Value::validated_to_string(ctx, value, "objectType"); - if (object_type.empty()) { - throw std::runtime_error("objectType cannot be empty"); - } - } - - auto &schema = realm->schema(); - auto object_schema = schema.find(object_type); - - if (object_schema == schema.end()) { - throw std::runtime_error("Object type '" + object_type + "' not found in schema."); - } - return *object_schema; - } -}; - -template -inline typename T::Function RealmClass::create_constructor(ContextType ctx) { - FunctionType realm_constructor = ObjectWrap>::create_constructor(ctx); - FunctionType collection_constructor = ObjectWrap>::create_constructor(ctx); - FunctionType list_constructor = ObjectWrap>::create_constructor(ctx); - FunctionType results_constructor = ObjectWrap>::create_constructor(ctx); - FunctionType realm_object_constructor = ObjectWrap>::create_constructor(ctx); - - PropertyAttributes attributes = ReadOnly | DontEnum | DontDelete; - Object::set_property(ctx, realm_constructor, "Collection", collection_constructor, attributes); - Object::set_property(ctx, realm_constructor, "List", list_constructor, attributes); - Object::set_property(ctx, realm_constructor, "Results", results_constructor, attributes); - Object::set_property(ctx, realm_constructor, "Object", realm_object_constructor, attributes); - -#if REALM_ENABLE_SYNC - FunctionType sync_constructor = SyncClass::create_constructor(ctx); - Object::set_property(ctx, realm_constructor, "Sync", sync_constructor, attributes); -#endif - - if (getenv("REALM_DISABLE_SYNC_TO_DISK")) { - realm::disable_sync_to_disk(); - } - - Object::set_global(ctx, "Realm", realm_constructor); - return realm_constructor; -} - -static inline void convert_outdated_datetime_columns(const SharedRealm &realm) { - realm::util::Optional old_file_format_version = realm->file_format_upgraded_from_version(); - if (old_file_format_version && old_file_format_version < 5) { - // any versions earlier than file format 5 are stored as milliseconds and need to be converted to the new format - for (auto& object_schema : realm->schema()) { - auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); - for (auto& property : object_schema.persisted_properties) { - if (property.type == realm::PropertyType::Date) { - if (!realm->is_in_transaction()) { - realm->begin_transaction(); - } - - for (size_t row_index = 0; row_index < table->size(); row_index++) { - if (table->is_null(property.table_column, row_index)) { - continue; - } - auto milliseconds = table->get_timestamp(property.table_column, row_index).get_seconds(); - table->set_timestamp(property.table_column, row_index, Timestamp(milliseconds / 1000, (milliseconds % 1000) * 1000000)); - } - } - } - if (realm->is_in_transaction()) { - realm->commit_transaction(); - } - } - } -} - -template -void RealmClass::constructor(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[]) { - realm::Realm::Config config; - ObjectDefaultsMap defaults; - ConstructorMap constructors; - bool schema_updated = false; - - if (argc == 0) { - config.path = default_path(); - } - else if (argc == 1) { - ValueType value = arguments[0]; - if (Value::is_string(ctx, value)) { - config.path = Value::validated_to_string(ctx, value, "path"); - } - else if (Value::is_object(ctx, value)) { - ObjectType object = Value::validated_to_object(ctx, value); - - static const String encryption_key_string = "encryptionKey"; - ValueType encryption_key_value = Object::get_property(ctx, object, encryption_key_string); - if (!Value::is_undefined(ctx, encryption_key_value)) { - auto encryption_key = Value::validated_to_binary(ctx, encryption_key_value, "encryptionKey"); - config.encryption_key.assign(encryption_key.data(), encryption_key.data() + encryption_key.size()); - } - -#if REALM_ENABLE_SYNC - SyncClass::populate_sync_config(ctx, Value::validated_to_object(ctx, Object::get_global(ctx, "Realm")), object, config); -#endif - - static const String path_string = "path"; - ValueType path_value = Object::get_property(ctx, object, path_string); - if (!Value::is_undefined(ctx, path_value)) { - config.path = Value::validated_to_string(ctx, path_value, "path"); - } - else if (config.path.empty()) { - config.path = js::default_path(); - } - - static const String in_memory_string = "inMemory"; - ValueType in_memory_value = Object::get_property(ctx, object, in_memory_string); - if (!Value::is_undefined(ctx, in_memory_value) && Value::validated_to_boolean(ctx, in_memory_value, "inMemory")) { - config.in_memory = true; - } - - static const String read_only_string = "readOnly"; - ValueType read_only_value = Object::get_property(ctx, object, read_only_string); - if (!Value::is_undefined(ctx, read_only_value) && Value::validated_to_boolean(ctx, read_only_value, "readOnly")) { - config.schema_mode = SchemaMode::Immutable; - } - - static const String delete_realm_if_migration_needed_string = "deleteRealmIfMigrationNeeded"; - ValueType delete_realm_if_migration_needed_value = Object::get_property(ctx, object, delete_realm_if_migration_needed_string); - if (!Value::is_undefined(ctx, delete_realm_if_migration_needed_value) && Value::validated_to_boolean(ctx, delete_realm_if_migration_needed_value, "deleteRealmIfMigrationNeeded")) { - if (config.schema_mode == SchemaMode::Immutable) { - throw std::invalid_argument("Cannot set 'deleteRealmIfMigrationNeeded' when 'readOnly' is set."); - } - - config.schema_mode = SchemaMode::ResetFile; - } - - static const String schema_string = "schema"; - ValueType schema_value = Object::get_property(ctx, object, schema_string); - if (!Value::is_undefined(ctx, schema_value)) { - ObjectType schema_object = Value::validated_to_array(ctx, schema_value, "schema"); - config.schema.emplace(Schema::parse_schema(ctx, schema_object, defaults, constructors)); - schema_updated = true; - } - - static const String schema_version_string = "schemaVersion"; - ValueType version_value = Object::get_property(ctx, object, schema_version_string); - if (!Value::is_undefined(ctx, version_value)) { - config.schema_version = Value::validated_to_number(ctx, version_value, "schemaVersion"); - } - else if (schema_updated) { - config.schema_version = 0; - } - - static const String compact_on_launch_string = "shouldCompactOnLaunch"; - ValueType compact_value = Object::get_property(ctx, object, compact_on_launch_string); - if (!Value::is_undefined(ctx, compact_value)) { - if (config.schema_mode == SchemaMode::Immutable) { - throw std::invalid_argument("Cannot set 'shouldCompactOnLaunch' when 'readOnly' is set."); - } - - FunctionType should_compact_on_launch_function = Value::validated_to_function(ctx, compact_value, "shouldCompactOnLaunch"); - config.should_compact_on_launch_function = [=](uint64_t total_bytes, uint64_t used_bytes) { - ValueType arguments[2] = { - Value::from_number(ctx, total_bytes), - Value::from_number(ctx, used_bytes) - }; - - ValueType should_compact = Function::callback(ctx, should_compact_on_launch_function, this_object, 2, arguments); - return Value::to_boolean(ctx, should_compact); - }; - } - - static const String migration_string = "migration"; - ValueType migration_value = Object::get_property(ctx, object, migration_string); - if (!Value::is_undefined(ctx, migration_value)) { - FunctionType migration_function = Value::validated_to_function(ctx, migration_value, "migration"); - - if (config.schema_mode == SchemaMode::ResetFile) { - throw std::invalid_argument("Cannot include 'migration' when 'deleteRealmIfMigrationNeeded' is set."); - } - - config.migration_function = [=](SharedRealm old_realm, SharedRealm realm, realm::Schema&) { - auto old_realm_ptr = new SharedRealm(old_realm); - auto realm_ptr = new SharedRealm(realm); - ValueType arguments[2] = { - create_object>(ctx, old_realm_ptr), - create_object>(ctx, realm_ptr) - }; - - try { - Function::call(ctx, migration_function, 2, arguments); - } - catch (...) { - old_realm->close(); - old_realm_ptr->reset(); - realm_ptr->reset(); - throw; - } - - old_realm->close(); - old_realm_ptr->reset(); - realm_ptr->reset(); - }; - } - - static const String cache_string = "_cache"; - ValueType cache_value = Object::get_property(ctx, object, cache_string); - if (!Value::is_undefined(ctx, cache_value)) { - config.cache = Value::validated_to_boolean(ctx, cache_value, "_cache"); - } - - static const String automatic_change_notifications_string = "_automaticChangeNotifications"; - ValueType automatic_change_notifications_value = Object::get_property(ctx, object, automatic_change_notifications_string); - if (!Value::is_undefined(ctx, automatic_change_notifications_value)) { - config.automatic_change_notifications = Value::validated_to_boolean(ctx, automatic_change_notifications_value, "_automaticChangeNotifications"); - } - - static const String disable_format_upgrade_string = "disableFormatUpgrade"; - ValueType disable_format_upgrade_value = Object::get_property(ctx, object, disable_format_upgrade_string); - if (!Value::is_undefined(ctx, disable_format_upgrade_value)) { - config.disable_format_upgrade = Value::validated_to_boolean(ctx, disable_format_upgrade_value, "disableFormatUpgrade"); - } - } - } - else { - throw std::runtime_error("Invalid arguments when constructing 'Realm'"); - } - - config.path = normalize_realm_path(config.path); - ensure_directory_exists_for_file(config.path); - - auto realm = create_shared_realm(ctx, config, schema_updated, std::move(defaults), std::move(constructors)); - - // Fix for datetime -> timestamp conversion - convert_outdated_datetime_columns(realm); - - set_internal>(this_object, new SharedRealm(realm)); -} - -template -SharedRealm RealmClass::create_shared_realm(ContextType ctx, realm::Realm::Config config, bool schema_updated, - ObjectDefaultsMap&& defaults, ConstructorMap&& constructors) { - config.execution_context = Context::get_execution_context_id(ctx); - - SharedRealm realm; - try { - realm = realm::Realm::get_shared_realm(config); - } - catch (const RealmFileException& ex) { - handleRealmFileException(ctx, config, ex); - } - -#if REALM_ENABLE_SYNC - auto schema = realm->schema(); - if (realm->is_partial() && schema.empty() && config.cache) { - throw std::invalid_argument("Query-based sync requires a schema."); - } -#endif - - GlobalContextType global_context = Context::get_global_context(ctx); - if (!realm->m_binding_context) { - realm->m_binding_context.reset(new RealmDelegate(realm, global_context)); - } - - RealmDelegate *js_binding_context = dynamic_cast *>(realm->m_binding_context.get()); - REALM_ASSERT(js_binding_context); - REALM_ASSERT(js_binding_context->m_context == global_context); - - // If a new schema was provided, then use its defaults and constructors. - if (schema_updated) { - js_binding_context->m_defaults = std::move(defaults); - js_binding_context->m_constructors = std::move(constructors); - } - - return realm; -} - -template -void RealmClass::schema_version(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(2); - - realm::Realm::Config config; - config.path = normalize_realm_path(Value::validated_to_string(ctx, args[0])); - if (args.count == 2) { - auto encryption_key = Value::validated_to_binary(ctx, args[1], "encryptionKey"); - config.encryption_key.assign(encryption_key.data(), encryption_key.data() + encryption_key.size()); - } - - auto version = realm::Realm::get_schema_version(config); - if (version == ObjectStore::NotVersioned) { - return_value.set(-1); - } - else { - return_value.set((double)version); - } -} - - -template -void RealmClass::clear_test_state(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - js::clear_test_state(); -} - -template -void RealmClass::copy_bundled_realm_files(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - realm::copy_bundled_realm_files(); -} - -template -void RealmClass::delete_file(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - - ValueType value = args[0]; - if (!Value::is_object(ctx, value)) { - throw std::runtime_error("Invalid argument, expected a Realm configuration object"); - } - - ObjectType object = Value::validated_to_object(ctx, value); - realm::Realm::Config config; - - static const String path_string = "path"; - ValueType path_value = Object::get_property(ctx, object, path_string); - if (!Value::is_undefined(ctx, path_value)) { - config.path = Value::validated_to_string(ctx, path_value, "path"); - } - else if (config.path.empty()) { - config.path = js::default_path(); - } - - config.path = normalize_realm_path(config.path); - - std::string realm_file_path = config.path; - realm::remove_file(realm_file_path); - realm::remove_file(realm_file_path + ".lock"); - realm::remove_file(realm_file_path + ".note"); - realm::remove_directory(realm_file_path + ".management"); - -} - -template -void RealmClass::delete_model(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - ValueType value = args[0]; - - SharedRealm& realm = *get_internal>(this_object); - - std::string model_name = Value::validated_to_string(ctx, value, "deleteModel"); - ObjectStore::delete_data_for_object(realm->read_group(), model_name); -} - -template -void RealmClass::get_default_path(ContextType ctx, ObjectType object, ReturnValue &return_value) { - return_value.set(realm::js::default_path()); -} - -template -void RealmClass::set_default_path(ContextType ctx, ObjectType object, ValueType value) { - js::set_default_path(Value::validated_to_string(ctx, value, "defaultPath")); -} - -template -void RealmClass::get_empty(ContextType ctx, ObjectType object, ReturnValue &return_value) { - SharedRealm& realm = *get_internal>(object); - bool is_empty = ObjectStore::is_empty(realm->read_group()); - return_value.set(is_empty); -} - -template -void RealmClass::get_path(ContextType ctx, ObjectType object, ReturnValue &return_value) { - std::string path = get_internal>(object)->get()->config().path; - return_value.set(path); -} - -template -void RealmClass::get_schema_version(ContextType ctx, ObjectType object, ReturnValue &return_value) { - double version = get_internal>(object)->get()->schema_version(); - return_value.set(version); -} - -template -void RealmClass::get_schema(ContextType ctx, ObjectType object, ReturnValue &return_value) { - auto& schema = get_internal>(object)->get()->schema(); - return_value.set(Schema::object_for_schema(ctx, schema)); -} - -template -void RealmClass::get_in_memory(ContextType ctx, ObjectType object, ReturnValue &return_value) { - return_value.set(get_internal>(object)->get()->config().in_memory); -} - -template -void RealmClass::get_read_only(ContextType ctx, ObjectType object, ReturnValue &return_value) { - return_value.set(get_internal>(object)->get()->config().immutable()); -} - -template -void RealmClass::get_is_in_transaction(ContextType ctx, ObjectType object, ReturnValue &return_value) { - return_value.set(get_internal>(object)->get()->is_in_transaction()); -} - -template -void RealmClass::get_is_closed(ContextType ctx, ObjectType object, ReturnValue &return_value) { - return_value.set(get_internal>(object)->get()->is_closed()); -} - -#if REALM_ENABLE_SYNC -template -void RealmClass::get_sync_session(ContextType ctx, ObjectType object, ReturnValue &return_value) { - auto realm = *get_internal>(object); - if (std::shared_ptr session = SyncManager::shared().get_existing_active_session(realm->config().path)) { - return_value.set(create_object>(ctx, new WeakSession(session))); - } else { - return_value.set_null(); - } - -} -#endif - -#if REALM_ENABLE_SYNC -template -void RealmClass::wait_for_download_completion(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(2); - auto callback_function = Value::validated_to_function(ctx, args[0 + (args.count == 2)]); - - ValueType session_callback = Value::from_null(ctx); - if (args.count == 2) { - session_callback = Value::validated_to_function(ctx, args[0]); - } - - auto realm = *get_internal>(this_object); - auto* sync_config = realm->config().sync_config.get(); - if (!sync_config) { - throw std::logic_error("_waitForDownload can only be used on a synchronized Realm."); - } - - Protected protected_callback(ctx, callback_function); - Protected protected_this(ctx, this_object); - Protected protected_ctx(Context::get_global_context(ctx)); - - std::shared_ptr user = sync_config->user; - if (user && user->state() != SyncUser::State::Error) { - if (auto session = user->session_for_on_disk_path(realm->config().path)) { - if (!Value::is_null(ctx, session_callback)) { - FunctionType session_callback_func = Value::to_function(ctx, session_callback); - auto syncSession = create_object>(ctx, new WeakSession(session)); - ValueType callback_arguments[1]; - callback_arguments[0] = syncSession; - Function::callback(protected_ctx, session_callback_func, typename T::Object(), 1, callback_arguments); - } - - EventLoopDispatcher wait_handler([=](std::error_code error_code) { - HANDLESCOPE - if (!error_code) { - //success - Function::callback(protected_ctx, protected_callback, typename T::Object(), 0, nullptr); - } - else { - //fail - ObjectType object = Object::create_empty(protected_ctx); - Object::set_property(protected_ctx, object, "message", Value::from_string(protected_ctx, error_code.message())); - Object::set_property(protected_ctx, object, "errorCode", Value::from_number(protected_ctx, error_code.value())); - - ValueType callback_arguments[1]; - callback_arguments[0] = object; - - Function::callback(protected_ctx, protected_callback, typename T::Object(), 1, callback_arguments); - } - // Ensure that the session remains alive until the callback has had an opportunity to reopen the Realm - // with the appropriate schema. - (void)session; - }); - session->wait_for_download_completion(std::move(wait_handler)); - return; - } - } - - ObjectType object = Object::create_empty(protected_ctx); - Object::set_property(protected_ctx, object, "message", - Value::from_string(protected_ctx, "Cannot asynchronously open synced Realm because the associated session previously experienced a fatal error")); - Object::set_property(protected_ctx, object, "errorCode", Value::from_number(protected_ctx, 1)); - - ValueType callback_arguments[1]; - callback_arguments[0] = object; - Function::callback(protected_ctx, protected_callback, protected_this, 1, callback_arguments); -} -#endif - -template -void RealmClass::objects(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - - SharedRealm realm = *get_internal>(this_object); - auto& object_schema = validated_object_schema_for_value(ctx, realm, args[0]); - return_value.set(ResultsClass::create_instance(ctx, realm, object_schema.name)); -} - -template -void RealmClass::object_for_primary_key(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(2); - - SharedRealm realm = *get_internal>(this_object); - std::string object_type; - auto &object_schema = validated_object_schema_for_value(ctx, realm, args[0]); - NativeAccessor accessor(ctx, realm, object_schema); - auto realm_object = realm::Object::get_for_primary_key(accessor, realm, object_schema, args[1]); - - if (realm_object.is_valid()) { - return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); - } - else { - return_value.set_undefined(); - } -} - -template -void RealmClass::create(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(3); - - SharedRealm realm = *get_internal>(this_object); - realm->verify_open(); - auto &object_schema = validated_object_schema_for_value(ctx, realm, args[0]); - - ObjectType object = Value::validated_to_object(ctx, args[1], "properties"); - if (Value::is_array(ctx, args[1])) { - object = Schema::dict_for_property_array(ctx, object_schema, object); - } - - bool update = false; - if (args.count == 3) { - update = Value::validated_to_boolean(ctx, args[2], "update"); - } - - NativeAccessor accessor(ctx, realm, object_schema); - auto realm_object = realm::Object::create(accessor, realm, object_schema, object, update); - return_value.set(RealmObjectClass::create_instance(ctx, std::move(realm_object))); -} - -template -void RealmClass::delete_one(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - - SharedRealm realm = *get_internal>(this_object); - realm->verify_open(); - if (!realm->is_in_transaction()) { - throw std::runtime_error("Can only delete objects within a transaction."); - } - - ObjectType arg = Value::validated_to_object(ctx, args[0], "object"); - - if (Object::template is_instance>(ctx, arg)) { - auto object = get_internal>(arg); - if (!object->is_valid()) { - throw std::runtime_error("Object is invalid. Either it has been previously deleted or the Realm it belongs to has been closed."); - } - - realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name); - table->move_last_over(object->row().get_index()); - } - else if (Value::is_array(ctx, arg)) { - uint32_t length = Object::validated_get_length(ctx, arg); - for (uint32_t i = length; i--;) { - ObjectType object = Object::validated_get_object(ctx, arg, i); - - if (!Object::template is_instance>(ctx, object)) { - throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects."); - } - - auto realm_object = get_internal>(object); - realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), realm_object->get_object_schema().name); - table->move_last_over(realm_object->row().get_index()); - } - } - else if (Object::template is_instance>(ctx, arg)) { - auto results = get_internal>(arg); - results->clear(); - } - else if (Object::template is_instance>(ctx, arg)) { - auto list = get_internal>(arg); - list->delete_all(); - } - else { - throw std::runtime_error("Argument to 'delete' must be a Realm object or a collection of Realm objects."); - } -} - -template -void RealmClass::delete_all(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - - SharedRealm realm = *get_internal>(this_object); - realm->verify_open(); - - if (!realm->is_in_transaction()) { - throw std::runtime_error("Can only delete objects within a transaction."); - } - - for (auto objectSchema : realm->schema()) { - auto table = ObjectStore::table_for_object_type(realm->read_group(), objectSchema.name); - if (realm->is_partial()) { - realm::Results(realm, *table).clear(); - } - else { - table->clear(); - } - } -} - -template -void RealmClass::write(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - - SharedRealm realm = *get_internal>(this_object); - FunctionType callback = Value::validated_to_function(ctx, args[0]); - - realm->begin_transaction(); - - try { - Function::call(ctx, callback, this_object, 0, nullptr); - } - catch (...) { - realm->cancel_transaction(); - throw; - } - - realm->commit_transaction(); -} - -template -void RealmClass::begin_transaction(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - - SharedRealm realm = *get_internal>(this_object); - realm->begin_transaction(); -} - -template -void RealmClass::commit_transaction(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - - SharedRealm realm = *get_internal>(this_object); - realm->commit_transaction(); -} - -template -void RealmClass::cancel_transaction(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - - SharedRealm realm = *get_internal>(this_object); - realm->cancel_transaction(); -} - -template -void RealmClass::add_listener(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(2); - - auto name = validated_notification_name(ctx, args[0]); - auto callback = Value::validated_to_function(ctx, args[1]); - - SharedRealm realm = *get_internal>(this_object); - realm->verify_open(); - if (name == "change") { - get_delegate(realm.get())->add_notification(callback); - } - else { - get_delegate(realm.get())->add_schema_notification(callback); - } -} - -template -void RealmClass::remove_listener(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(2); - - auto name = validated_notification_name(ctx, args[0]); - auto callback = Value::validated_to_function(ctx, args[1]); - - SharedRealm realm = *get_internal>(this_object); - realm->verify_open(); - if (name == "change") { - get_delegate(realm.get())->remove_notification(callback); - } - else { - get_delegate(realm.get())->remove_schema_notification(callback); - } -} - -template -void RealmClass::remove_all_listeners(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - std::string name = "change"; - if (args.count) { - name = validated_notification_name(ctx, args[0]); - } - - SharedRealm realm = *get_internal>(this_object); - realm->verify_open(); - if (name == "change") { - get_delegate(realm.get())->remove_all_notifications(); - } - else { - get_delegate(realm.get())->remove_all_schema_notifications(); - } -} - -template -void RealmClass::close(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - - SharedRealm realm = *get_internal>(this_object); - realm->close(); -} - -template -void RealmClass::compact(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(0); - - SharedRealm realm = *get_internal>(this_object); - if (realm->is_in_transaction()) { - throw std::runtime_error("Cannot compact a Realm within a transaction."); - } - - return_value.set(realm->compact()); -} - -template -void RealmClass::writeCopyTo(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(2); - - if (args.count == 0) { - throw std::runtime_error("At least path has to be provided for 'writeCopyTo'"); - } - - SharedRealm realm = *get_internal>(this_object); - - ValueType pathValue = args[0]; - if (!Value::is_string(ctx, pathValue)) { - throw std::runtime_error("Argument to 'writeCopyTo' must be a String."); - } - - std::string path = Value::validated_to_string(ctx, pathValue); - - if (args.count == 1) { - BinaryData empty_encryption_key; - realm->write_copy(path, empty_encryption_key); - - return; - } - - // enryption key is specified - ValueType encryption_key_arg = args[1]; - - if (!Value::is_binary(ctx, encryption_key_arg)) { - throw std::runtime_error("Encryption key for 'writeCopyTo' must be a Binary."); - } - - auto encryption_key = Value::validated_to_binary(ctx, encryption_key_arg); - - realm->write_copy(path, encryption_key.get()); -} - -template -void RealmClass::object_for_object_id(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue& return_value) { - args.validate_count(2); - -#if REALM_ENABLE_SYNC - SharedRealm realm = *get_internal>(this_object); - if (!sync::has_object_ids(realm->read_group())) - throw std::logic_error("Realm._objectForObjectId() can only be used with synced Realms."); - - auto& object_schema = validated_object_schema_for_value(ctx, realm, args[0]); - std::string object_id_string = Value::validated_to_string(ctx, args[1]); - auto object_id = sync::ObjectID::from_string(object_id_string); - - const Group& group = realm->read_group(); - size_t ndx = sync::row_for_object_id(group, *ObjectStore::table_for_object_type(group, object_schema.name), object_id); - if (ndx != realm::npos) { - return_value.set(RealmObjectClass::create_instance(ctx, realm::Object(realm, object_schema.name, ndx))); - } -#else - throw std::logic_error("Realm._objectForObjectId() can only be used with synced Realms."); -#endif // REALM_ENABLE_SYNC -} - -template -void RealmClass::privileges(ContextType ctx, ObjectType this_object, Arguments args, ReturnValue &return_value) { - args.validate_maximum(1); - - using Privilege = realm::ComputedPrivileges; - auto has_privilege = [](Privilege actual, Privilege expected) { - return (static_cast(actual) & static_cast(expected)) == static_cast(expected); - }; - - SharedRealm realm = *get_internal>(this_object); - if (args.count == 0) { - auto p = realm->get_privileges(); - ObjectType object = Object::create_empty(ctx); - Object::set_property(ctx, object, "read", Value::from_boolean(ctx, has_privilege(p, Privilege::Read))); - Object::set_property(ctx, object, "update", Value::from_boolean(ctx,has_privilege(p, Privilege::Update))); - Object::set_property(ctx, object, "modifySchema", Value::from_boolean(ctx, has_privilege(p, Privilege::ModifySchema))); - Object::set_property(ctx, object, "setPermissions", Value::from_boolean(ctx, has_privilege(p, Privilege::SetPermissions))); - return_value.set(object); - return; - } - - if (Value::is_object(ctx, args[0])) { - auto arg = Value::to_object(ctx, args[0]); - if (Object::template is_instance>(ctx, arg)) { - auto obj = get_internal>(arg); - auto p = realm->get_privileges(obj->row()); - - ObjectType object = Object::create_empty(ctx); - Object::set_property(ctx, object, "read", Value::from_boolean(ctx, has_privilege(p, Privilege::Read))); - Object::set_property(ctx, object, "update", Value::from_boolean(ctx,has_privilege(p, Privilege::Update))); - Object::set_property(ctx, object, "delete", Value::from_boolean(ctx,has_privilege(p, Privilege::Delete))); - Object::set_property(ctx, object, "setPermissions", Value::from_boolean(ctx, has_privilege(p, Privilege::SetPermissions))); - return_value.set(object); - return; - } - } - - auto& object_schema = validated_object_schema_for_value(ctx, realm, args[0]); - auto p = realm->get_privileges(object_schema.name); - ObjectType object = Object::create_empty(ctx); - Object::set_property(ctx, object, "read", Value::from_boolean(ctx, has_privilege(p, Privilege::Read))); - Object::set_property(ctx, object, "update", Value::from_boolean(ctx,has_privilege(p, Privilege::Update))); - Object::set_property(ctx, object, "create", Value::from_boolean(ctx, has_privilege(p, Privilege::Create))); - Object::set_property(ctx, object, "subscribe", Value::from_boolean(ctx, has_privilege(p, Privilege::Query))); - Object::set_property(ctx, object, "setPermissions", Value::from_boolean(ctx, has_privilege(p, Privilege::SetPermissions))); - return_value.set(object); -} - -} // js -} // realm