convert schema parsing
This commit is contained in:
parent
61685dee83
commit
f80bcd882d
|
@ -20,11 +20,13 @@
|
|||
|
||||
#include "js_util.hpp"
|
||||
#include "js_schema.hpp"
|
||||
|
||||
#include "shared_realm.hpp"
|
||||
#include "binding_context.hpp"
|
||||
#include "object_accessor.hpp"
|
||||
#include "results.hpp"
|
||||
#include "platform.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
@ -191,8 +193,8 @@ void Realm<T>::Constructor(ContextType ctx, ObjectType constructor, size_t argum
|
|||
using StringType = typename T::String;
|
||||
|
||||
realm::Realm::Config config;
|
||||
std::map<std::string, ObjectDefaults> defaults;
|
||||
std::map<std::string, ObjectType> constructors;
|
||||
typename Schema<T>::ObjectDefaultsMap defaults;
|
||||
typename Schema<T>::ConstructorMap constructors;
|
||||
if (argumentCount == 0) {
|
||||
config.path = default_path();
|
||||
}
|
||||
|
@ -215,8 +217,8 @@ void Realm<T>::Constructor(ContextType ctx, ObjectType constructor, size_t argum
|
|||
|
||||
StringType schemaString("schema");
|
||||
ValueType schemaValue = RJSValidatedPropertyValue(ctx, object, schemaString);
|
||||
if (!JSValueIsUndefined(ctx, schemaValue)) {
|
||||
config.schema.reset(new Schema(RJSParseSchema(ctx, RJSValidatedValueToObject(ctx, schemaValue), defaults, constructors)));
|
||||
if (!ValueIsUndefined(ctx, schemaValue)) {
|
||||
config.schema.reset(new realm::Schema(Schema<T>::parse_schema(ctx, RJSValidatedValueToObject(ctx, schemaValue), defaults, constructors)));
|
||||
}
|
||||
|
||||
StringType schemaVersionString("schemaVersion");
|
||||
|
|
|
@ -44,163 +44,3 @@ JSObjectRef RJSSchemaCreate(JSContextRef ctx, Schema &schema) {
|
|||
wrapper->owned = false;
|
||||
return js::WrapObject(ctx, RJSSchemaClass(), wrapper);
|
||||
}
|
||||
|
||||
static inline Property RJSParseProperty(JSContextRef ctx, JSValueRef propertyAttributes, std::string propertyName, ObjectDefaults &objectDefaults) {
|
||||
static JSStringRef defaultString = JSStringCreateWithUTF8CString("default");
|
||||
static JSStringRef indexedString = JSStringCreateWithUTF8CString("indexed");
|
||||
static JSStringRef typeString = JSStringCreateWithUTF8CString("type");
|
||||
static JSStringRef objectTypeString = JSStringCreateWithUTF8CString("objectType");
|
||||
static JSStringRef optionalString = JSStringCreateWithUTF8CString("optional");
|
||||
|
||||
Property prop;
|
||||
prop.name = propertyName;
|
||||
|
||||
JSObjectRef propertyObject = NULL;
|
||||
std::string type;
|
||||
|
||||
if (JSValueIsObject(ctx, propertyAttributes)) {
|
||||
propertyObject = RJSValidatedValueToObject(ctx, propertyAttributes);
|
||||
type = RJSValidatedStringProperty(ctx, propertyObject, typeString);
|
||||
|
||||
JSValueRef optionalValue = JSObjectGetProperty(ctx, propertyObject, optionalString, NULL);
|
||||
if (!JSValueIsUndefined(ctx, optionalValue)) {
|
||||
if (!JSValueIsBoolean(ctx, optionalValue)) {
|
||||
throw std::runtime_error("'optional' designation expected to be of type boolean");
|
||||
}
|
||||
prop.is_nullable = JSValueToBoolean(ctx, optionalValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = RJSValidatedStringForValue(ctx, propertyAttributes);
|
||||
}
|
||||
|
||||
if (type == "bool") {
|
||||
prop.type = PropertyTypeBool;
|
||||
}
|
||||
else if (type == "int") {
|
||||
prop.type = PropertyTypeInt;
|
||||
}
|
||||
else if (type == "float") {
|
||||
prop.type = PropertyTypeFloat;
|
||||
}
|
||||
else if (type == "double") {
|
||||
prop.type = PropertyTypeDouble;
|
||||
}
|
||||
else if (type == "string") {
|
||||
prop.type = PropertyTypeString;
|
||||
}
|
||||
else if (type == "date") {
|
||||
prop.type = PropertyTypeDate;
|
||||
}
|
||||
else if (type == "data") {
|
||||
prop.type = PropertyTypeData;
|
||||
}
|
||||
else if (type == "list") {
|
||||
if (!propertyObject) {
|
||||
throw std::runtime_error("List property must specify 'objectType'");
|
||||
}
|
||||
prop.type = PropertyTypeArray;
|
||||
prop.object_type = RJSValidatedStringProperty(ctx, propertyObject, objectTypeString);
|
||||
}
|
||||
else {
|
||||
prop.type = PropertyTypeObject;
|
||||
prop.is_nullable = true;
|
||||
|
||||
// The type could either be 'object' or the name of another object type in the same schema.
|
||||
if (type == "object") {
|
||||
if (!propertyObject) {
|
||||
throw std::runtime_error("Object property must specify 'objectType'");
|
||||
}
|
||||
prop.object_type = RJSValidatedStringProperty(ctx, propertyObject, objectTypeString);
|
||||
}
|
||||
else {
|
||||
prop.object_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyObject) {
|
||||
JSValueRef defaultValue = RJSValidatedPropertyValue(ctx, propertyObject, defaultString);
|
||||
if (!JSValueIsUndefined(ctx, defaultValue)) {
|
||||
JSValueProtect(ctx, defaultValue);
|
||||
objectDefaults.emplace(prop.name, defaultValue);
|
||||
}
|
||||
|
||||
JSValueRef indexedValue = RJSValidatedPropertyValue(ctx, propertyObject, indexedString);
|
||||
if (!JSValueIsUndefined(ctx, indexedValue)) {
|
||||
prop.is_indexed = JSValueToBoolean(ctx, indexedValue);
|
||||
}
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef objectSchemaObject, std::map<std::string, realm::ObjectDefaults> &defaults, std::map<std::string, JSObjectRef> &constructors) {
|
||||
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
||||
static JSStringRef primaryString = JSStringCreateWithUTF8CString("primaryKey");
|
||||
static JSStringRef propertiesString = JSStringCreateWithUTF8CString("properties");
|
||||
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
||||
|
||||
JSObjectRef objectConstructor = NULL;
|
||||
|
||||
if (JSObjectIsConstructor(ctx, objectSchemaObject)) {
|
||||
objectConstructor = objectSchemaObject;
|
||||
objectSchemaObject = RJSValidatedObjectProperty(ctx, objectConstructor, schemaString, "Realm object constructor must have a 'schema' property.");
|
||||
}
|
||||
|
||||
ObjectDefaults objectDefaults;
|
||||
ObjectSchema objectSchema;
|
||||
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
||||
|
||||
JSObjectRef propertiesObject = RJSValidatedObjectProperty(ctx, objectSchemaObject, propertiesString, "ObjectSchema must have a 'properties' object.");
|
||||
if (RJSIsValueArray(ctx, propertiesObject)) {
|
||||
size_t propertyCount = RJSValidatedListLength(ctx, propertiesObject);
|
||||
for (size_t i = 0; i < propertyCount; i++) {
|
||||
JSObjectRef propertyObject = RJSValidatedObjectAtIndex(ctx, propertiesObject, (unsigned int)i);
|
||||
std::string propertyName = RJSValidatedStringProperty(ctx, propertyObject, nameString);
|
||||
objectSchema.properties.emplace_back(RJSParseProperty(ctx, propertyObject, propertyName, objectDefaults));
|
||||
}
|
||||
}
|
||||
else {
|
||||
JSPropertyNameArrayRef propertyNames = JSObjectCopyPropertyNames(ctx, propertiesObject);
|
||||
size_t propertyCount = JSPropertyNameArrayGetCount(propertyNames);
|
||||
for (size_t i = 0; i < propertyCount; i++) {
|
||||
JSStringRef propertyName = JSPropertyNameArrayGetNameAtIndex(propertyNames, i);
|
||||
JSValueRef propertyValue = RJSValidatedPropertyValue(ctx, propertiesObject, propertyName);
|
||||
objectSchema.properties.emplace_back(RJSParseProperty(ctx, propertyValue, RJSStringForJSString(propertyName), objectDefaults));
|
||||
}
|
||||
JSPropertyNameArrayRelease(propertyNames);
|
||||
}
|
||||
|
||||
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
||||
if (!JSValueIsUndefined(ctx, primaryValue)) {
|
||||
objectSchema.primary_key = RJSValidatedStringForValue(ctx, primaryValue);
|
||||
Property *property = objectSchema.primary_key_property();
|
||||
if (!property) {
|
||||
throw std::runtime_error("Missing primary key property '" + objectSchema.primary_key + "'");
|
||||
}
|
||||
property->is_primary = true;
|
||||
}
|
||||
|
||||
// Store prototype so that objects of this type will have their prototype set to this prototype object.
|
||||
if (objectConstructor) {
|
||||
JSValueProtect(ctx, objectConstructor);
|
||||
constructors[objectSchema.name] = std::move(objectConstructor);
|
||||
}
|
||||
|
||||
defaults.emplace(objectSchema.name, std::move(objectDefaults));
|
||||
|
||||
return objectSchema;
|
||||
}
|
||||
|
||||
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject, std::map<std::string, realm::ObjectDefaults> &defaults, std::map<std::string, JSObjectRef> &constructors) {
|
||||
std::vector<ObjectSchema> schema;
|
||||
size_t length = RJSValidatedListLength(ctx, jsonObject);
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i);
|
||||
ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema, defaults, constructors);
|
||||
schema.emplace_back(std::move(objectSchema));
|
||||
}
|
||||
|
||||
return Schema(schema);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,14 +19,189 @@
|
|||
#pragma once
|
||||
|
||||
#include "js_util.hpp"
|
||||
#include "schema.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace realm {
|
||||
class Schema;
|
||||
using ObjectDefaults = std::map<std::string, JSValueRef>;
|
||||
}
|
||||
|
||||
JSClassRef RJSSchemaClass();
|
||||
JSObjectRef RJSSchemaCreate(JSContextRef ctx, realm::Schema *schema);
|
||||
|
||||
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject, std::map<std::string, realm::ObjectDefaults> &defaults, std::map<std::string, JSObjectRef> &constructors);
|
||||
namespace realm {
|
||||
namespace js {
|
||||
|
||||
template<typename T>
|
||||
struct Schema
|
||||
{
|
||||
using ContextType = typename T::Context;
|
||||
using ObjectType = typename T::Object;
|
||||
using ValueType = typename T::Value;
|
||||
using ReturnType = typename T::Return;
|
||||
using StringType = typename T::String;
|
||||
using ObjectDefaults = std::map<std::string, ValueType>;
|
||||
using ObjectDefaultsMap = std::map<std::string, ObjectDefaults>;
|
||||
using ConstructorMap = std::map<std::string, ObjectType>;
|
||||
|
||||
static Property parse_property(ContextType ctx, ValueType attributes, std::string propertyame, ObjectDefaults &objectDefaults);
|
||||
static ObjectSchema parse_object_schema(ContextType ctx, ObjectType objectSchemaObject, ObjectDefaultsMap &defaults, ConstructorMap &constructors);
|
||||
static realm::Schema parse_schema(ContextType ctx, ObjectType jsonObject, ObjectDefaultsMap &defaults, ConstructorMap &constructors);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Property Schema<T>::parse_property(ContextType ctx, ValueType attributes, std::string propertyName, ObjectDefaults &objectDefaults) {
|
||||
StringType defaultString("default");
|
||||
StringType indexedString("indexed");
|
||||
StringType typeString("type");
|
||||
StringType objectTypeString("objectType");
|
||||
StringType optionalString("optional");
|
||||
|
||||
Property prop;
|
||||
prop.name = propertyName;
|
||||
|
||||
JSObjectRef propertyObject = NULL;
|
||||
std::string type;
|
||||
|
||||
if (ValueIsObject(ctx, attributes)) {
|
||||
propertyObject = RJSValidatedValueToObject(ctx, attributes);
|
||||
type = RJSValidatedStringProperty(ctx, propertyObject, typeString);
|
||||
|
||||
ValueType optionalValue = ObjectGetProperty(ctx, propertyObject, optionalString, NULL);
|
||||
if (!ValueIsUndefined(ctx, optionalValue)) {
|
||||
prop.is_nullable = RJSValidatedValueToBoolean(ctx, optionalValue, "'optional' designation expected to be of type boolean");
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = RJSValidatedStringForValue(ctx, attributes);
|
||||
}
|
||||
|
||||
if (type == "bool") {
|
||||
prop.type = PropertyTypeBool;
|
||||
}
|
||||
else if (type == "int") {
|
||||
prop.type = PropertyTypeInt;
|
||||
}
|
||||
else if (type == "float") {
|
||||
prop.type = PropertyTypeFloat;
|
||||
}
|
||||
else if (type == "double") {
|
||||
prop.type = PropertyTypeDouble;
|
||||
}
|
||||
else if (type == "string") {
|
||||
prop.type = PropertyTypeString;
|
||||
}
|
||||
else if (type == "date") {
|
||||
prop.type = PropertyTypeDate;
|
||||
}
|
||||
else if (type == "data") {
|
||||
prop.type = PropertyTypeData;
|
||||
}
|
||||
else if (type == "list") {
|
||||
if (!propertyObject) {
|
||||
throw std::runtime_error("List property must specify 'objectType'");
|
||||
}
|
||||
prop.type = PropertyTypeArray;
|
||||
prop.object_type = RJSValidatedStringProperty(ctx, propertyObject, objectTypeString);
|
||||
}
|
||||
else {
|
||||
prop.type = PropertyTypeObject;
|
||||
prop.is_nullable = true;
|
||||
|
||||
// The type could either be 'object' or the name of another object type in the same schema.
|
||||
if (type == "object") {
|
||||
if (!propertyObject) {
|
||||
throw std::runtime_error("Object property must specify 'objectType'");
|
||||
}
|
||||
prop.object_type = RJSValidatedStringProperty(ctx, propertyObject, objectTypeString);
|
||||
}
|
||||
else {
|
||||
prop.object_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyObject) {
|
||||
ValueType defaultValue = RJSValidatedPropertyValue(ctx, propertyObject, defaultString);
|
||||
if (!ValueIsUndefined(ctx, defaultValue)) {
|
||||
ValueProtect(ctx, defaultValue);
|
||||
objectDefaults.emplace(prop.name, defaultValue);
|
||||
}
|
||||
|
||||
ValueType indexedValue = RJSValidatedPropertyValue(ctx, propertyObject, indexedString);
|
||||
if (!ValueIsUndefined(ctx, indexedValue)) {
|
||||
prop.is_indexed = RJSValidatedValueToBoolean(ctx, indexedValue);
|
||||
}
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectSchema Schema<T>::parse_object_schema(ContextType ctx, ObjectType objectSchemaObject, ObjectDefaultsMap &defaults, ConstructorMap &constructors) {
|
||||
StringType nameString("name");
|
||||
StringType primaryString("primaryKey");
|
||||
StringType propertiesString("properties");
|
||||
StringType schemaString("schema");
|
||||
|
||||
ObjectType objectConstructor = NULL;
|
||||
if (ValueIsConstructor(ctx, objectSchemaObject)) {
|
||||
objectConstructor = objectSchemaObject;
|
||||
objectSchemaObject = RJSValidatedObjectProperty(ctx, objectConstructor, schemaString, "Realm object constructor must have a 'schema' property.");
|
||||
}
|
||||
|
||||
ObjectDefaults objectDefaults;
|
||||
ObjectSchema objectSchema;
|
||||
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
||||
|
||||
ObjectType propertiesObject = RJSValidatedObjectProperty(ctx, objectSchemaObject, propertiesString, "ObjectSchema must have a 'properties' object.");
|
||||
if (RJSIsValueArray(ctx, propertiesObject)) {
|
||||
size_t propertyCount = RJSValidatedListLength(ctx, propertiesObject);
|
||||
for (size_t i = 0; i < propertyCount; i++) {
|
||||
ObjectType propertyObject = RJSValidatedObjectAtIndex(ctx, propertiesObject, (unsigned int)i);
|
||||
std::string propertyName = RJSValidatedStringProperty(ctx, propertyObject, nameString);
|
||||
objectSchema.properties.emplace_back(parse_property(ctx, propertyObject, propertyName, objectDefaults));
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto propertyNames = ObjectGetPropertyNames(ctx, propertiesObject);
|
||||
for (auto propertyName : propertyNames) {
|
||||
ValueType propertyValue = RJSValidatedPropertyValue(ctx, propertiesObject, StringType(propertyName.c_str()));
|
||||
objectSchema.properties.emplace_back(parse_property(ctx, propertyValue, propertyName, objectDefaults));
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
||||
if (!JSValueIsUndefined(ctx, primaryValue)) {
|
||||
objectSchema.primary_key = RJSValidatedStringForValue(ctx, primaryValue);
|
||||
Property *property = objectSchema.primary_key_property();
|
||||
if (!property) {
|
||||
throw std::runtime_error("Missing primary key property '" + objectSchema.primary_key + "'");
|
||||
}
|
||||
property->is_primary = true;
|
||||
}
|
||||
|
||||
// Store prototype so that objects of this type will have their prototype set to this prototype object.
|
||||
if (objectConstructor) {
|
||||
ValueProtect(ctx, objectConstructor);
|
||||
constructors[objectSchema.name] = std::move(objectConstructor);
|
||||
}
|
||||
|
||||
defaults.emplace(objectSchema.name, std::move(objectDefaults));
|
||||
|
||||
return objectSchema;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
realm::Schema Schema<T>::parse_schema(ContextType ctx, ObjectType jsonObject, ObjectDefaultsMap &defaults, ConstructorMap &constructors) {
|
||||
std::vector<ObjectSchema> schema;
|
||||
size_t length = RJSValidatedListLength(ctx, jsonObject);
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i);
|
||||
ObjectSchema objectSchema = parse_object_schema(ctx, jsonObjectSchema, defaults, constructors);
|
||||
schema.emplace_back(std::move(objectSchema));
|
||||
}
|
||||
return realm::Schema(schema);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -123,19 +123,19 @@ std::string RJSValidatedStringForValue(JSContextRef ctx, JSValueRef value, const
|
|||
JSStringRef RJSStringForString(const std::string &str);
|
||||
JSValueRef RJSValueForString(JSContextRef ctx, const std::string &str);
|
||||
|
||||
inline void RJSValidateArgumentCount(size_t argumentCount, size_t expected, const char *message = NULL) {
|
||||
inline void RJSValidateArgumentCount(size_t argumentCount, size_t expected, const char *message = nullptr) {
|
||||
if (argumentCount != expected) {
|
||||
throw std::invalid_argument(message ?: "Invalid arguments");
|
||||
}
|
||||
}
|
||||
|
||||
inline void RJSValidateArgumentCountIsAtLeast(size_t argumentCount, size_t expected, const char *message = NULL) {
|
||||
inline void RJSValidateArgumentCountIsAtLeast(size_t argumentCount, size_t expected, const char *message = nullptr) {
|
||||
if (argumentCount < expected) {
|
||||
throw std::invalid_argument(message ?: "Invalid arguments");
|
||||
}
|
||||
}
|
||||
|
||||
inline void RJSValidateArgumentRange(size_t argumentCount, size_t min, size_t max, const char *message = NULL) {
|
||||
inline void RJSValidateArgumentRange(size_t argumentCount, size_t min, size_t max, const char *message = nullptr) {
|
||||
if (argumentCount < min || argumentCount > max) {
|
||||
throw std::invalid_argument(message ?: "Invalid arguments");
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ bool RJSIsValueArray(JSContextRef ctx, JSValueRef value);
|
|||
bool RJSIsValueArrayBuffer(JSContextRef ctx, JSValueRef value);
|
||||
bool RJSIsValueDate(JSContextRef ctx, JSValueRef value);
|
||||
|
||||
static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef value, const char *message = NULL) {
|
||||
static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef value, const char *message = nullptr) {
|
||||
JSObjectRef object = JSValueToObject(ctx, value, NULL);
|
||||
if (!object) {
|
||||
throw std::runtime_error(message ?: "Value is not an object.");
|
||||
|
@ -167,7 +167,7 @@ static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef
|
|||
return object;
|
||||
}
|
||||
|
||||
static inline JSObjectRef RJSValidatedValueToDate(JSContextRef ctx, JSValueRef value, const char *message = NULL) {
|
||||
static inline JSObjectRef RJSValidatedValueToDate(JSContextRef ctx, JSValueRef value, const char *message = nullptr) {
|
||||
JSObjectRef object = JSValueToObject(ctx, value, NULL);
|
||||
if (!object || !RJSIsValueDate(ctx, object)) {
|
||||
throw std::runtime_error(message ?: "Value is not a date.");
|
||||
|
@ -175,7 +175,7 @@ static inline JSObjectRef RJSValidatedValueToDate(JSContextRef ctx, JSValueRef v
|
|||
return object;
|
||||
}
|
||||
|
||||
static inline JSObjectRef RJSValidatedValueToFunction(JSContextRef ctx, JSValueRef value, const char *message = NULL) {
|
||||
static inline JSObjectRef RJSValidatedValueToFunction(JSContextRef ctx, JSValueRef value, const char *message = nullptr) {
|
||||
JSObjectRef object = JSValueToObject(ctx, value, NULL);
|
||||
if (!object || !JSObjectIsFunction(ctx, object)) {
|
||||
throw std::runtime_error(message ?: "Value is not a function.");
|
||||
|
@ -199,9 +199,9 @@ static inline double RJSValidatedValueToNumber(JSContextRef ctx, JSValueRef valu
|
|||
return number;
|
||||
}
|
||||
|
||||
static inline double RJSValidatedValueToBoolean(JSContextRef ctx, JSValueRef value) {
|
||||
static inline double RJSValidatedValueToBoolean(JSContextRef ctx, JSValueRef value, const char *err = nullptr) {
|
||||
if (!JSValueIsBoolean(ctx, value)) {
|
||||
throw std::invalid_argument("Value is not a boolean.");
|
||||
throw std::invalid_argument(err ?: "Value is not a boolean.");
|
||||
}
|
||||
return JSValueToBoolean(ctx, value);
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ static inline JSValueRef RJSValidatedPropertyAtIndex(JSContextRef ctx, JSObjectR
|
|||
return propertyValue;
|
||||
}
|
||||
|
||||
static inline JSObjectRef RJSValidatedObjectProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property, const char *err = NULL) {
|
||||
static inline JSObjectRef RJSValidatedObjectProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property, const char *err = nullptr) {
|
||||
JSValueRef propertyValue = RJSValidatedPropertyValue(ctx, object, property);
|
||||
if (JSValueIsUndefined(ctx, propertyValue)) {
|
||||
throw std::runtime_error(err ?: "Object property '" + RJSStringForJSString(property) + "' is undefined");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "types.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace realm {
|
||||
namespace js {
|
||||
|
@ -33,10 +34,31 @@ static inline bool ValueIsObject(jsc::Types::Context ctx, jsc::Types::Value valu
|
|||
static inline bool ValueIsConstructor(jsc::Types::Context ctx, jsc::Types::Value value) { return ValueIsObject(ctx, value) && JSObjectIsConstructor(ctx, (JSObjectRef)value); }
|
||||
|
||||
static inline jsc::Types::Object ValueToObject(jsc::Types::Context ctx, jsc::Types::Value value) { return (JSObjectRef)value; }
|
||||
|
||||
|
||||
static inline void ValueProtect(jsc::Types::Context ctx, jsc::Types::Value value) { JSValueProtect(ctx, value); }
|
||||
static inline void ValueUnprotect(jsc::Types::Context ctx, jsc::Types::Value value) { JSValueUnprotect(ctx, value); }
|
||||
|
||||
static inline std::string StringTypeToString(JSStringRef jsString) {
|
||||
std::string str;
|
||||
size_t maxSize = JSStringGetMaximumUTF8CStringSize(jsString);
|
||||
str.resize(maxSize);
|
||||
str.resize(JSStringGetUTF8CString(jsString, &str[0], maxSize) - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline std::vector<std::string> ObjectGetPropertyNames(jsc::Types::Context ctx, jsc::Types::Object object) {
|
||||
JSPropertyNameArrayRef propertyNames = JSObjectCopyPropertyNames(ctx, object);
|
||||
size_t propertyCount = JSPropertyNameArrayGetCount(propertyNames);
|
||||
std::vector<std::string> outNames;
|
||||
for (size_t i = 0; i < propertyCount; i++) {
|
||||
outNames.push_back(StringTypeToString(JSPropertyNameArrayGetNameAtIndex(propertyNames, i)));
|
||||
}
|
||||
JSPropertyNameArrayRelease(propertyNames);
|
||||
return outNames;
|
||||
}
|
||||
static inline jsc::Types::Value ObjectGetProperty(jsc::Types::Context ctx, jsc::Types::Object object, jsc::Types::String propertyName, jsc::Types::Exception *exception) {
|
||||
return JSObjectGetProperty(ctx, object, propertyName, exception);
|
||||
}
|
||||
static inline void ObjectCallAsFunction(jsc::Types::Context ctx, jsc::Types::Object function, jsc::Types::Object thisObject, size_t argsCount, const jsc::Types::Value args[], jsc::Types::Exception &exception) {
|
||||
JSObjectCallAsFunction(ctx, function, thisObject, argsCount, args, &exception);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace jsc {
|
|||
class String {
|
||||
public:
|
||||
String(const char * str) : m_str(JSStringCreateWithUTF8CString(str)) {}
|
||||
String(const String &other) : m_str(JSStringRetain(other)) {}
|
||||
~String() { JSStringRelease(m_str); }
|
||||
operator JSStringRef() const { return m_str; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue