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