PageRenderTime 16ms CodeModel.GetById 3ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/c_src/erlv8_call.cc

http://github.com/beamjs/erlv8
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