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

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