mirror of
https://github.com/status-im/realm-js.git
synced 2025-01-11 14:54:33 +00:00
store schema and prototypes on the realm object
This commit is contained in:
parent
8ee6e757ee
commit
167c3e97b5
@ -21,6 +21,7 @@
|
|||||||
#import "RJSResults.hpp"
|
#import "RJSResults.hpp"
|
||||||
#import "RJSSchema.hpp"
|
#import "RJSSchema.hpp"
|
||||||
#import "RJSList.hpp"
|
#import "RJSList.hpp"
|
||||||
|
#import "RJSRealm.hpp"
|
||||||
|
|
||||||
#import "object_store.hpp"
|
#import "object_store.hpp"
|
||||||
#import "object_accessor.hpp"
|
#import "object_accessor.hpp"
|
||||||
@ -63,7 +64,7 @@ JSClassRef RJSObjectClass() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) {
|
JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) {
|
||||||
JSValueRef prototype = RJSPrototypeForClassName(object.object_schema.name);
|
JSValueRef prototype = RJSPrototypes(object.realm.get())[object.object_schema.name];
|
||||||
JSObjectRef jsObject = RJSWrapObject(ctx, RJSObjectClass(), new Object(object), prototype);
|
JSObjectRef jsObject = RJSWrapObject(ctx, RJSObjectClass(), new Object(object), prototype);
|
||||||
return jsObject;
|
return jsObject;
|
||||||
}
|
}
|
||||||
@ -86,13 +87,13 @@ template<> JSValueRef RJSAccessor::dict_value_for_key(JSContextRef ctx, JSValueR
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> bool RJSAccessor::has_default_value_for_property(JSContextRef ctx, const ObjectSchema &object_schema, const std::string &prop_name) {
|
template<> bool RJSAccessor::has_default_value_for_property(JSContextRef ctx, Realm *realm, const ObjectSchema &object_schema, const std::string &prop_name) {
|
||||||
ObjectDefaults &defaults = RJSDefaultsForClassName(object_schema.name);
|
ObjectDefaults &defaults = RJSDefaults(realm)[object_schema.name];
|
||||||
return defaults.find(prop_name) != defaults.end();
|
return defaults.find(prop_name) != defaults.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx, const ObjectSchema &object_schema, const std::string &prop_name) {
|
template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx, Realm *realm, const ObjectSchema &object_schema, const std::string &prop_name) {
|
||||||
ObjectDefaults &defaults = RJSDefaultsForClassName(object_schema.name);
|
ObjectDefaults &defaults = RJSDefaults(realm)[object_schema.name];
|
||||||
return defaults[prop_name];
|
return defaults[prop_name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,12 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#import "RJSUtil.hpp"
|
#import "RJSUtil.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace realm {
|
||||||
|
class Realm;
|
||||||
|
using ObjectDefaults = std::map<std::string, JSValueRef>;
|
||||||
|
}
|
||||||
|
|
||||||
extern const JSStaticFunction RJSRealmFuncs[];
|
extern const JSStaticFunction RJSRealmFuncs[];
|
||||||
|
|
||||||
@ -28,3 +34,6 @@ std::string RJSDefaultPath();
|
|||||||
void RJSSetDefaultPath(std::string path);
|
void RJSSetDefaultPath(std::string path);
|
||||||
|
|
||||||
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException);
|
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException);
|
||||||
|
|
||||||
|
std::map<std::string, realm::ObjectDefaults> &RJSDefaults(realm::Realm *realm);
|
||||||
|
std::map<std::string, JSValueRef> &RJSPrototypes(realm::Realm *realm);
|
@ -59,8 +59,36 @@ public:
|
|||||||
std::vector<void*> const& invalidated) {
|
std::vector<void*> const& invalidated) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSGlobalContextRef m_context;
|
||||||
|
std::map<std::string, ObjectDefaults> m_defaults;
|
||||||
|
std::map<std::string, JSValueRef> m_prototypes;
|
||||||
|
|
||||||
|
RJSRealmDelegate(JSGlobalContextRef ctx) : m_context(ctx) {
|
||||||
|
JSGlobalContextRetain(m_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
~RJSRealmDelegate() {
|
||||||
|
for (auto prototype : m_prototypes) {
|
||||||
|
JSValueUnprotect(m_context, prototype.second);
|
||||||
|
}
|
||||||
|
for (auto objectDefaults : m_defaults) {
|
||||||
|
for (auto value : objectDefaults.second) {
|
||||||
|
JSValueUnprotect(m_context, value.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSGlobalContextRelease(m_context);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::map<std::string, ObjectDefaults> &RJSDefaults(Realm *realm) {
|
||||||
|
return static_cast<RJSRealmDelegate *>(realm->m_delegate.get())->m_defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, JSValueRef> &RJSPrototypes(Realm *realm) {
|
||||||
|
return static_cast<RJSRealmDelegate *>(realm->m_delegate.get())->m_prototypes;
|
||||||
|
}
|
||||||
|
|
||||||
std::string writeablePathForFile(const std::string &fileName) {
|
std::string writeablePathForFile(const std::string &fileName) {
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
// On iOS the Documents directory isn't user-visible, so put files there
|
// On iOS the Documents directory isn't user-visible, so put files there
|
||||||
@ -114,6 +142,8 @@ static bool SetDefaultPath(JSContextRef ctx, JSObjectRef object, JSStringRef pro
|
|||||||
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
try {
|
try {
|
||||||
Realm::Config config;
|
Realm::Config config;
|
||||||
|
std::map<std::string, realm::ObjectDefaults> defaults;
|
||||||
|
std::map<std::string, JSValueRef> prototypes;
|
||||||
switch (argumentCount) {
|
switch (argumentCount) {
|
||||||
case 0:
|
case 0:
|
||||||
config.path = RJSDefaultPath();
|
config.path = RJSDefaultPath();
|
||||||
@ -139,7 +169,7 @@ JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t a
|
|||||||
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
||||||
JSValueRef schemaValue = RJSValidatedPropertyValue(ctx, object, schemaString);
|
JSValueRef schemaValue = RJSValidatedPropertyValue(ctx, object, schemaString);
|
||||||
if (!JSValueIsUndefined(ctx, schemaValue)) {
|
if (!JSValueIsUndefined(ctx, schemaValue)) {
|
||||||
config.schema = std::make_unique<Schema>(RJSParseSchema(ctx, RJSValidatedValueToObject(ctx, schemaValue)));
|
config.schema = std::make_unique<Schema>(RJSParseSchema(ctx, RJSValidatedValueToObject(ctx, schemaValue), defaults, prototypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSStringRef schemaVersionString = JSStringCreateWithUTF8CString("schemaVersion");
|
static JSStringRef schemaVersionString = JSStringCreateWithUTF8CString("schemaVersion");
|
||||||
@ -159,8 +189,10 @@ JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t a
|
|||||||
}
|
}
|
||||||
SharedRealm realm = Realm::get_shared_realm(config);
|
SharedRealm realm = Realm::get_shared_realm(config);
|
||||||
if (!realm->m_delegate) {
|
if (!realm->m_delegate) {
|
||||||
realm->m_delegate = std::make_unique<RJSRealmDelegate>();
|
realm->m_delegate = std::make_unique<RJSRealmDelegate>(JSContextGetGlobalContext(ctx));
|
||||||
}
|
}
|
||||||
|
RJSDefaults(realm.get()) = defaults;
|
||||||
|
RJSPrototypes(realm.get()) = prototypes;
|
||||||
return RJSWrapObject<SharedRealm *>(ctx, RJSRealmClass(), new SharedRealm(realm));
|
return RJSWrapObject<SharedRealm *>(ctx, RJSRealmClass(), new SharedRealm(realm));
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception &ex) {
|
||||||
@ -424,6 +456,7 @@ JSValueRef RealmClose(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb
|
|||||||
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
SharedRealm realm = *RJSGetInternal<SharedRealm *>(thisObject);
|
||||||
realm->invalidate();
|
realm->invalidate();
|
||||||
realm::Realm::s_global_cache.remove(realm->config().path, realm->thread_id());
|
realm::Realm::s_global_cache.remove(realm->config().path, realm->thread_id());
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception &exp) {
|
catch (std::exception &exp) {
|
||||||
if (jsException) {
|
if (jsException) {
|
||||||
|
@ -27,8 +27,4 @@ namespace realm {
|
|||||||
JSClassRef RJSSchemaClass();
|
JSClassRef RJSSchemaClass();
|
||||||
JSObjectRef RJSSchemaCreate(JSContextRef ctx, realm::Schema *schema);
|
JSObjectRef RJSSchemaCreate(JSContextRef ctx, realm::Schema *schema);
|
||||||
|
|
||||||
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject);
|
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject, std::map<std::string, realm::ObjectDefaults> &defaults, std::map<std::string, JSValueRef> &prototypes);
|
||||||
|
|
||||||
JSValueRef RJSPrototypeForClassName(const std::string &className);
|
|
||||||
realm::ObjectDefaults &RJSDefaultsForClassName(const std::string &className);
|
|
||||||
void RJSSchemaClearState(JSContextRef ctx);
|
|
||||||
|
@ -45,30 +45,6 @@ JSObjectRef RJSSchemaCreate(JSContextRef ctx, Schema &schema) {
|
|||||||
return RJSWrapObject(ctx, RJSSchemaClass(), wrapper);
|
return RJSWrapObject(ctx, RJSSchemaClass(), wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<std::string, ObjectDefaults> s_defaults;
|
|
||||||
ObjectDefaults &RJSDefaultsForClassName(const std::string &className) {
|
|
||||||
return s_defaults[className];
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::map<std::string, JSValueRef> s_prototypes;
|
|
||||||
JSValueRef RJSPrototypeForClassName(const std::string &className) {
|
|
||||||
return s_prototypes[className];
|
|
||||||
}
|
|
||||||
|
|
||||||
void RJSSchemaClearState(JSContextRef ctx) {
|
|
||||||
for (auto prototype : s_prototypes) {
|
|
||||||
JSValueUnprotect(ctx, prototype.second);
|
|
||||||
}
|
|
||||||
s_prototypes.clear();
|
|
||||||
|
|
||||||
for (auto defaults : s_defaults) {
|
|
||||||
for (auto value : defaults.second) {
|
|
||||||
JSValueUnprotect(ctx, value.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s_defaults.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Property RJSParseProperty(JSContextRef ctx, JSObjectRef propertyObject) {
|
static inline Property RJSParseProperty(JSContextRef ctx, JSObjectRef propertyObject) {
|
||||||
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
||||||
static JSStringRef typeString = JSStringCreateWithUTF8CString("type");
|
static JSStringRef typeString = JSStringCreateWithUTF8CString("type");
|
||||||
@ -116,7 +92,7 @@ static inline Property RJSParseProperty(JSContextRef ctx, JSObjectRef propertyOb
|
|||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef objectSchemaObject) {
|
static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef objectSchemaObject, std::map<std::string, realm::ObjectDefaults> &defaults, std::map<std::string, JSValueRef> &prototypes) {
|
||||||
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
||||||
static JSStringRef prototypeString = JSStringCreateWithUTF8CString("prototype");
|
static JSStringRef prototypeString = JSStringCreateWithUTF8CString("prototype");
|
||||||
JSObjectRef prototypeObject = NULL;
|
JSObjectRef prototypeObject = NULL;
|
||||||
@ -136,8 +112,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
|
|||||||
JSObjectRef propertiesObject = RJSValidatedObjectProperty(ctx, objectSchemaObject, propertiesString, "ObjectSchema object must have a 'properties' array.");
|
JSObjectRef propertiesObject = RJSValidatedObjectProperty(ctx, objectSchemaObject, propertiesString, "ObjectSchema object must have a 'properties' array.");
|
||||||
|
|
||||||
ObjectSchema objectSchema;
|
ObjectSchema objectSchema;
|
||||||
ObjectDefaults defaults;
|
ObjectDefaults objectDefaults;
|
||||||
|
|
||||||
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
||||||
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
||||||
|
|
||||||
@ -150,10 +125,10 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
|
|||||||
JSValueRef defaultValue = JSObjectGetProperty(ctx, property, defaultString, NULL);
|
JSValueRef defaultValue = JSObjectGetProperty(ctx, property, defaultString, NULL);
|
||||||
if (!JSValueIsUndefined(ctx, defaultValue)) {
|
if (!JSValueIsUndefined(ctx, defaultValue)) {
|
||||||
JSValueProtect(ctx, defaultValue);
|
JSValueProtect(ctx, defaultValue);
|
||||||
defaults.emplace(objectSchema.properties.back().name, defaultValue);
|
objectDefaults.emplace(objectSchema.properties.back().name, defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s_defaults.emplace(objectSchema.name, std::move(defaults));
|
defaults.emplace(objectSchema.name, std::move(objectDefaults));
|
||||||
|
|
||||||
static JSStringRef primaryString = JSStringCreateWithUTF8CString("primaryKey");
|
static JSStringRef primaryString = JSStringCreateWithUTF8CString("primaryKey");
|
||||||
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
||||||
@ -169,18 +144,18 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
|
|||||||
// store prototype
|
// store prototype
|
||||||
if (prototypeObject) {
|
if (prototypeObject) {
|
||||||
JSValueProtect(ctx, prototypeObject);
|
JSValueProtect(ctx, prototypeObject);
|
||||||
s_prototypes[objectSchema.name] = std::move(prototypeObject);
|
prototypes[objectSchema.name] = std::move(prototypeObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
return objectSchema;
|
return objectSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) {
|
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject, std::map<std::string, realm::ObjectDefaults> &defaults, std::map<std::string, JSValueRef> &prototypes) {
|
||||||
std::vector<ObjectSchema> schema;
|
std::vector<ObjectSchema> schema;
|
||||||
size_t length = RJSValidatedListLength(ctx, jsonObject);
|
size_t length = RJSValidatedListLength(ctx, jsonObject);
|
||||||
for (unsigned int i = 0; i < length; i++) {
|
for (unsigned int i = 0; i < length; i++) {
|
||||||
JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i);
|
JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i);
|
||||||
ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema);
|
ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema, defaults, prototypes);
|
||||||
schema.emplace_back(std::move(objectSchema));
|
schema.emplace_back(std::move(objectSchema));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
// add realm apis to the given js context
|
// add realm apis to the given js context
|
||||||
+ (void)initializeContext:(JSContextRef)ctx;
|
+ (void)initializeContext:(JSContextRef)ctx;
|
||||||
|
+ (void)disposeContext:(JSContextRef)ctx;
|
||||||
+ (void)clearTestState;
|
+ (void)clearTestState;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -58,7 +58,6 @@ NSString *RealmFileDirectory() {
|
|||||||
|
|
||||||
static JSValueRef ClearTestState(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) {
|
static JSValueRef ClearTestState(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) {
|
||||||
[RealmJS clearTestState];
|
[RealmJS clearTestState];
|
||||||
//RJSSchemaClearState(ctx);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ namespace realm {
|
|||||||
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
||||||
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
||||||
|
|
||||||
static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
|
static bool has_default_value_for_property(ContextType ctx, Realm *realm, const ObjectSchema &object_schema, const std::string &prop_name);
|
||||||
static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
|
static ValueType default_value_for_property(ContextType ctx, Realm *realm, const ObjectSchema &object_schema, const std::string &prop_name);
|
||||||
|
|
||||||
static bool to_bool(ContextType, ValueType &);
|
static bool to_bool(ContextType, ValueType &);
|
||||||
static ValueType from_bool(ContextType, bool);
|
static ValueType from_bool(ContextType, bool);
|
||||||
@ -260,8 +260,8 @@ namespace realm {
|
|||||||
object.set_property_value_impl(ctx, prop, Accessor::dict_value_for_key(ctx, value, prop.name), try_update);
|
object.set_property_value_impl(ctx, prop, Accessor::dict_value_for_key(ctx, value, prop.name), try_update);
|
||||||
}
|
}
|
||||||
else if (created) {
|
else if (created) {
|
||||||
if (Accessor::has_default_value_for_property(ctx, object_schema, prop.name)) {
|
if (Accessor::has_default_value_for_property(ctx, realm.get(), object_schema, prop.name)) {
|
||||||
object.set_property_value_impl(ctx, prop, Accessor::default_value_for_property(ctx, object_schema, prop.name), try_update);
|
object.set_property_value_impl(ctx, prop, Accessor::default_value_for_property(ctx, realm.get(), object_schema, prop.name), try_update);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw std::runtime_error("Missing property value for property " + prop.name);
|
throw std::runtime_error("Missing property value for property " + prop.name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user