/c_src/erlv8_call.cc
C++ | 104 lines | 91 code | 11 blank | 2 comment | 11 complexity | 8f09258ab9a2e4b0404aacea20059a83 MD5 | raw file
1#include "erlv8.hh" 2 3void ErlangFun(VM * vm, ERL_NIF_TERM term, ERL_NIF_TERM ref, v8::Handle<v8::Object> recv, v8::Handle<v8::Array> array); // fwd 4 5TickHandler(CallTickHandler) { 6 ErlNifEnv *ref_env = enif_alloc_env(); 7 ERL_NIF_TERM call_ref = enif_make_copy(ref_env, tick_ref); 8 val_res_t *fun_res; 9 if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&fun_res))) { 10 ERL_NIF_TERM head, tail; 11 ERL_NIF_TERM current = array[2]; 12 unsigned int alen; 13 14 enif_get_list_length(vm->env,array[2],&alen); 15 16 v8::Local<v8::Value> *args = NULL; 17 args = new v8::Local<v8::Value>[alen]; 18 int i = 0; 19 while (enif_get_list_cell(vm->env, current, &head, &tail)) { 20 args[i] = v8::Local<v8::Value>::New(term_to_js(fun_res->ctx, vm->isolate, vm->env,head)); 21 i++; current = tail; 22 } 23 v8::Local<v8::Object> recv; 24 if (arity == 4) { // this is specified 25 recv = term_to_js(fun_res->ctx, vm->isolate, vm->env, array[3])->ToObject(); 26 } else { 27 recv = fun_res->ctx->Global(); 28 } 29 v8::Persistent<v8::Function> f = v8::Persistent<v8::Function>::Cast(fun_res->val); 30 31 if (!*f->GetHiddenValue(vm->string__erlv8__)) { // js function 32 v8::TryCatch try_catch; 33 v8::Local<v8::Value> call_result = f->Call(recv, alen, args); 34 if (call_result.IsEmpty()) { 35 SEND(vm->server, 36 enif_make_tuple3(env, 37 enif_make_atom(env,"result"), 38 enif_make_copy(env,call_ref), 39 enif_make_tuple2(env, 40 enif_make_atom(env,"throw"), 41 enif_make_tuple2(env, 42 enif_make_atom(env,"error"), 43 js_to_term(fun_res->ctx, 44 vm->isolate, 45 env, 46 try_catch.Exception()))))); 47 } else { 48 SEND(vm->server, 49 enif_make_tuple3(env, 50 enif_make_atom(env,"result"), 51 enif_make_copy(env,call_ref), 52 js_to_term(fun_res->ctx, 53 vm->isolate, 54 env, 55 call_result))); 56 } 57 } else { // native Erlang function 58 v8::Local<v8::Array> array = v8::Array::New(alen); 59 60 for (unsigned int i=0;i<alen;i++) { 61 array->Set(i,args[i]); 62 } 63 64 ErlangFun(vm, external_to_term(f->GetHiddenValue((vm->string__erlv8__))), call_ref, recv, array); 65 } 66 67 delete [] args; 68 args = NULL; 69 } 70 enif_free_env(ref_env); 71 TickHandlerResolution result; 72 result.type = DONE; 73 return result; 74} 75 76void ErlangFun(VM * vm, ERL_NIF_TERM term, ERL_NIF_TERM ref, v8::Handle<v8::Object> recv, v8::Handle<v8::Array> array) { 77 v8::HandleScope handle_scope; 78 79 // prepare arguments 80 ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * array->Length()); 81 for (unsigned int i=0;i<array->Length();i++) { 82 arr[i] = js_to_term(vm->context, 83 vm->isolate, 84 vm->env, 85 array->Get(v8::Integer::NewFromUnsigned(i))); 86 } 87 ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,array->Length()); 88 free(arr); 89 // send invocation request 90 SEND(vm->server, 91 enif_make_tuple3(env, 92 enif_make_copy(env,term), 93 enif_make_tuple7(env, 94 enif_make_atom(env,"erlv8_fun_invocation"), 95 enif_make_atom(env, "false"), 96 js_to_term(vm->context, vm->isolate, env, recv), // FIXME: not quite sure it's right 97 js_to_term(vm->context, vm->isolate, env, recv), 98 enif_make_copy(env, ref), 99 enif_make_pid(env, vm->server), 100 enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__")))) 101 ), 102 enif_make_copy(env,arglist))); 103}; 104