forked from enlightenment/efl
eina_js: initial binding for Eina_Value
There is value_cast, which can be used to convert back and forth between efl::eina::value and v8::Local<v8::Value>. value_cast will throw std::bad_cast if conversion fails. There is also `register_*_value` functions to setup the global object that act like a bridge between the C++ code and the JavaScript code. There are several tests also. The JavaScript code will use a non-idiomatic API which needs to manually clean the resources. Ideally, we'd allow construction in the familiar `new eina_value(42)` way, but the `this` JavaScript reference is exposed to C++ code through V8 as `v8::Local<v8::Value>`, which cannot be used to register finalizers. Finalizers support is only supported in `v8::Persistent`. Future work include: - Fix failing tests. - Need to investigate why the code below fails: ``` efl::eina::get<std::string>(efl::eina::value(std::string("Matroška"))); efl::eina::get<efl::eina::stringshare>(efl::eina::value(std::string("Matroška"))); ``` - The bridge between JavaScript and C++ code (`register_*_value` functions) isn't handling all errors as it should. Implement and add tests. - Move most of the code out of the headers. Currently I'm stumbling upon a linking problem.
This commit is contained in:
parent
df7028f3f5
commit
391ebe306f
|
@ -56,12 +56,17 @@ bindings/eina_cxx/eina_value.hh
|
|||
|
||||
if EFL_ENABLE_TESTS
|
||||
|
||||
check_PROGRAMS += tests/eina_js/eina_js_suite
|
||||
TESTS += tests/eina_js/eina_js_suite
|
||||
check_PROGRAMS += tests/eina_js/eina_js_suite \
|
||||
tests/eina_js/eina_js_value
|
||||
TESTS += tests/eina_js/eina_js_suite \
|
||||
tests/eina_js/eina_js_value
|
||||
|
||||
tests_eina_js_eina_js_suite_SOURCES = \
|
||||
tests/eina_js/eina_js_suite.cc
|
||||
|
||||
tests_eina_js_eina_js_value_SOURCES = \
|
||||
tests/eina_js/eina_js_value.cc
|
||||
|
||||
tests_eina_js_eina_js_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
|
||||
-DTESTS_WD=\"`pwd`\" \
|
||||
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eina_js\" \
|
||||
|
@ -76,6 +81,19 @@ tests_eina_js_eina_js_suite_LDADD = \
|
|||
@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EOLIAN_JS_LIBS@ @USE_EINA_JS_LIBS@
|
||||
tests_eina_js_eina_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EINA_JS_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@
|
||||
|
||||
tests_eina_js_eina_js_value_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
|
||||
-DTESTS_WD=\"`pwd`\" \
|
||||
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eina_js\" \
|
||||
-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eina_js\" \
|
||||
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eina_js\" \
|
||||
@CHECK_CFLAGS@ \
|
||||
@EINA_CXX_CFLAGS@ \
|
||||
@EO_CXX_CFLAGS@ \
|
||||
@EO_CFLAGS@ \
|
||||
@EINA_JS_CFLAGS@
|
||||
tests_eina_js_eina_js_value_LDADD = @CHECK_LIBS@ @USE_EINA_JS_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@
|
||||
tests_eina_js_eina_js_value_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EINA_JS_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
#ifndef EINA_JS_VALUE_HH
|
||||
#define EINA_JS_VALUE_HH
|
||||
|
||||
#include <v8.h>
|
||||
#include <Eina.hh>
|
||||
#include <type_traits>
|
||||
|
||||
namespace efl { namespace js {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_representable_as_v8_integer: std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_representable_as_v8_integer
|
||||
<T,
|
||||
typename std::enable_if<std::is_integral<T>::value
|
||||
/* v8::Integer only stores 32-bit signed and unsigned
|
||||
numbers. */
|
||||
&& (sizeof(T) <= sizeof(int32_t))>::type>
|
||||
: std::true_type {};
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<is_representable_as_v8_integer<T>::value
|
||||
&& std::is_signed<T>::value,
|
||||
v8::Local<v8::Value>>::type
|
||||
to_v8_number(const T &v, v8::Isolate *isolate)
|
||||
{
|
||||
return v8::Integer::New(isolate, v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<is_representable_as_v8_integer<T>::value
|
||||
&& std::is_unsigned<T>::value,
|
||||
v8::Local<v8::Value>>::type
|
||||
to_v8_number(const T &v, v8::Isolate *isolate)
|
||||
{
|
||||
return v8::Integer::NewFromUnsigned(isolate, v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<(std::is_integral<T>::value
|
||||
&& !is_representable_as_v8_integer<T>::value)
|
||||
|| std::is_floating_point<T>::value,
|
||||
v8::Local<v8::Value>>::type
|
||||
to_v8_number(const T &v, v8::Isolate *isolate)
|
||||
{
|
||||
return v8::Number::New(isolate, v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_same<T, ::efl::eina::stringshare>::value
|
||||
|| std::is_same<T, std::string>::value,
|
||||
v8::Local<v8::Value>>::type
|
||||
to_v8_string(const T &v, v8::Isolate *isolate)
|
||||
{
|
||||
return v8::String::NewFromUtf8(isolate, v.c_str(),
|
||||
v8::String::kNormalString, v.size());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_same<T, v8::Local<v8::Value>>::value, T>::type
|
||||
value_cast(const ::efl::eina::value &v, v8::Isolate *isolate)
|
||||
{
|
||||
using detail::to_v8_number;
|
||||
using detail::to_v8_string;
|
||||
using ::efl::eina::get;
|
||||
|
||||
const auto &t = v.type_info();
|
||||
if (t == EINA_VALUE_TYPE_UINT64) {
|
||||
return to_v8_number(get<uint64_t>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_UCHAR) {
|
||||
return to_v8_number(get<unsigned char>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_USHORT) {
|
||||
return to_v8_number(get<unsigned short>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_UINT) {
|
||||
return to_v8_number(get<unsigned int>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_ULONG) {
|
||||
return to_v8_number(get<unsigned long>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_CHAR) {
|
||||
return to_v8_number(get<char>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_SHORT) {
|
||||
return to_v8_number(get<short>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_INT) {
|
||||
return to_v8_number(get<int>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_LONG) {
|
||||
return to_v8_number(get<long>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_FLOAT) {
|
||||
return to_v8_number(get<float>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_DOUBLE) {
|
||||
return to_v8_number(get<double>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_STRINGSHARE) {
|
||||
return to_v8_string(get<::efl::eina::stringshare>(v), isolate);
|
||||
} else if (t == EINA_VALUE_TYPE_STRING) {
|
||||
return to_v8_string(get<std::string>(v), isolate);
|
||||
}
|
||||
|
||||
throw std::bad_cast{};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_same<T, ::efl::eina::value>::value, T>::type
|
||||
value_cast(const v8::Local<v8::Value> &v)
|
||||
{
|
||||
using ::efl::eina::value;
|
||||
|
||||
if (v->IsBoolean()) {
|
||||
return value(int{v->BooleanValue()});
|
||||
} else if (v->IsInt32()) {
|
||||
return value(v->Int32Value());
|
||||
} else if (v->IsUint32()) {
|
||||
return value(v->Uint32Value());
|
||||
} else if (v->IsNumber()) {
|
||||
return value(v->NumberValue());
|
||||
} else if (v->IsString()) {
|
||||
v8::String::Utf8Value data(v);
|
||||
return value(std::string(*data, data.length()));
|
||||
}
|
||||
|
||||
throw std::bad_cast{};
|
||||
}
|
||||
|
||||
/*
|
||||
# JS binding
|
||||
|
||||
- There is the `value()` constructor, which accepts a primitive value as input
|
||||
argument and might throw.
|
||||
- The returned object has a `get()` method, which can be used to get the
|
||||
wrapped value as a JavaScript value.
|
||||
- The returned object has a `set()` method, which can be used to change the
|
||||
wrapped value.
|
||||
*/
|
||||
inline
|
||||
void register_make_value(v8::Isolate *isolate,
|
||||
v8::Handle<v8::ObjectTemplate> global,
|
||||
v8::Local<v8::String> name)
|
||||
{
|
||||
//v8::Local<v8::FunctionTemplate>
|
||||
using v8::Local;
|
||||
using v8::Value;
|
||||
using v8::String;
|
||||
using v8::Object;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::FunctionCallbackInfo;
|
||||
|
||||
typedef ::efl::eina::value value_type;
|
||||
typedef value_type *ptr_type;
|
||||
|
||||
auto ctor = [](const FunctionCallbackInfo<Value> &info) {
|
||||
auto set = [](const FunctionCallbackInfo<Value> &info) {
|
||||
if (info.Length() != 1)
|
||||
return;
|
||||
|
||||
void *ptr = info.Holder()->GetAlignedPointerFromInternalField(0);
|
||||
try {
|
||||
*static_cast<ptr_type>(ptr) = value_cast<value_type>(info[0]);
|
||||
} catch(const std::bad_cast &e) {
|
||||
} catch(const ::efl::eina::system_error &e) {
|
||||
}
|
||||
};
|
||||
auto get = [](const FunctionCallbackInfo<Value> &info) {
|
||||
void *ptr = info.Holder()->GetAlignedPointerFromInternalField(0);
|
||||
auto &value = *static_cast<ptr_type>(ptr);
|
||||
info.GetReturnValue().Set(value_cast<Local<Value>>
|
||||
(value, info.GetIsolate()));
|
||||
};
|
||||
|
||||
if (info.Length() != 1)
|
||||
return;
|
||||
|
||||
auto obj_tpl = v8::ObjectTemplate::New(info.GetIsolate());
|
||||
obj_tpl->SetInternalFieldCount(1);
|
||||
|
||||
auto ret = obj_tpl->NewInstance();
|
||||
info.GetReturnValue().Set(ret);
|
||||
|
||||
ret->Set(String::NewFromUtf8(info.GetIsolate(), "set"),
|
||||
FunctionTemplate::New(info.GetIsolate(), set)->GetFunction());
|
||||
ret->Set(String::NewFromUtf8(info.GetIsolate(), "get"),
|
||||
FunctionTemplate::New(info.GetIsolate(), get)->GetFunction());
|
||||
|
||||
try {
|
||||
std::unique_ptr<value_type>
|
||||
ptr(new value_type(value_cast<value_type>(info[0])));
|
||||
ret->SetAlignedPointerInInternalField(0, ptr.get());
|
||||
ptr.release();
|
||||
} catch(const std::bad_cast &e) {
|
||||
} catch(const ::efl::eina::system_error &e) {
|
||||
}
|
||||
};
|
||||
|
||||
global->Set(name, FunctionTemplate::New(isolate, ctor));
|
||||
}
|
||||
|
||||
inline
|
||||
void register_destroy_value(v8::Isolate *isolate,
|
||||
v8::Handle<v8::ObjectTemplate> global,
|
||||
v8::Local<v8::String> name)
|
||||
{
|
||||
//v8::Local<v8::FunctionTemplate>
|
||||
using v8::Handle;
|
||||
using v8::Local;
|
||||
using v8::Value;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::FunctionCallbackInfo;
|
||||
|
||||
typedef ::efl::eina::value value_type;
|
||||
typedef value_type *ptr_type;
|
||||
|
||||
auto dtor = [](const FunctionCallbackInfo<Value> &info) {
|
||||
if (info.Length() != 1)
|
||||
return;
|
||||
|
||||
auto o = info[0]->ToObject();
|
||||
delete static_cast<ptr_type>(o->GetAlignedPointerFromInternalField(0));
|
||||
o->SetAlignedPointerInInternalField(0, nullptr);
|
||||
assert(o->GetAlignedPointerFromInternalField(0) == nullptr);
|
||||
};
|
||||
|
||||
global->Set(name, FunctionTemplate::New(isolate, dtor));
|
||||
}
|
||||
|
||||
} } // namespace efl::js
|
||||
|
||||
#endif /* EINA_JS_VALUE_HH */
|
|
@ -0,0 +1,264 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <eina_js_value.hh>
|
||||
#include <Eo.hh>
|
||||
|
||||
void print(const v8::FunctionCallbackInfo<v8::Value> &args)
|
||||
{
|
||||
bool first = true;
|
||||
for (int i = 0; i < args.Length(); i++) {
|
||||
v8::HandleScope handle_scope(args.GetIsolate());
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
v8::String::Utf8Value str(args[i]);
|
||||
std::cout << std::string(*str, str.length());
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static const char script[] =
|
||||
"function assert(test, message) { if (test !== true) throw message; };"
|
||||
|
||||
"var my_value = make_value(1);"
|
||||
"var wrapped = my_value.get();"
|
||||
"assert(typeof(wrapped) === 'number', '#1');"
|
||||
"assert(wrapped === 1, '#2');"
|
||||
|
||||
"my_value.set(2);"
|
||||
"assert(wrapped === 1, '#3');"
|
||||
"wrapped = my_value.get();"
|
||||
"assert(typeof(wrapped) === 'number', '#4');"
|
||||
"assert(wrapped === 2, '#5');"
|
||||
|
||||
"my_value.set(true);"
|
||||
"assert(wrapped === 2, '#6');"
|
||||
"wrapped = my_value.get();"
|
||||
// boolean is represented as integer in the efl::eina::value layer
|
||||
"assert(typeof(wrapped) === 'number', '#7');"
|
||||
"assert(wrapped === 1, '#8');"
|
||||
|
||||
"destroy_value(my_value);"
|
||||
;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
efl::eina::eina_init eina_init;
|
||||
efl::eo::eo_init eo_init;
|
||||
|
||||
v8::V8::InitializeICU();
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Handle<v8::Context> context = [&isolate]() {
|
||||
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
|
||||
|
||||
efl::js::register_make_value(isolate, global,
|
||||
v8::String::NewFromUtf8(isolate,
|
||||
"make_value"));
|
||||
efl::js::register_destroy_value(isolate, global,
|
||||
v8::String::NewFromUtf8(isolate,
|
||||
"destroy_value"));
|
||||
global->Set(v8::String::NewFromUtf8(isolate, "print"),
|
||||
v8::FunctionTemplate::New(isolate, print));
|
||||
|
||||
return v8::Context::New(isolate, NULL, global);
|
||||
}();
|
||||
|
||||
if (context.IsEmpty()) {
|
||||
fprintf(stderr, "Error creating context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
context->Enter();
|
||||
{
|
||||
// Enter the execution environment before evaluating any code.
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<uint64_t>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<uint64_t>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(UINT64_MAX));
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned char>::max()),
|
||||
isolate)->IsUint32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned char>::max()),
|
||||
isolate)->Uint32Value() == UINT8_MAX);
|
||||
|
||||
if (sizeof(short) > sizeof(int32_t)) {
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned short>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned short>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<unsigned short>::max()));
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<short>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<short>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<short>::max()));
|
||||
} else {
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned short>::max()),
|
||||
isolate)->IsUint32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned short>::max()),
|
||||
isolate)->Uint32Value()
|
||||
== std::numeric_limits<unsigned short>::max());
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<short>::max()),
|
||||
isolate)->IsInt32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<short>::max()),
|
||||
isolate)->Int32Value()
|
||||
== std::numeric_limits<short>::max());
|
||||
}
|
||||
|
||||
if (sizeof(int) > sizeof(int32_t)) {
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned int>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned int>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<unsigned int>::max()));
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<int>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<int>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<int>::max()));
|
||||
} else {
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned int>::max()),
|
||||
isolate)->IsUint32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned int>::max()),
|
||||
isolate)->Uint32Value()
|
||||
== std::numeric_limits<unsigned int>::max());
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<int>::max()),
|
||||
isolate)->IsInt32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<int>::max()),
|
||||
isolate)->Int32Value()
|
||||
== std::numeric_limits<int>::max());
|
||||
}
|
||||
|
||||
if (sizeof(long) > sizeof(int32_t)) {
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned long>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned long>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<unsigned long>::max()));
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<long>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<long>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<long>::max()));
|
||||
} else {
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned long>::max()),
|
||||
isolate)->IsUint32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<unsigned long>::max()),
|
||||
isolate)->Uint32Value()
|
||||
== std::numeric_limits<unsigned long>::max());
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<long>::max()),
|
||||
isolate)->IsInt32());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<long>::max()),
|
||||
isolate)->Int32Value()
|
||||
== std::numeric_limits<long>::max());
|
||||
}
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<float>::max()),
|
||||
isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::numeric_limits<float>::max()),
|
||||
isolate)->NumberValue()
|
||||
== double(std::numeric_limits<float>::max()));
|
||||
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(42.42), isolate)->IsNumber());
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(42.42), isolate)->NumberValue()
|
||||
== 42.42);
|
||||
|
||||
assert(efl::eina::get<int>
|
||||
(efl::js::value_cast<efl::eina::value>
|
||||
(v8::Boolean::New(isolate, true))) == 1);
|
||||
assert(efl::eina::get<int32_t>
|
||||
(efl::js::value_cast<efl::eina::value>
|
||||
(v8::Integer::New(isolate, INT32_MAX))) == INT32_MAX);
|
||||
assert(efl::eina::get<uint32_t>
|
||||
(efl::js::value_cast<efl::eina::value>
|
||||
(v8::Integer::NewFromUnsigned(isolate, UINT32_MAX)))
|
||||
== UINT32_MAX);
|
||||
assert(efl::eina::get<double>
|
||||
(efl::js::value_cast<efl::eina::value>
|
||||
(v8::Number::New(isolate,
|
||||
std::numeric_limits<double>::max())))
|
||||
== std::numeric_limits<double>::max());
|
||||
|
||||
{
|
||||
const char utf8_data[] = "Matroška";
|
||||
|
||||
assert(efl::js::value_cast<efl::eina::value>
|
||||
(v8::String::NewFromUtf8(isolate, utf8_data))
|
||||
== efl::eina::value(std::string(utf8_data)));
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(std::string(utf8_data)), isolate)
|
||||
->StrictEquals(v8::String::NewFromUtf8(isolate, utf8_data)));
|
||||
assert(efl::js::value_cast<v8::Local<v8::Value>>
|
||||
(efl::eina::value(efl::eina::stringshare(utf8_data)), isolate)
|
||||
->StrictEquals(v8::String::NewFromUtf8(isolate, utf8_data)));
|
||||
}
|
||||
|
||||
{
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::TryCatch try_catch;
|
||||
auto source = v8::String::NewFromUtf8(isolate, script);
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile(std::move(source));
|
||||
|
||||
assert(!script.IsEmpty());
|
||||
|
||||
/*v8::Handle<v8::Value> result = */script->Run();
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
v8::String::Utf8Value message(try_catch.Message()->Get());
|
||||
std::cerr << std::string(*message, message.length()) << std::endl;
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
context->Exit();
|
||||
}
|
Loading…
Reference in New Issue