Split up JS abstractions into type-specific files

This commit is contained in:
Scott Kyle 2016-04-18 01:15:54 -07:00
parent d57483c675
commit 5c56a99403
23 changed files with 1355 additions and 863 deletions

View File

@ -173,6 +173,22 @@
F60102E31CBBB19700EC01BA /* node_object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = node_object_accessor.hpp; sourceTree = "<group>"; };
F60102E71CBBB36500EC01BA /* jsc_object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = jsc_object_accessor.hpp; sourceTree = "<group>"; };
F60102F71CBDA6D400EC01BA /* js_collection.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_collection.hpp; sourceTree = "<group>"; };
F60103071CC4B3DF00EC01BA /* node_protected.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_protected.hpp; sourceTree = "<group>"; };
F60103081CC4B4F900EC01BA /* jsc_protected.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_protected.hpp; sourceTree = "<group>"; };
F60103091CC4B5E800EC01BA /* jsc_context.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_context.hpp; sourceTree = "<group>"; };
F601030A1CC4B64E00EC01BA /* node_context.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_context.hpp; sourceTree = "<group>"; };
F601030B1CC4B6C900EC01BA /* jsc_value.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_value.hpp; sourceTree = "<group>"; };
F601030C1CC4B72B00EC01BA /* node_value.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_value.hpp; sourceTree = "<group>"; };
F601030D1CC4B76F00EC01BA /* jsc_object.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_object.hpp; sourceTree = "<group>"; };
F601030E1CC4B7C900EC01BA /* node_object.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_object.hpp; sourceTree = "<group>"; };
F601030F1CC4B80800EC01BA /* jsc_function.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_function.hpp; sourceTree = "<group>"; };
F60103101CC4B86000EC01BA /* node_function.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_function.hpp; sourceTree = "<group>"; };
F60103111CC4BA6500EC01BA /* jsc_exception.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_exception.hpp; sourceTree = "<group>"; };
F60103121CC4CBF000EC01BA /* node_exception.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_exception.hpp; sourceTree = "<group>"; };
F60103131CC4CC4500EC01BA /* jsc_string.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_string.hpp; sourceTree = "<group>"; };
F60103141CC4CC8C00EC01BA /* jsc_return_value.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_return_value.hpp; sourceTree = "<group>"; };
F60103151CC4CCFD00EC01BA /* node_return_value.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_return_value.hpp; sourceTree = "<group>"; };
F60103161CC4CD2F00EC01BA /* node_string.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_string.hpp; sourceTree = "<group>"; };
F61378781C18EAAC008BFC51 /* js */ = {isa = PBXFileReference; lastKnownFileType = folder; path = js; sourceTree = "<group>"; };
F620F0521CAF0B600082977B /* js_class.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_class.hpp; sourceTree = "<group>"; };
F620F0531CAF2EF70082977B /* jsc_class.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsc_class.hpp; sourceTree = "<group>"; };
@ -271,20 +287,17 @@
children = (
F6BCCFDF1C83809A00FE31AE /* lib */,
F62A35131C18E6E2004A917D /* iOS */,
F60103051CC4ADE500EC01BA /* JS */,
F6874A441CAD2ACD00EEEE36 /* JSC */,
F62BF9001CAC72C40022BCDC /* Node */,
F62A35141C18E783004A917D /* Object Store */,
F60102F71CBDA6D400EC01BA /* js_collection.hpp */,
029048041C0428DF00ABDED4 /* js_list.hpp */,
F620F0591CB7B4C80082977B /* js_object_accessor.hpp */,
029048061C0428DF00ABDED4 /* js_realm_object.hpp */,
029048071C0428DF00ABDED4 /* js_realm.cpp */,
029048081C0428DF00ABDED4 /* js_realm.hpp */,
0290480A1C0428DF00ABDED4 /* js_results.hpp */,
0290480C1C0428DF00ABDED4 /* js_schema.hpp */,
F620F0521CAF0B600082977B /* js_class.hpp */,
F6874A3E1CACA5A900EEEE36 /* js_types.hpp */,
F6267BC91CADC30000AC36B1 /* js_util.hpp */,
029048351C042A3C00ABDED4 /* platform.hpp */,
0290480F1C0428DF00ABDED4 /* rpc.cpp */,
029048101C0428DF00ABDED4 /* rpc.hpp */,
@ -346,6 +359,17 @@
name = Frameworks;
sourceTree = "<group>";
};
F60103051CC4ADE500EC01BA /* JS */ = {
isa = PBXGroup;
children = (
F620F0521CAF0B600082977B /* js_class.hpp */,
F6874A3E1CACA5A900EEEE36 /* js_types.hpp */,
F6267BC91CADC30000AC36B1 /* js_util.hpp */,
F620F0591CB7B4C80082977B /* js_object_accessor.hpp */,
);
name = JS;
sourceTree = "<group>";
};
F62A35131C18E6E2004A917D /* iOS */ = {
isa = PBXGroup;
children = (
@ -408,6 +432,14 @@
F620F0571CB766DA0082977B /* node_init.cpp */,
F620F0551CB655A50082977B /* node_class.hpp */,
F6874A351CAC792D00EEEE36 /* node_types.hpp */,
F60103161CC4CD2F00EC01BA /* node_string.hpp */,
F601030A1CC4B64E00EC01BA /* node_context.hpp */,
F601030C1CC4B72B00EC01BA /* node_value.hpp */,
F601030E1CC4B7C900EC01BA /* node_object.hpp */,
F60103101CC4B86000EC01BA /* node_function.hpp */,
F60103121CC4CBF000EC01BA /* node_exception.hpp */,
F60103071CC4B3DF00EC01BA /* node_protected.hpp */,
F60103151CC4CCFD00EC01BA /* node_return_value.hpp */,
F60102E31CBBB19700EC01BA /* node_object_accessor.hpp */,
);
name = Node;
@ -482,6 +514,14 @@
029048011C0428DF00ABDED4 /* jsc_init.cpp */,
F620F0531CAF2EF70082977B /* jsc_class.hpp */,
025678951CAB392000FB8501 /* jsc_types.hpp */,
F60103131CC4CC4500EC01BA /* jsc_string.hpp */,
F60103091CC4B5E800EC01BA /* jsc_context.hpp */,
F601030B1CC4B6C900EC01BA /* jsc_value.hpp */,
F601030D1CC4B76F00EC01BA /* jsc_object.hpp */,
F601030F1CC4B80800EC01BA /* jsc_function.hpp */,
F60103111CC4BA6500EC01BA /* jsc_exception.hpp */,
F60103081CC4B4F900EC01BA /* jsc_protected.hpp */,
F60103141CC4CC8C00EC01BA /* jsc_return_value.hpp */,
F60102E71CBBB36500EC01BA /* jsc_object_accessor.hpp */,
);
name = JSC;

View File

@ -19,6 +19,7 @@
#pragma once
#include "jsc_types.hpp"
#include "js_class.hpp"
#include "js_util.hpp"

32
src/jsc/jsc_context.hpp Normal file
View File

@ -0,0 +1,32 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
template<>
inline JSGlobalContextRef jsc::Context::get_global_context(JSContextRef ctx) {
return JSContextGetGlobalContext(ctx);
}
} // js
} // realm

33
src/jsc/jsc_exception.hpp Normal file
View File

@ -0,0 +1,33 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
template<>
inline JSValueRef jsc::Exception::value(JSContextRef ctx, const std::string &message) {
JSValueRef value = jsc::Value::from_string(ctx, message);
return JSObjectMakeError(ctx, 1, &value, NULL);
}
} // js
} // realm

47
src/jsc/jsc_function.hpp Normal file
View File

@ -0,0 +1,47 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
template<>
inline JSValueRef jsc::Function::call(JSContextRef ctx, const JSObjectRef &function, const JSObjectRef &this_object, size_t argc, const JSValueRef arguments[]) {
JSValueRef exception = nullptr;
JSValueRef result = JSObjectCallAsFunction(ctx, function, this_object, argc, arguments, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return result;
}
template<>
inline JSObjectRef jsc::Function::construct(JSContextRef ctx, const JSObjectRef &function, size_t argc, const JSValueRef arguments[]) {
JSValueRef exception = nullptr;
JSObjectRef result = JSObjectCallAsConstructor(ctx, function, argc, arguments, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return result;
}
} // js
} // realm

View File

@ -19,5 +19,14 @@
#pragma once
#include "jsc_init.h"
#include "jsc_string.hpp"
#include "jsc_protected.hpp"
#include "jsc_context.hpp"
#include "jsc_value.hpp"
#include "jsc_object.hpp"
#include "jsc_function.hpp"
#include "jsc_exception.hpp"
#include "jsc_return_value.hpp"
#include "jsc_object_accessor.hpp"
#include "js_realm.hpp"

147
src/jsc/jsc_object.hpp Normal file
View File

@ -0,0 +1,147 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
template<>
inline bool jsc::Object::has_property(JSContextRef ctx, const JSObjectRef &object, const jsc::String &key) {
return JSObjectHasProperty(ctx, object, key);
}
template<>
inline bool jsc::Object::has_property(JSContextRef ctx, const JSObjectRef &object, uint32_t index) {
return JSObjectHasProperty(ctx, object, jsc::String(util::to_string(index)));
}
template<>
inline JSValueRef jsc::Object::get_property(JSContextRef ctx, const JSObjectRef &object, const jsc::String &key) {
JSValueRef exception = nullptr;
JSValueRef value = JSObjectGetProperty(ctx, object, key, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return value;
}
template<>
inline JSValueRef jsc::Object::get_property(JSContextRef ctx, const JSObjectRef &object, uint32_t index) {
JSValueRef exception = nullptr;
JSValueRef value = JSObjectGetPropertyAtIndex(ctx, object, index, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return value;
}
template<>
inline void jsc::Object::set_property(JSContextRef ctx, const JSObjectRef &object, const jsc::String &key, const JSValueRef &value, PropertyAttributes attributes) {
JSValueRef exception = nullptr;
JSObjectSetProperty(ctx, object, key, value, attributes << 1, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
}
template<>
inline void jsc::Object::set_property(JSContextRef ctx, const JSObjectRef &object, uint32_t index, const JSValueRef &value) {
JSValueRef exception = nullptr;
JSObjectSetPropertyAtIndex(ctx, object, index, value, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
}
template<>
inline std::vector<jsc::String> jsc::Object::get_property_names(JSContextRef ctx, const JSObjectRef &object) {
JSPropertyNameArrayRef property_names = JSObjectCopyPropertyNames(ctx, object);
size_t property_count = JSPropertyNameArrayGetCount(property_names);
std::vector<jsc::String> names;
names.reserve(property_count);
for (size_t i = 0; i < property_count; i++) {
names.push_back(JSPropertyNameArrayGetNameAtIndex(property_names, i));
}
JSPropertyNameArrayRelease(property_names);
return names;
}
template<>
inline JSValueRef jsc::Object::get_prototype(JSContextRef ctx, const JSObjectRef &object) {
return JSObjectGetPrototype(ctx, object);
}
template<>
inline void jsc::Object::set_prototype(JSContextRef ctx, const JSObjectRef &object, const JSValueRef &prototype) {
JSObjectSetPrototype(ctx, object, prototype);
}
template<>
inline JSObjectRef jsc::Object::create_empty(JSContextRef ctx) {
return JSObjectMake(ctx, nullptr, nullptr);
}
template<>
inline JSObjectRef jsc::Object::create_array(JSContextRef ctx, uint32_t length, const JSValueRef values[]) {
JSValueRef exception = nullptr;
JSObjectRef array = JSObjectMakeArray(ctx, length, values, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return array;
}
template<>
inline JSObjectRef jsc::Object::create_date(JSContextRef ctx, double time) {
JSValueRef number = jsc::Value::from_number(ctx, time);
return JSObjectMakeDate(ctx, 1, &number, nullptr);
}
template<>
template<typename ClassType>
inline JSObjectRef jsc::Object::create_instance(JSContextRef ctx, typename ClassType::Internal* internal) {
return jsc::ObjectWrap<ClassType>::create_instance(ctx, internal);
}
template<>
template<typename ClassType>
inline bool jsc::Object::is_instance(JSContextRef ctx, const JSObjectRef &object) {
return jsc::ObjectWrap<ClassType>::has_instance(ctx, object);
}
template<>
template<typename ClassType>
inline typename ClassType::Internal* jsc::Object::get_internal(const JSObjectRef &object) {
return *static_cast<jsc::ObjectWrap<ClassType> *>(JSObjectGetPrivate(object));
}
template<>
template<typename ClassType>
inline void jsc::Object::set_internal(const JSObjectRef &object, typename ClassType::Internal* ptr) {
auto wrap = static_cast<jsc::ObjectWrap<ClassType> *>(JSObjectGetPrivate(object));
*wrap = ptr;
}
} // js
} // realm

78
src/jsc/jsc_protected.hpp Normal file
View File

@ -0,0 +1,78 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace jsc {
template<typename MemberType>
class Protected {
const MemberType m_value;
public:
Protected(MemberType value) : m_value(value) {}
operator MemberType() const {
return m_value;
}
};
} // jsc
namespace js {
template<>
class Protected<JSGlobalContextRef> : public jsc::Protected<JSGlobalContextRef> {
public:
Protected(JSGlobalContextRef ctx) : jsc::Protected<JSGlobalContextRef>(ctx) {
JSGlobalContextRetain(*this);
}
~Protected() {
JSGlobalContextRelease(*this);
}
};
template<>
class Protected<JSValueRef> : public jsc::Protected<JSValueRef> {
const JSGlobalContextRef m_context;
public:
Protected(JSContextRef ctx, JSValueRef value) : jsc::Protected<JSValueRef>(value), m_context(JSContextGetGlobalContext(ctx)) {
JSValueProtect(m_context, *this);
}
~Protected() {
JSValueUnprotect(m_context, *this);
}
};
template<>
class Protected<JSObjectRef> : public Protected<JSValueRef> {
public:
Protected(JSContextRef ctx, JSObjectRef object) : Protected<JSValueRef>(ctx, object) {}
operator JSObjectRef() const {
JSValueRef value = static_cast<JSValueRef>(*this);
return (JSObjectRef)value;
}
};
} // js
} // realm

View File

@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
template<>
class ReturnValue<jsc::Types> {
const JSContextRef m_context;
JSValueRef m_value = nullptr;
public:
ReturnValue(JSContextRef ctx) : m_context(ctx) {}
void set(const JSValueRef &value) {
m_value = value;
}
void set(const std::string &string) {
m_value = JSValueMakeString(m_context, jsc::String(string));
}
void set(bool boolean) {
m_value = JSValueMakeBoolean(m_context, boolean);
}
void set(double number) {
m_value = JSValueMakeNumber(m_context, number);
}
void set(int32_t number) {
m_value = JSValueMakeNumber(m_context, number);
}
void set(uint32_t number) {
m_value = JSValueMakeNumber(m_context, number);
}
void set_null() {
m_value = JSValueMakeNull(m_context);
}
void set_undefined() {
m_value = JSValueMakeUndefined(m_context);
}
operator JSValueRef() const {
return m_value;
}
};
} // js
} // realm

59
src/jsc/jsc_string.hpp Normal file
View File

@ -0,0 +1,59 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
template<>
class String<jsc::Types> {
using StringType = String<jsc::Types>;
JSStringRef m_str;
public:
String(const char *s) : m_str(JSStringCreateWithUTF8CString(s)) {}
String(const JSStringRef &s) : m_str(JSStringRetain(s)) {}
String(const std::string &str) : String(str.c_str()) {}
String(const StringType &o) : String(o.m_str) {}
String(StringType &&o) : m_str(o.m_str) {
o.m_str = nullptr;
}
~String() {
if (m_str) {
JSStringRelease(m_str);
}
}
operator JSStringRef() const {
return m_str;
}
operator std::string() const {
size_t max_size = JSStringGetMaximumUTF8CStringSize(m_str);
std::string string;
string.resize(max_size);
string.resize(JSStringGetUTF8CString(m_str, &string[0], max_size) - 1);
return string;
}
};
} // js
} // realm

View File

@ -47,19 +47,7 @@ struct Types {
using StringPropertyEnumeratorCallback = JSObjectGetPropertyNamesCallback;
};
template<typename T>
class Protected {
const T m_value;
public:
Protected(T value) : m_value(value) {}
operator T() const {
return m_value;
}
};
template<typename T>
template<typename ClassType>
class ObjectWrap;
using String = js::String<Types>;
@ -71,430 +59,4 @@ using Exception = js::Exception<Types>;
using ReturnValue = js::ReturnValue<Types>;
} // jsc
namespace js {
template<>
class String<jsc::Types> {
using StringType = String<jsc::Types>;
JSStringRef m_str;
public:
String(const char *s) : m_str(JSStringCreateWithUTF8CString(s)) {}
String(const JSStringRef &s) : m_str(JSStringRetain(s)) {}
String(const std::string &str) : String(str.c_str()) {}
String(const StringType &o) : String(o.m_str) {}
String(StringType &&o) : m_str(o.m_str) {
o.m_str = nullptr;
}
~String() {
if (m_str) {
JSStringRelease(m_str);
}
}
operator JSStringRef() const {
return m_str;
}
operator std::string() const {
size_t max_size = JSStringGetMaximumUTF8CStringSize(m_str);
std::string string;
string.resize(max_size);
string.resize(JSStringGetUTF8CString(m_str, &string[0], max_size) - 1);
return string;
}
};
template<>
class ReturnValue<jsc::Types> {
const JSContextRef m_context;
JSValueRef m_value = nullptr;
public:
ReturnValue(JSContextRef ctx) : m_context(ctx) {}
void set(const JSValueRef &value) {
m_value = value;
}
void set(const std::string &string) {
m_value = JSValueMakeString(m_context, jsc::String(string));
}
void set(bool boolean) {
m_value = JSValueMakeBoolean(m_context, boolean);
}
void set(double number) {
m_value = JSValueMakeNumber(m_context, number);
}
void set(int32_t number) {
m_value = JSValueMakeNumber(m_context, number);
}
void set(uint32_t number) {
m_value = JSValueMakeNumber(m_context, number);
}
void set_null() {
m_value = JSValueMakeNull(m_context);
}
void set_undefined() {
m_value = JSValueMakeUndefined(m_context);
}
operator JSValueRef() const {
return m_value;
}
};
template<>
class Protected<JSGlobalContextRef> : public jsc::Protected<JSGlobalContextRef> {
public:
Protected(JSGlobalContextRef ctx) : jsc::Protected<JSGlobalContextRef>(ctx) {
JSGlobalContextRetain(*this);
}
~Protected() {
JSGlobalContextRelease(*this);
}
};
template<>
class Protected<JSValueRef> : public jsc::Protected<JSValueRef> {
const JSGlobalContextRef m_context;
public:
Protected(JSContextRef ctx, JSValueRef value) : jsc::Protected<JSValueRef>(value), m_context(JSContextGetGlobalContext(ctx)) {
JSValueProtect(m_context, *this);
}
~Protected() {
JSValueUnprotect(m_context, *this);
}
};
template<>
class Protected<JSObjectRef> : public Protected<JSValueRef> {
public:
Protected(JSContextRef ctx, JSObjectRef object) : Protected<JSValueRef>(ctx, object) {}
operator JSObjectRef() const {
JSValueRef value = static_cast<JSValueRef>(*this);
return (JSObjectRef)value;
}
};
static inline bool is_object_of_type(JSContextRef ctx, JSValueRef value, jsc::String type) {
JSObjectRef global_object = JSContextGetGlobalObject(ctx);
JSValueRef exception = nullptr;
JSValueRef constructor = JSObjectGetProperty(ctx, global_object, type, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
bool result = JSValueIsInstanceOfConstructor(ctx, value, jsc::Value::validated_to_constructor(ctx, constructor), &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return result;
}
template<>
inline JSGlobalContextRef jsc::Context::get_global_context(JSContextRef ctx) {
return JSContextGetGlobalContext(ctx);
}
template<>
inline bool jsc::Value::is_array(JSContextRef ctx, const JSValueRef &value) {
// JSValueIsArray() is not available until iOS 9.
static const jsc::String type = "Array";
return is_object_of_type(ctx, value, type);
}
template<>
inline bool jsc::Value::is_array_buffer(JSContextRef ctx, const JSValueRef &value) {
static const jsc::String type = "ArrayBuffer";
return is_object_of_type(ctx, value, type);
}
template<>
inline bool jsc::Value::is_date(JSContextRef ctx, const JSValueRef &value) {
static const jsc::String type = "Date";
return is_object_of_type(ctx, value, type);
}
template<>
inline bool jsc::Value::is_boolean(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsBoolean(ctx, value);
}
template<>
inline bool jsc::Value::is_constructor(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsObject(ctx, value) && JSObjectIsConstructor(ctx, (JSObjectRef)value);
}
template<>
inline bool jsc::Value::is_function(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsObject(ctx, value) && JSObjectIsFunction(ctx, (JSObjectRef)value);
}
template<>
inline bool jsc::Value::is_null(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsNull(ctx, value);
}
template<>
inline bool jsc::Value::is_number(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsNumber(ctx, value);
}
template<>
inline bool jsc::Value::is_object(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsObject(ctx, value);
}
template<>
inline bool jsc::Value::is_string(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsString(ctx, value);
}
template<>
inline bool jsc::Value::is_undefined(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsUndefined(ctx, value);
}
template<>
inline bool jsc::Value::is_valid(const JSValueRef &value) {
return value != nullptr;
}
template<>
inline JSValueRef jsc::Value::from_boolean(JSContextRef ctx, bool boolean) {
return JSValueMakeBoolean(ctx, boolean);
}
template<>
inline JSValueRef jsc::Value::from_null(JSContextRef ctx) {
return JSValueMakeNull(ctx);
}
template<>
inline JSValueRef jsc::Value::from_number(JSContextRef ctx, double number) {
return JSValueMakeNumber(ctx, number);
}
template<>
inline JSValueRef jsc::Value::from_string(JSContextRef ctx, const jsc::String &string) {
return JSValueMakeString(ctx, string);
}
template<>
inline JSValueRef jsc::Value::from_undefined(JSContextRef ctx) {
return JSValueMakeUndefined(ctx);
}
template<>
inline bool jsc::Value::to_boolean(JSContextRef ctx, const JSValueRef &value) {
return JSValueToBoolean(ctx, value);
}
template<>
inline double jsc::Value::to_number(JSContextRef ctx, const JSValueRef &value) {
JSValueRef exception = nullptr;
double number = JSValueToNumber(ctx, value, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
if (isnan(number)) {
throw std::invalid_argument("Value not convertible to a number.");
}
return number;
}
template<>
inline jsc::String jsc::Value::to_string(JSContextRef ctx, const JSValueRef &value) {
JSValueRef exception = nullptr;
jsc::String string = JSValueToStringCopy(ctx, value, &exception);
// Since the string's retain value is +2 here, we need to manually release it before returning.
JSStringRelease(string);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return string;
}
template<>
inline JSObjectRef jsc::Value::to_object(JSContextRef ctx, const JSValueRef &value) {
JSValueRef exception = nullptr;
JSObjectRef object = JSValueToObject(ctx, value, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return object;
}
template<>
inline JSObjectRef jsc::Value::to_array(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSObjectRef jsc::Value::to_constructor(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSObjectRef jsc::Value::to_date(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSObjectRef jsc::Value::to_function(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSValueRef jsc::Function::call(JSContextRef ctx, const JSObjectRef &function, const JSObjectRef &this_object, size_t argc, const JSValueRef arguments[]) {
JSValueRef exception = nullptr;
JSValueRef result = JSObjectCallAsFunction(ctx, function, this_object, argc, arguments, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return result;
}
template<>
inline JSObjectRef jsc::Function::construct(JSContextRef ctx, const JSObjectRef &function, size_t argc, const JSValueRef arguments[]) {
JSValueRef exception = nullptr;
JSObjectRef result = JSObjectCallAsConstructor(ctx, function, argc, arguments, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return result;
}
template<>
inline bool jsc::Object::has_property(JSContextRef ctx, const JSObjectRef &object, const jsc::String &key) {
return JSObjectHasProperty(ctx, object, key);
}
template<>
inline bool jsc::Object::has_property(JSContextRef ctx, const JSObjectRef &object, uint32_t index) {
return JSObjectHasProperty(ctx, object, jsc::String(util::to_string(index)));
}
template<>
inline JSValueRef jsc::Object::get_property(JSContextRef ctx, const JSObjectRef &object, const jsc::String &key) {
JSValueRef exception = nullptr;
JSValueRef value = JSObjectGetProperty(ctx, object, key, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return value;
}
template<>
inline JSValueRef jsc::Object::get_property(JSContextRef ctx, const JSObjectRef &object, uint32_t index) {
JSValueRef exception = nullptr;
JSValueRef value = JSObjectGetPropertyAtIndex(ctx, object, index, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return value;
}
template<>
inline void jsc::Object::set_property(JSContextRef ctx, const JSObjectRef &object, const jsc::String &key, const JSValueRef &value, PropertyAttributes attributes) {
JSValueRef exception = nullptr;
JSObjectSetProperty(ctx, object, key, value, attributes << 1, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
}
template<>
inline void jsc::Object::set_property(JSContextRef ctx, const JSObjectRef &object, uint32_t index, const JSValueRef &value) {
JSValueRef exception = nullptr;
JSObjectSetPropertyAtIndex(ctx, object, index, value, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
}
template<>
inline std::vector<jsc::String> jsc::Object::get_property_names(JSContextRef ctx, const JSObjectRef &object) {
JSPropertyNameArrayRef property_names = JSObjectCopyPropertyNames(ctx, object);
size_t property_count = JSPropertyNameArrayGetCount(property_names);
std::vector<jsc::String> names;
names.reserve(property_count);
for (size_t i = 0; i < property_count; i++) {
names.push_back(JSPropertyNameArrayGetNameAtIndex(property_names, i));
}
JSPropertyNameArrayRelease(property_names);
return names;
}
template<>
inline JSValueRef jsc::Object::get_prototype(JSContextRef ctx, const JSObjectRef &object) {
return JSObjectGetPrototype(ctx, object);
}
template<>
inline void jsc::Object::set_prototype(JSContextRef ctx, const JSObjectRef &object, const JSValueRef &prototype) {
JSObjectSetPrototype(ctx, object, prototype);
}
template<>
inline JSObjectRef jsc::Object::create_empty(JSContextRef ctx) {
return JSObjectMake(ctx, nullptr, nullptr);
}
template<>
inline JSObjectRef jsc::Object::create_array(JSContextRef ctx, uint32_t length, const JSValueRef values[]) {
JSValueRef exception = nullptr;
JSObjectRef array = JSObjectMakeArray(ctx, length, values, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return array;
}
template<>
inline JSObjectRef jsc::Object::create_date(JSContextRef ctx, double time) {
JSValueRef number = jsc::Value::from_number(ctx, time);
return JSObjectMakeDate(ctx, 1, &number, nullptr);
}
template<>
template<typename ClassType>
inline JSObjectRef jsc::Object::create_instance(JSContextRef ctx, typename ClassType::Internal* internal) {
return jsc::ObjectWrap<ClassType>::create_instance(ctx, internal);
}
template<>
template<typename ClassType>
inline bool jsc::Object::is_instance(JSContextRef ctx, const JSObjectRef &object) {
return jsc::ObjectWrap<ClassType>::has_instance(ctx, object);
}
template<>
template<typename ClassType>
inline typename ClassType::Internal* jsc::Object::get_internal(const JSObjectRef &object) {
return *static_cast<jsc::ObjectWrap<ClassType> *>(JSObjectGetPrivate(object));
}
template<>
template<typename ClassType>
inline void jsc::Object::set_internal(const JSObjectRef &object, typename ClassType::Internal* ptr) {
auto wrap = static_cast<jsc::ObjectWrap<ClassType> *>(JSObjectGetPrivate(object));
*wrap = ptr;
}
template<>
inline JSValueRef jsc::Exception::value(JSContextRef ctx, const std::string &message) {
JSValueRef value = jsc::Value::from_string(ctx, message);
return JSObjectMakeError(ctx, 1, &value, NULL);
}
} // js
} // realm

194
src/jsc/jsc_value.hpp Normal file
View File

@ -0,0 +1,194 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "jsc_types.hpp"
namespace realm {
namespace js {
static inline bool is_object_of_type(JSContextRef ctx, JSValueRef value, jsc::String type) {
JSObjectRef global_object = JSContextGetGlobalObject(ctx);
JSValueRef exception = nullptr;
JSValueRef constructor = JSObjectGetProperty(ctx, global_object, type, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
bool result = JSValueIsInstanceOfConstructor(ctx, value, jsc::Value::validated_to_constructor(ctx, constructor), &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return result;
}
template<>
inline bool jsc::Value::is_array(JSContextRef ctx, const JSValueRef &value) {
// JSValueIsArray() is not available until iOS 9.
static const jsc::String type = "Array";
return is_object_of_type(ctx, value, type);
}
template<>
inline bool jsc::Value::is_array_buffer(JSContextRef ctx, const JSValueRef &value) {
static const jsc::String type = "ArrayBuffer";
return is_object_of_type(ctx, value, type);
}
template<>
inline bool jsc::Value::is_date(JSContextRef ctx, const JSValueRef &value) {
static const jsc::String type = "Date";
return is_object_of_type(ctx, value, type);
}
template<>
inline bool jsc::Value::is_boolean(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsBoolean(ctx, value);
}
template<>
inline bool jsc::Value::is_constructor(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsObject(ctx, value) && JSObjectIsConstructor(ctx, (JSObjectRef)value);
}
template<>
inline bool jsc::Value::is_function(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsObject(ctx, value) && JSObjectIsFunction(ctx, (JSObjectRef)value);
}
template<>
inline bool jsc::Value::is_null(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsNull(ctx, value);
}
template<>
inline bool jsc::Value::is_number(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsNumber(ctx, value);
}
template<>
inline bool jsc::Value::is_object(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsObject(ctx, value);
}
template<>
inline bool jsc::Value::is_string(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsString(ctx, value);
}
template<>
inline bool jsc::Value::is_undefined(JSContextRef ctx, const JSValueRef &value) {
return JSValueIsUndefined(ctx, value);
}
template<>
inline bool jsc::Value::is_valid(const JSValueRef &value) {
return value != nullptr;
}
template<>
inline JSValueRef jsc::Value::from_boolean(JSContextRef ctx, bool boolean) {
return JSValueMakeBoolean(ctx, boolean);
}
template<>
inline JSValueRef jsc::Value::from_null(JSContextRef ctx) {
return JSValueMakeNull(ctx);
}
template<>
inline JSValueRef jsc::Value::from_number(JSContextRef ctx, double number) {
return JSValueMakeNumber(ctx, number);
}
template<>
inline JSValueRef jsc::Value::from_string(JSContextRef ctx, const jsc::String &string) {
return JSValueMakeString(ctx, string);
}
template<>
inline JSValueRef jsc::Value::from_undefined(JSContextRef ctx) {
return JSValueMakeUndefined(ctx);
}
template<>
inline bool jsc::Value::to_boolean(JSContextRef ctx, const JSValueRef &value) {
return JSValueToBoolean(ctx, value);
}
template<>
inline double jsc::Value::to_number(JSContextRef ctx, const JSValueRef &value) {
JSValueRef exception = nullptr;
double number = JSValueToNumber(ctx, value, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
if (isnan(number)) {
throw std::invalid_argument("Value not convertible to a number.");
}
return number;
}
template<>
inline jsc::String jsc::Value::to_string(JSContextRef ctx, const JSValueRef &value) {
JSValueRef exception = nullptr;
jsc::String string = JSValueToStringCopy(ctx, value, &exception);
// Since the string's retain value is +2 here, we need to manually release it before returning.
JSStringRelease(string);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return string;
}
template<>
inline JSObjectRef jsc::Value::to_object(JSContextRef ctx, const JSValueRef &value) {
JSValueRef exception = nullptr;
JSObjectRef object = JSValueToObject(ctx, value, &exception);
if (exception) {
throw jsc::Exception(ctx, exception);
}
return object;
}
template<>
inline JSObjectRef jsc::Value::to_array(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSObjectRef jsc::Value::to_constructor(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSObjectRef jsc::Value::to_date(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
template<>
inline JSObjectRef jsc::Value::to_function(JSContextRef ctx, const JSValueRef &value) {
return to_object(ctx, value);
}
} // js
} // realm

View File

@ -19,6 +19,7 @@
#pragma once
#include "node_types.hpp"
#include "js_class.hpp"
#include "js_util.hpp"

32
src/node/node_context.hpp Normal file
View File

@ -0,0 +1,32 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
inline v8::Local<v8::Context> node::Context::get_global_context(v8::Isolate* isolate) {
return isolate->GetCurrentContext();
}
} // js
} // realm

View File

@ -0,0 +1,32 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
inline v8::Local<v8::Value> node::Exception::value(v8::Isolate* isolate, const std::string &message) {
return Nan::Error(message.c_str());
}
} // js
} // realm

View File

@ -0,0 +1,49 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
inline v8::Local<v8::Value> node::Function::call(v8::Isolate* isolate, const v8::Local<v8::Function> &function, const v8::Local<v8::Object> &this_object, size_t argc, const v8::Local<v8::Value> arguments[]) {
Nan::TryCatch trycatch;
auto result = Nan::Call(function, this_object, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return result.ToLocalChecked();
}
template<>
inline v8::Local<v8::Object> node::Function::construct(v8::Isolate* isolate, const v8::Local<v8::Function> &function, size_t argc, const v8::Local<v8::Value> arguments[]) {
Nan::TryCatch trycatch;
auto result = Nan::NewInstance(function, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return result.ToLocalChecked();
}
} // js
} // realm

View File

@ -18,5 +18,14 @@
#pragma once
#include "node_string.hpp"
#include "node_protected.hpp"
#include "node_context.hpp"
#include "node_value.hpp"
#include "node_object.hpp"
#include "node_function.hpp"
#include "node_exception.hpp"
#include "node_return_value.hpp"
#include "node_object_accessor.hpp"
#include "js_realm.hpp"

159
src/node/node_object.hpp Normal file
View File

@ -0,0 +1,159 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
inline bool node::Object::has_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const node::String &key) {
return Nan::Has(object, key).FromMaybe(false);
}
template<>
inline bool node::Object::has_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, uint32_t index) {
return Nan::Has(object, index).FromMaybe(false);
}
template<>
inline v8::Local<v8::Value> node::Object::get_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const node::String &key) {
Nan::TryCatch trycatch;
auto value = Nan::Get(object, v8::Local<v8::String>(key));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return value.ToLocalChecked();
}
template<>
inline v8::Local<v8::Value> node::Object::get_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, uint32_t index) {
Nan::TryCatch trycatch;
auto value = Nan::Get(object, index);
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return value.ToLocalChecked();
}
template<>
inline void node::Object::set_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const node::String &key, const v8::Local<v8::Value> &value, PropertyAttributes attributes) {
Nan::TryCatch trycatch;
if (attributes) {
Nan::ForceSet(object, v8::Local<v8::String>(key), value, v8::PropertyAttribute(attributes));
}
else {
Nan::Set(object, v8::Local<v8::String>(key), value);
}
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
}
template<>
inline void node::Object::set_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, uint32_t index, const v8::Local<v8::Value> &value) {
Nan::TryCatch trycatch;
Nan::Set(object, index, value);
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
}
template<>
inline std::vector<node::String> node::Object::get_property_names(v8::Isolate* isolate, const v8::Local<v8::Object> &object) {
auto maybe_array = Nan::GetPropertyNames(object);
if (maybe_array.IsEmpty()) {
return std::vector<node::String>();
}
auto array = maybe_array.ToLocalChecked();
uint32_t count = array->Length();
std::vector<node::String> names;
names.reserve(count);
for (uint32_t i = 0; i < count; i++) {
names.push_back(array->Get(i)->ToString());
}
return names;
}
template<>
inline v8::Local<v8::Value> node::Object::get_prototype(v8::Isolate* isolate, const v8::Local<v8::Object> &object) {
return object->GetPrototype();
}
template<>
inline void node::Object::set_prototype(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const v8::Local<v8::Value> &prototype) {
Nan::SetPrototype(object, prototype);
}
template<>
inline v8::Local<v8::Object> node::Object::create_empty(v8::Isolate* isolate) {
return Nan::New<v8::Object>();
}
template<>
inline v8::Local<v8::Object> node::Object::create_array(v8::Isolate* isolate, uint32_t length, const v8::Local<v8::Value> values[]) {
v8::Local<v8::Array> array = Nan::New<v8::Array>(length);
for (uint32_t i = 0; i < length; i++) {
set_property(isolate, array, i, values[i]);
}
return array;
}
template<>
inline v8::Local<v8::Object> node::Object::create_date(v8::Isolate* isolate, double time) {
return Nan::New<v8::Date>(time).ToLocalChecked();
}
template<>
template<typename ClassType>
inline v8::Local<v8::Object> node::Object::create_instance(v8::Isolate* isolate, typename ClassType::Internal* internal) {
return node::ObjectWrap<ClassType>::create_instance(isolate, internal);
}
template<>
template<typename ClassType>
inline bool node::Object::is_instance(v8::Isolate* isolate, const v8::Local<v8::Object> &object) {
return node::ObjectWrap<ClassType>::has_instance(isolate, object);
}
template<>
template<typename ClassType>
inline typename ClassType::Internal* node::Object::get_internal(const v8::Local<v8::Object> &object) {
return *Nan::ObjectWrap::Unwrap<node::ObjectWrap<ClassType>>(object);
}
template<>
template<typename ClassType>
inline void node::Object::set_internal(const v8::Local<v8::Object> &object, typename ClassType::Internal* ptr) {
auto wrap = Nan::ObjectWrap::Unwrap<node::ObjectWrap<ClassType>>(object);
*wrap = ptr;
}
} // js
} // realm

View File

@ -0,0 +1,84 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace node {
template<typename MemberType>
class Protected {
// TODO: Figure out why Nan::CopyablePersistentTraits causes a build failure.
Nan::Persistent<MemberType, v8::CopyablePersistentTraits<MemberType>> m_value;
public:
Protected(v8::Local<MemberType> value) : m_value(value) {}
operator v8::Local<MemberType>() const {
return Nan::New(m_value);
}
bool operator==(const v8::Local<MemberType> &other) const {
return m_value == other;
}
bool operator!=(const v8::Local<MemberType> &other) const {
return m_value != other;
}
bool operator==(const Protected<MemberType> &other) const {
return m_value == other.m_value;
}
bool operator!=(const Protected<MemberType> &other) const {
return m_value != other.m_value;
}
};
} // node
namespace js {
template<>
class Protected<node::Types::GlobalContext> : public node::Protected<v8::Context> {
public:
Protected(v8::Local<v8::Context> ctx) : node::Protected<v8::Context>(ctx) {}
operator v8::Isolate*() const {
return v8::Local<v8::Context>(*this)->GetIsolate();
}
};
template<>
class Protected<node::Types::Value> : public node::Protected<v8::Value> {
public:
Protected(v8::Isolate* isolate, v8::Local<v8::Value> value) : node::Protected<v8::Value>(value) {}
};
template<>
class Protected<node::Types::Object> : public node::Protected<v8::Object> {
public:
Protected(v8::Isolate* isolate, v8::Local<v8::Object> object) : node::Protected<v8::Object>(object) {}
};
template<>
class Protected<node::Types::Function> : public node::Protected<v8::Function> {
public:
Protected(v8::Isolate* isolate, v8::Local<v8::Function> object) : node::Protected<v8::Function>(object) {}
};
} // js
} // realm

View File

@ -0,0 +1,65 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
class ReturnValue<node::Types> {
Nan::ReturnValue<v8::Value> m_value;
public:
ReturnValue(Nan::ReturnValue<v8::Value> value) : m_value(value) {}
void set(const v8::Local<v8::Value> &value) {
m_value.Set(value);
}
void set(const std::string &string) {
if (string.empty()) {
m_value.SetEmptyString();
}
else {
m_value.Set(Nan::New(string).ToLocalChecked());
}
}
void set(bool boolean) {
m_value.Set(boolean);
}
void set(double number) {
m_value.Set(number);
}
void set(int32_t number) {
m_value.Set(number);
}
void set(uint32_t number) {
m_value.Set(number);
}
void set_null() {
m_value.SetNull();
}
void set_undefined() {
m_value.SetUndefined();
}
};
} // js
} // realm

45
src/node/node_string.hpp Normal file
View File

@ -0,0 +1,45 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
class String<node::Types> {
std::string m_str;
public:
String(const char* s) : m_str(s) {}
String(const std::string &s) : m_str(s) {}
String(const v8::Local<v8::String> &s) : m_str(*Nan::Utf8String(s)) {}
String(v8::Local<v8::String> &&s) : String(s) {}
operator std::string() const {
return m_str;
}
operator v8::Local<v8::String>() const {
return Nan::New(m_str).ToLocalChecked();
}
};
} // js
} // realm

View File

@ -53,32 +53,7 @@ struct Types {
using StringPropertyEnumeratorCallback = Nan::PropertyEnumeratorCallback;
};
template<typename T>
class Protected {
// TODO: Figure out why Nan::CopyablePersistentTraits causes a build failure.
Nan::Persistent<T, v8::CopyablePersistentTraits<T>> m_value;
public:
Protected(v8::Local<T> value) : m_value(value) {}
operator v8::Local<T>() const {
return Nan::New(m_value);
}
bool operator==(const v8::Local<T> &other) const {
return m_value == other;
}
bool operator!=(const v8::Local<T> &other) const {
return m_value != other;
}
bool operator==(const Protected<T> &other) const {
return m_value == other.m_value;
}
bool operator!=(const Protected<T> &other) const {
return m_value != other.m_value;
}
};
template<typename T>
template<typename ClassType>
class ObjectWrap;
using String = js::String<Types>;
@ -90,398 +65,4 @@ using Exception = js::Exception<Types>;
using ReturnValue = js::ReturnValue<Types>;
} // node
namespace js {
template<>
class String<node::Types> {
std::string m_str;
public:
String(const char* s) : m_str(s) {}
String(const std::string &s) : m_str(s) {}
String(const v8::Local<v8::String> &s) : m_str(*Nan::Utf8String(s)) {}
String(v8::Local<v8::String> &&s) : String(s) {}
operator std::string() const {
return m_str;
}
operator v8::Local<v8::String>() const {
return Nan::New(m_str).ToLocalChecked();
}
};
template<>
class ReturnValue<node::Types> {
Nan::ReturnValue<v8::Value> m_value;
public:
ReturnValue(Nan::ReturnValue<v8::Value> value) : m_value(value) {}
void set(const v8::Local<v8::Value> &value) {
m_value.Set(value);
}
void set(const std::string &string) {
if (string.empty()) {
m_value.SetEmptyString();
}
else {
m_value.Set(Nan::New(string).ToLocalChecked());
}
}
void set(bool boolean) {
m_value.Set(boolean);
}
void set(double number) {
m_value.Set(number);
}
void set(int32_t number) {
m_value.Set(number);
}
void set(uint32_t number) {
m_value.Set(number);
}
void set_null() {
m_value.SetNull();
}
void set_undefined() {
m_value.SetUndefined();
}
};
template<>
class Protected<node::Types::GlobalContext> : public node::Protected<v8::Context> {
public:
Protected(v8::Local<v8::Context> ctx) : node::Protected<v8::Context>(ctx) {}
operator v8::Isolate*() const {
return v8::Local<v8::Context>(*this)->GetIsolate();
}
};
template<>
class Protected<node::Types::Value> : public node::Protected<v8::Value> {
public:
Protected(v8::Isolate* isolate, v8::Local<v8::Value> value) : node::Protected<v8::Value>(value) {}
};
template<>
class Protected<node::Types::Object> : public node::Protected<v8::Object> {
public:
Protected(v8::Isolate* isolate, v8::Local<v8::Object> object) : node::Protected<v8::Object>(object) {}
};
template<>
class Protected<node::Types::Function> : public node::Protected<v8::Function> {
public:
Protected(v8::Isolate* isolate, v8::Local<v8::Function> object) : node::Protected<v8::Function>(object) {}
};
template<>
inline v8::Local<v8::Context> node::Context::get_global_context(v8::Isolate* isolate) {
return isolate->GetCurrentContext();
}
template<>
inline bool node::Value::is_array(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsArray();
}
template<>
inline bool node::Value::is_array_buffer(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
#if REALM_V8_ARRAY_BUFFER_API
return value->IsArrayBuffer();
#else
// TODO: Implement this!
#endif
}
template<>
inline bool node::Value::is_array_buffer_view(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
#if REALM_V8_ARRAY_BUFFER_API
return value->IsArrayBufferView();
#else
// TODO: Implement this!
#endif
}
template<>
inline bool node::Value::is_date(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsDate();
}
template<>
inline bool node::Value::is_boolean(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsBoolean();
}
template<>
inline bool node::Value::is_constructor(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsFunction();
}
template<>
inline bool node::Value::is_function(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsFunction();
}
template<>
inline bool node::Value::is_null(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsNull();
}
template<>
inline bool node::Value::is_number(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsNumber();
}
template<>
inline bool node::Value::is_object(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsObject();
}
template<>
inline bool node::Value::is_string(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsString();
}
template<>
inline bool node::Value::is_undefined(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsUndefined();
}
template<>
inline bool node::Value::is_valid(const v8::Local<v8::Value> &value) {
return !value.IsEmpty();
}
template<>
inline v8::Local<v8::Value> node::Value::from_boolean(v8::Isolate* isolate, bool boolean) {
return Nan::New(boolean);
}
template<>
inline v8::Local<v8::Value> node::Value::from_null(v8::Isolate* isolate) {
return Nan::Null();
}
template<>
inline v8::Local<v8::Value> node::Value::from_number(v8::Isolate* isolate, double number) {
return Nan::New(number);
}
template<>
inline v8::Local<v8::Value> node::Value::from_string(v8::Isolate* isolate, const node::String &string) {
return v8::Local<v8::String>(string);
}
template<>
inline v8::Local<v8::Value> node::Value::from_undefined(v8::Isolate* isolate) {
return Nan::Undefined();
}
template<>
inline bool node::Value::to_boolean(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return Nan::To<bool>(value).FromMaybe(false);
}
template<>
inline double node::Value::to_number(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
double number = Nan::To<double>(value).FromMaybe(NAN);
if (isnan(number)) {
throw std::invalid_argument("Value not convertible to a number.");
}
return number;
}
template<>
inline node::String node::Value::to_string(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->ToString();
}
template<>
inline v8::Local<v8::Object> node::Value::to_object(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return Nan::To<v8::Object>(value).FromMaybe(v8::Local<v8::Object>());
}
template<>
inline v8::Local<v8::Object> node::Value::to_array(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return to_object(isolate, value);
}
template<>
inline v8::Local<v8::Object> node::Value::to_date(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return to_object(isolate, value);
}
template<>
inline v8::Local<v8::Function> node::Value::to_function(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsFunction() ? v8::Local<v8::Function>::Cast(value) : v8::Local<v8::Function>();
}
template<>
inline v8::Local<v8::Function> node::Value::to_constructor(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return to_function(isolate, value);
}
template<>
inline v8::Local<v8::Value> node::Function::call(v8::Isolate* isolate, const v8::Local<v8::Function> &function, const v8::Local<v8::Object> &this_object, size_t argc, const v8::Local<v8::Value> arguments[]) {
Nan::TryCatch trycatch;
auto result = Nan::Call(function, this_object, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return result.ToLocalChecked();
}
template<>
inline v8::Local<v8::Object> node::Function::construct(v8::Isolate* isolate, const v8::Local<v8::Function> &function, size_t argc, const v8::Local<v8::Value> arguments[]) {
Nan::TryCatch trycatch;
auto result = Nan::NewInstance(function, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return result.ToLocalChecked();
}
template<>
inline bool node::Object::has_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const node::String &key) {
return Nan::Has(object, key).FromMaybe(false);
}
template<>
inline bool node::Object::has_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, uint32_t index) {
return Nan::Has(object, index).FromMaybe(false);
}
template<>
inline v8::Local<v8::Value> node::Object::get_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const node::String &key) {
Nan::TryCatch trycatch;
auto value = Nan::Get(object, v8::Local<v8::String>(key));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return value.ToLocalChecked();
}
template<>
inline v8::Local<v8::Value> node::Object::get_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, uint32_t index) {
Nan::TryCatch trycatch;
auto value = Nan::Get(object, index);
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
return value.ToLocalChecked();
}
template<>
inline void node::Object::set_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const node::String &key, const v8::Local<v8::Value> &value, PropertyAttributes attributes) {
Nan::TryCatch trycatch;
if (attributes) {
Nan::ForceSet(object, v8::Local<v8::String>(key), value, v8::PropertyAttribute(attributes));
}
else {
Nan::Set(object, v8::Local<v8::String>(key), value);
}
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
}
template<>
inline void node::Object::set_property(v8::Isolate* isolate, const v8::Local<v8::Object> &object, uint32_t index, const v8::Local<v8::Value> &value) {
Nan::TryCatch trycatch;
Nan::Set(object, index, value);
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
}
}
template<>
inline std::vector<node::String> node::Object::get_property_names(v8::Isolate* isolate, const v8::Local<v8::Object> &object) {
auto maybe_array = Nan::GetPropertyNames(object);
if (maybe_array.IsEmpty()) {
return std::vector<node::String>();
}
auto array = maybe_array.ToLocalChecked();
uint32_t count = array->Length();
std::vector<node::String> names;
names.reserve(count);
for (uint32_t i = 0; i < count; i++) {
names.push_back(array->Get(i)->ToString());
}
return names;
}
template<>
inline v8::Local<v8::Value> node::Object::get_prototype(v8::Isolate* isolate, const v8::Local<v8::Object> &object) {
return object->GetPrototype();
}
template<>
inline void node::Object::set_prototype(v8::Isolate* isolate, const v8::Local<v8::Object> &object, const v8::Local<v8::Value> &prototype) {
Nan::SetPrototype(object, prototype);
}
template<>
inline v8::Local<v8::Object> node::Object::create_empty(v8::Isolate* isolate) {
return Nan::New<v8::Object>();
}
template<>
inline v8::Local<v8::Object> node::Object::create_array(v8::Isolate* isolate, uint32_t length, const v8::Local<v8::Value> values[]) {
v8::Local<v8::Array> array = Nan::New<v8::Array>(length);
for (uint32_t i = 0; i < length; i++) {
set_property(isolate, array, i, values[i]);
}
return array;
}
template<>
inline v8::Local<v8::Object> node::Object::create_date(v8::Isolate* isolate, double time) {
return Nan::New<v8::Date>(time).ToLocalChecked();
}
template<>
template<typename ClassType>
inline v8::Local<v8::Object> node::Object::create_instance(v8::Isolate* isolate, typename ClassType::Internal* internal) {
return node::ObjectWrap<ClassType>::create_instance(isolate, internal);
}
template<>
template<typename ClassType>
inline bool node::Object::is_instance(v8::Isolate* isolate, const v8::Local<v8::Object> &object) {
return node::ObjectWrap<ClassType>::has_instance(isolate, object);
}
template<>
template<typename ClassType>
inline typename ClassType::Internal* node::Object::get_internal(const v8::Local<v8::Object> &object) {
return *Nan::ObjectWrap::Unwrap<node::ObjectWrap<ClassType>>(object);
}
template<>
template<typename ClassType>
inline void node::Object::set_internal(const v8::Local<v8::Object> &object, typename ClassType::Internal* ptr) {
auto wrap = Nan::ObjectWrap::Unwrap<node::ObjectWrap<ClassType>>(object);
*wrap = ptr;
}
template<>
inline v8::Local<v8::Value> node::Exception::value(v8::Isolate* isolate, const std::string &message) {
return Nan::Error(message.c_str());
}
} // js
} // realm

169
src/node/node_value.hpp Normal file
View File

@ -0,0 +1,169 @@
////////////////////////////////////////////////////////////////////////////
//
// 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 "node_types.hpp"
namespace realm {
namespace js {
template<>
inline bool node::Value::is_array(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsArray();
}
template<>
inline bool node::Value::is_array_buffer(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
#if REALM_V8_ARRAY_BUFFER_API
return value->IsArrayBuffer();
#else
// TODO: Implement this!
#endif
}
template<>
inline bool node::Value::is_array_buffer_view(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
#if REALM_V8_ARRAY_BUFFER_API
return value->IsArrayBufferView();
#else
// TODO: Implement this!
#endif
}
template<>
inline bool node::Value::is_date(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsDate();
}
template<>
inline bool node::Value::is_boolean(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsBoolean();
}
template<>
inline bool node::Value::is_constructor(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsFunction();
}
template<>
inline bool node::Value::is_function(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsFunction();
}
template<>
inline bool node::Value::is_null(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsNull();
}
template<>
inline bool node::Value::is_number(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsNumber();
}
template<>
inline bool node::Value::is_object(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsObject();
}
template<>
inline bool node::Value::is_string(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsString();
}
template<>
inline bool node::Value::is_undefined(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsUndefined();
}
template<>
inline bool node::Value::is_valid(const v8::Local<v8::Value> &value) {
return !value.IsEmpty();
}
template<>
inline v8::Local<v8::Value> node::Value::from_boolean(v8::Isolate* isolate, bool boolean) {
return Nan::New(boolean);
}
template<>
inline v8::Local<v8::Value> node::Value::from_null(v8::Isolate* isolate) {
return Nan::Null();
}
template<>
inline v8::Local<v8::Value> node::Value::from_number(v8::Isolate* isolate, double number) {
return Nan::New(number);
}
template<>
inline v8::Local<v8::Value> node::Value::from_string(v8::Isolate* isolate, const node::String &string) {
return v8::Local<v8::String>(string);
}
template<>
inline v8::Local<v8::Value> node::Value::from_undefined(v8::Isolate* isolate) {
return Nan::Undefined();
}
template<>
inline bool node::Value::to_boolean(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return Nan::To<bool>(value).FromMaybe(false);
}
template<>
inline double node::Value::to_number(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
double number = Nan::To<double>(value).FromMaybe(NAN);
if (isnan(number)) {
throw std::invalid_argument("Value not convertible to a number.");
}
return number;
}
template<>
inline node::String node::Value::to_string(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->ToString();
}
template<>
inline v8::Local<v8::Object> node::Value::to_object(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return Nan::To<v8::Object>(value).FromMaybe(v8::Local<v8::Object>());
}
template<>
inline v8::Local<v8::Object> node::Value::to_array(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return to_object(isolate, value);
}
template<>
inline v8::Local<v8::Object> node::Value::to_date(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return to_object(isolate, value);
}
template<>
inline v8::Local<v8::Function> node::Value::to_function(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return value->IsFunction() ? v8::Local<v8::Function>::Cast(value) : v8::Local<v8::Function>();
}
template<>
inline v8::Local<v8::Function> node::Value::to_constructor(v8::Isolate* isolate, const v8::Local<v8::Value> &value) {
return to_function(isolate, value);
}
} // js
} // realm