//////////////////////////////////////////////////////////////////////////// // // 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 "js_class.hpp" #include "js_types.hpp" #include "js_util.hpp" #include "object_accessor.hpp" #include "object_store.hpp" namespace realm { namespace js { template class RealmObject { using ContextType = typename T::Context; using FunctionType = typename T::Function; using ObjectType = typename T::Object; using ValueType = typename T::Value; using String = String; using Value = Value; using Object = Object; using Function = Function; using ReturnValue = ReturnValue; public: static ObjectType create_instance(ContextType, realm::Object &); static void get_property(ContextType, ObjectType, const String &, ReturnValue &); static bool set_property(ContextType, ObjectType, const String &, ValueType); static std::vector get_property_names(ContextType, ObjectType); }; template struct RealmObjectClass : ClassDefinition { using RealmObject = RealmObject; const std::string name = "RealmObject"; const StringPropertyType string_accessor = { wrap, wrap, wrap, }; }; template typename T::Object RealmObject::create_instance(ContextType ctx, realm::Object &realm_object) { static String prototype_string = "prototype"; auto delegate = get_delegate(realm_object.realm().get()); auto name = realm_object.get_object_schema().name; auto object = create_object>(ctx, new realm::Object(realm_object)); if (!delegate->m_constructors.count(name)) { return object; } FunctionType constructor = delegate->m_constructors.at(name); ObjectType prototype = Object::validated_get_object(ctx, constructor, prototype_string); Object::set_prototype(ctx, object, prototype); 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 void RealmObject::get_property(ContextType ctx, ObjectType object, const String &property, ReturnValue &return_value) { try { auto realm_object = get_internal>(object); auto result = realm_object->template get_property_value(ctx, property); return_value.set(result); } catch (InvalidPropertyException &ex) { // getters for nonexistent properties in JS should always return undefined } } template bool RealmObject::set_property(ContextType ctx, ObjectType object, const String &property, ValueType value) { auto realm_object = get_internal>(object); realm_object->set_property_value(ctx, property, value, true); return true; } template std::vector> RealmObject::get_property_names(ContextType ctx, ObjectType object) { auto realm_object = get_internal>(object); auto &properties = realm_object->get_object_schema().properties; std::vector names; names.reserve(properties.size()); for (auto &prop : properties) { names.push_back(prop.name); } return names; } } // js } // realm