2016-02-18 11:59:34 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
2015-08-13 09:12:48 -07:00
|
|
|
|
2015-12-01 14:52:38 -08:00
|
|
|
#pragma once
|
|
|
|
|
2016-03-30 14:11:57 -07:00
|
|
|
#include "js_class.hpp"
|
|
|
|
#include "js_types.hpp"
|
2015-12-01 14:52:38 -08:00
|
|
|
#include "js_util.hpp"
|
2015-08-13 09:12:48 -07:00
|
|
|
|
2016-03-30 14:11:57 -07:00
|
|
|
#include "object_accessor.hpp"
|
|
|
|
#include "object_store.hpp"
|
|
|
|
|
2015-08-13 09:12:48 -07:00
|
|
|
namespace realm {
|
2016-03-30 14:11:57 -07:00
|
|
|
namespace js {
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct RealmObject {
|
2016-04-14 10:54:43 -07:00
|
|
|
using TContext = typename T::Context;
|
|
|
|
using TFunction = typename T::Function;
|
|
|
|
using TObject = typename T::Object;
|
|
|
|
using TValue = typename T::Value;
|
2016-03-30 14:11:57 -07:00
|
|
|
using String = String<T>;
|
|
|
|
using Value = Value<T>;
|
|
|
|
using Object = Object<T>;
|
|
|
|
using Function = Function<T>;
|
|
|
|
using ReturnValue = ReturnValue<T>;
|
|
|
|
|
2016-04-14 11:19:01 -07:00
|
|
|
static TObject create_instance(TContext, realm::Object &);
|
2016-03-30 14:11:57 -07:00
|
|
|
|
2016-04-14 10:54:43 -07:00
|
|
|
static void GetProperty(TContext, TObject, const String &, ReturnValue &);
|
|
|
|
static bool SetProperty(TContext, TObject, const String &, TValue);
|
|
|
|
static std::vector<String> GetPropertyNames(TContext, TObject);
|
2016-03-30 14:11:57 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
2016-04-15 13:47:01 -07:00
|
|
|
struct RealmObjectClass : ClassDefinition<T, realm::Object>, BaseClassDefinition<T> {
|
2016-03-30 14:11:57 -07:00
|
|
|
using RealmObject = RealmObject<T>;
|
|
|
|
|
|
|
|
const std::string name = "RealmObject";
|
|
|
|
|
|
|
|
const StringPropertyType<T> string_accessor = {
|
|
|
|
wrap<RealmObject::GetProperty>,
|
|
|
|
wrap<RealmObject::SetProperty>,
|
|
|
|
wrap<RealmObject::GetPropertyNames>,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
2016-04-14 11:19:01 -07:00
|
|
|
typename T::Object RealmObject<T>::create_instance(TContext ctx, realm::Object &realm_object) {
|
2016-03-30 14:11:57 -07:00
|
|
|
static String s_prototype = "prototype";
|
|
|
|
|
|
|
|
auto delegate = get_delegate<T>(realm_object.realm().get());
|
|
|
|
auto name = realm_object.get_object_schema().name;
|
2016-04-15 13:47:01 -07:00
|
|
|
auto object = create_object<T, RealmObjectClass<T>>(ctx, new realm::Object(realm_object));
|
2016-03-30 14:11:57 -07:00
|
|
|
|
|
|
|
if (!delegate->m_constructors.count(name)) {
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2016-04-14 10:54:43 -07:00
|
|
|
TFunction constructor = delegate->m_constructors.at(name);
|
|
|
|
TObject prototype = Object::validated_get_object(ctx, constructor, s_prototype);
|
2016-03-30 14:11:57 -07:00
|
|
|
Object::set_prototype(ctx, object, prototype);
|
|
|
|
|
2016-04-14 10:54:43 -07:00
|
|
|
TValue result = Function::call(ctx, constructor, object, 0, NULL);
|
2016-03-30 14:11:57 -07:00
|
|
|
if (result != object && !Value::is_null(ctx, result) && !Value::is_undefined(ctx, result)) {
|
|
|
|
throw std::runtime_error("Realm object constructor must not return another value");
|
|
|
|
}
|
|
|
|
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2016-04-14 10:54:43 -07:00
|
|
|
void RealmObject<T>::GetProperty(TContext ctx, TObject object, const String &property, ReturnValue &return_value) {
|
2016-03-30 14:11:57 -07:00
|
|
|
try {
|
2016-04-15 13:47:01 -07:00
|
|
|
auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
|
2016-04-14 10:54:43 -07:00
|
|
|
auto result = realm_object->template get_property_value<TValue>(ctx, property);
|
2016-03-30 14:11:57 -07:00
|
|
|
return_value.set(result);
|
|
|
|
} catch (InvalidPropertyException &ex) {
|
|
|
|
// getters for nonexistent properties in JS should always return undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2016-04-14 10:54:43 -07:00
|
|
|
bool RealmObject<T>::SetProperty(TContext ctx, TObject object, const String &property, TValue value) {
|
2016-04-15 13:47:01 -07:00
|
|
|
auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
|
2016-03-30 14:11:57 -07:00
|
|
|
realm_object->set_property_value(ctx, property, value, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2016-04-14 10:54:43 -07:00
|
|
|
std::vector<String<T>> RealmObject<T>::GetPropertyNames(TContext ctx, TObject object) {
|
2016-04-15 13:47:01 -07:00
|
|
|
auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
|
2016-03-30 14:11:57 -07:00
|
|
|
auto &properties = realm_object->get_object_schema().properties;
|
2016-04-12 14:42:05 -07:00
|
|
|
|
|
|
|
std::vector<String> names;
|
|
|
|
names.reserve(properties.size());
|
2016-03-30 14:11:57 -07:00
|
|
|
|
|
|
|
for (auto &prop : properties) {
|
2016-04-12 14:42:05 -07:00
|
|
|
names.push_back(prop.name);
|
2016-03-30 14:11:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return names;
|
2015-08-13 09:12:48 -07:00
|
|
|
}
|
|
|
|
|
2016-03-30 14:11:57 -07:00
|
|
|
} // js
|
|
|
|
} // realm
|