/c_src/erlv8_instantiate.cc

http://github.com/beamjs/erlv8 · C++ · 96 lines · 83 code · 11 blank · 2 comment · 8 complexity · eb3d03cde7097fa5168c66fe549a9082 MD5 · raw file

  1. #include "erlv8.hh"
  2. void ErlangConstFun(VM * vm, ERL_NIF_TERM term, ERL_NIF_TERM ref, v8::Handle<v8::Object> instance, v8::Handle<v8::Array> array); // fwd
  3. TickHandler(InstantiateTickHandler) {
  4. ErlNifEnv *ref_env = enif_alloc_env();
  5. ERL_NIF_TERM inst_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::Handle<v8::Function> f = v8::Handle<v8::Function>::Cast(fun_res->val);
  20. if (!*f->GetHiddenValue(vm->string__erlv8__)) { // js function
  21. v8::TryCatch try_catch;
  22. v8::Local<v8::Value> inst_result = f->NewInstance(alen, args);
  23. if (inst_result.IsEmpty()) {
  24. SEND(vm->server,
  25. enif_make_tuple3(env,
  26. enif_make_atom(env,"result"),
  27. enif_make_copy(env,inst_ref),
  28. enif_make_tuple2(env,
  29. enif_make_atom(env,"throw"),
  30. enif_make_tuple2(env,
  31. enif_make_atom(env,"error"),
  32. js_to_term(fun_res->ctx,vm->isolate, env,try_catch.Exception())))));
  33. } else {
  34. SEND(vm->server,
  35. enif_make_tuple3(env,
  36. enif_make_atom(env,"result"),
  37. enif_make_copy(env,inst_ref),
  38. js_to_term(fun_res->ctx,vm->isolate, env,inst_result)));
  39. }
  40. } else { // native Erlang function
  41. v8::Local<v8::Array> array = v8::Array::New(alen);
  42. for (unsigned int i=0;i<alen;i++) {
  43. array->Set(i,args[i]);
  44. }
  45. ErlangConstFun(vm,
  46. external_to_term(f->GetHiddenValue(v8::String::New("__erlv8__"))),
  47. inst_ref,
  48. vm->empty_constructor->GetFunction()->NewInstance(),
  49. array);
  50. }
  51. delete [] args;
  52. args = NULL;
  53. }
  54. enif_free_env(ref_env);
  55. TickHandlerResolution result;
  56. result.type = DONE;
  57. return result;
  58. }
  59. void ErlangConstFun(VM * vm, ERL_NIF_TERM term, ERL_NIF_TERM ref, v8::Handle<v8::Object> instance, v8::Handle<v8::Array> array) {
  60. v8::HandleScope handle_scope;
  61. ctx_res_t *ptr = (ctx_res_t *)enif_alloc_resource(ctx_resource, sizeof(ctx_res_t));
  62. ptr->ctx = v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
  63. // prepare arguments
  64. ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * array->Length());
  65. for (unsigned int i=0;i<array->Length();i++) {
  66. arr[i] = js_to_term(vm->context,vm->isolate, vm->env,array->Get(v8::Integer::NewFromUnsigned(i)));
  67. }
  68. ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,array->Length());
  69. free(arr);
  70. // send invocation request
  71. SEND(vm->server,
  72. enif_make_tuple3(env,
  73. enif_make_copy(env,term),
  74. enif_make_tuple7(env,
  75. enif_make_atom(env,"erlv8_fun_invocation"),
  76. enif_make_atom(env, "true"),
  77. js_to_term(vm->context, vm->isolate, env, instance), // FIXME: not quite sure it's right
  78. js_to_term(vm->context, vm->isolate, env, instance),
  79. enif_make_copy(env, ref),
  80. enif_make_pid(env, vm->server),
  81. enif_make_resource(env, ptr)
  82. ),
  83. enif_make_copy(env,arglist)));
  84. enif_release_resource(ptr);
  85. };