eina-js: binding for Eina_Error added

It's a function that check if an error is set and convert to a
JavaScript exception. The exception object is well specified and
useful, giving sane information about the object and following a
model similar to the one used by the Eina_Value binding.
This commit is contained in:
Vinícius dos Santos Oliveira 2014-11-18 01:20:42 -03:00
parent 8412ec8918
commit f250ae0c47
4 changed files with 187 additions and 3 deletions

View File

@ -20,7 +20,8 @@ lib_eina_js_libeina_js_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
lib_eina_js_libeina_js_la_SOURCES = \
bindings/eina_js/eina_js_container.cc \
bindings/eina_js/eina_js_value.cc
bindings/eina_js/eina_js_value.cc \
bindings/eina_js/eina_js_error.cc
#installed_einacxxmainheadersdir = $(includedir)/eina-cxx-@VMAJ@
#dist_installed_einacxxmainheaders_DATA = \
@ -58,9 +59,11 @@ bindings/eina_cxx/eina_value.hh
if EFL_ENABLE_TESTS
check_PROGRAMS += tests/eina_js/eina_js_suite \
tests/eina_js/eina_js_value
tests/eina_js/eina_js_value \
tests/eina_js/eina_js_error
TESTS += tests/eina_js/eina_js_suite \
tests/eina_js/eina_js_value
tests/eina_js/eina_js_value \
tests/eina_js/eina_js_error
tests_eina_js_eina_js_suite_SOURCES = \
tests/eina_js/eina_js_suite.cc
@ -68,6 +71,9 @@ 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_error_SOURCES = \
tests/eina_js/eina_js_error.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\" \
@ -95,6 +101,19 @@ tests_eina_js_eina_js_value_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
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@
tests_eina_js_eina_js_error_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_error_LDADD = @CHECK_LIBS@ @USE_EINA_JS_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@
tests_eina_js_eina_js_error_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EINA_JS_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@
endif
endif

View File

@ -0,0 +1,28 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <eina_js_error.hh>
namespace efl { namespace js {
EAPI
void convert_error_to_javascript_exception(v8::Isolate *isolate)
{
using v8::Local;
using v8::Object;
using v8::String;
Eina_Error err = eina_error_get();
if (!err)
return;
Local<Object> je = Object::New(isolate);
je->Set(String::NewFromUtf8(isolate, "code"),
String::NewFromUtf8(isolate, "Eina_Error"));
je->Set(String::NewFromUtf8(isolate, "value"),
String::NewFromUtf8(isolate, eina_error_msg_get(err)));
isolate->ThrowException(je);
}
} } // namespace efl { namespace js {

View File

@ -0,0 +1,26 @@
#ifndef EINA_JS_ERROR_HH
#define EINA_JS_ERROR_HH
#include <v8.h>
#include <Eina.hh>
namespace efl { namespace js {
/**
* Converts the error value set through Eina's error tool to a JavaScript
* exception.
*
* The exception object will have a `code` string field with the `"Eina_Error"`
* string value and a `value` string field with the value extracted from
* `eina_error_msg_get`.
*
* It won't reset the error to NULL, so you can still access the error object,
* but if you keep calling this function without clearing the error, a new
* exception will be generated for each call after some error is reached. We,
* therefore, suggest you to call `eina_error_set(0)` afterwards.
*/
void convert_error_to_javascript_exception(v8::Isolate *isolate);
} } // namespace efl::js
#endif /* EINA_JS_ERROR_HH */

View File

@ -0,0 +1,111 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cassert>
#include <eina_js_error.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);
}
void clear_eina_error(const v8::FunctionCallbackInfo<v8::Value> &args)
{
eina_error_set(0);
efl::js::convert_error_to_javascript_exception(args.GetIsolate());
}
void set_eina_error(const v8::FunctionCallbackInfo<v8::Value> &args)
{
eina_error_set(eina_error_msg_static_register("foobar"));
efl::js::convert_error_to_javascript_exception(args.GetIsolate());
}
static const char script[] =
"function assert(test, message) { if (test !== true) throw message; };"
"var captured = false;"
"try {"
" clear_eina_error();"
"} catch(e) {"
" captured = true;"
"}"
"assert(captured === false, '#1');"
"captured = false;"
"try {"
" set_eina_error();"
"} catch(e) {"
" assert(e.code === 'Eina_Error', '#2');"
" assert(e.value === 'foobar', '#3');"
" captured = true;"
"}"
"assert(captured === true, '#4');"
;
int main(int argc, char *argv[])
{
efl::eina::eina_init eina_init;
efl::eo::eo_init eo_init;
v8::V8::Initialize();
v8::V8::InitializeICU();
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::Isolate* isolate = v8::Isolate::New();
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Context> context
= v8::Context::New(isolate, NULL, v8::ObjectTemplate::New(isolate));
if (context.IsEmpty()) {
fprintf(stderr, "Error creating context\n");
return 1;
}
{
// Enter the execution environment before evaluating any code.
v8::Context::Scope context_scope(context);
v8::Handle<v8::Object> global = context->Global();
global->Set(v8::String::NewFromUtf8(isolate, "print"),
v8::FunctionTemplate::New(isolate, print)->GetFunction());
global->Set(v8::String::NewFromUtf8(isolate, "clear_eina_error"),
v8::FunctionTemplate::New(isolate, clear_eina_error)
->GetFunction());
global->Set(v8::String::NewFromUtf8(isolate, "set_eina_error"),
v8::FunctionTemplate::New(isolate, set_eina_error)
->GetFunction());
{
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();
}
}
}
}