realm-js/src/js_realm_object.hpp

139 lines
4.7 KiB
C++
Raw Normal View History

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
#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
#include "object_accessor.hpp"
#include "object_store.hpp"
2015-08-13 09:12:48 -07:00
namespace realm {
namespace js {
template<typename T>
class RealmObject {
2016-04-18 12:15:00 -07:00
using ContextType = typename T::Context;
using FunctionType = typename T::Function;
using ObjectType = typename T::Object;
using ValueType = typename T::Value;
using String = js::String<T>;
using Value = js::Value<T>;
using Object = js::Object<T>;
using Function = js::Function<T>;
using ReturnValue = js::ReturnValue<T>;
public:
2016-04-18 12:15:00 -07:00
static ObjectType create_instance(ContextType, realm::Object &);
2016-04-18 12:15:00 -07:00
static void get_property(ContextType, ObjectType, const String &, ReturnValue &);
static bool set_property(ContextType, ObjectType, const String &, ValueType);
static std::vector<String> get_property_names(ContextType, ObjectType);
static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &);
};
template<typename T>
2016-04-16 16:46:16 -07:00
struct RealmObjectClass : ClassDefinition<T, realm::Object> {
using RealmObject = js::RealmObject<T>;
const std::string name = "RealmObject";
const StringPropertyType<T> string_accessor = {
wrap<RealmObject::get_property>,
wrap<RealmObject::set_property>,
wrap<RealmObject::get_property_names>,
};
MethodMap<T> const methods = {
{"isValid", wrap<RealmObject::is_valid>},
};
};
template<typename T>
void RealmObject<T>::is_valid(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
return_value.set(get_internal<T, RealmObjectClass<T>>(this_object)->is_valid());
}
template<typename T>
2016-04-18 12:15:00 -07:00
typename T::Object RealmObject<T>::create_instance(ContextType ctx, realm::Object &realm_object) {
static String prototype_string = "prototype";
auto delegate = get_delegate<T>(realm_object.realm().get());
auto name = realm_object.get_object_schema().name;
auto object = create_object<T, RealmObjectClass<T>>(ctx, new realm::Object(realm_object));
2016-04-18 15:24:58 -07:00
if (!delegate || !delegate->m_constructors.count(name)) {
return object;
}
2016-04-18 12:15:00 -07:00
FunctionType constructor = delegate->m_constructors.at(name);
ObjectType prototype = Object::validated_get_object(ctx, constructor, prototype_string);
Object::set_prototype(ctx, object, prototype);
2016-04-18 12:15:00 -07:00
ValueType result = Function::call(ctx, constructor, object, 0, NULL);
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-18 12:15:00 -07:00
void RealmObject<T>::get_property(ContextType ctx, ObjectType object, const String &property, ReturnValue &return_value) {
try {
auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
2016-04-18 12:15:00 -07:00
auto result = realm_object->template get_property_value<ValueType>(ctx, property);
return_value.set(result);
} catch (InvalidPropertyException &ex) {
// getters for nonexistent properties in JS should always return undefined
}
}
template<typename T>
2016-04-18 12:15:00 -07:00
bool RealmObject<T>::set_property(ContextType ctx, ObjectType object, const String &property, ValueType value) {
auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
try {
realm_object->set_property_value(ctx, property, value, true);
}
catch (InvalidPropertyException &ex) {
return false;
}
return true;
}
template<typename T>
2016-04-18 12:15:00 -07:00
std::vector<String<T>> RealmObject<T>::get_property_names(ContextType ctx, ObjectType object) {
auto realm_object = get_internal<T, RealmObjectClass<T>>(object);
auto &properties = realm_object->get_object_schema().properties;
2016-04-12 14:42:05 -07:00
std::vector<String> names;
names.reserve(properties.size());
for (auto &prop : properties) {
2016-04-12 14:42:05 -07:00
names.push_back(prop.name);
}
return names;
2015-08-13 09:12:48 -07:00
}
} // js
} // realm