PageRenderTime 48ms CodeModel.GetById 8ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 1ms

/c_src/erlv8_set.cc

http://github.com/beamjs/erlv8
C++ | 254 lines | 208 code | 40 blank | 6 comment | 28 complexity | a66b5452056a6fa05c9d76ac27d327e1 MD5 | raw file
  1#include "erlv8.hh"
  2
  3TickHandler(SetTickHandler) {
  4    ErlNifEnv *tmp_env = enif_alloc_env();
  5    ERL_NIF_TERM value = enif_make_copy(tmp_env, array[3]); // stashing it away since Set() might call an accessor, which might change vm->env
  6    val_res_t *obj_res;
  7    if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
  8        LHCS(vm->isolate, obj_res->ctx);
  9
 10        v8::PropertyAttribute property_attribute = v8::None;
 11
 12        if (arity == 5) {
 13            property_attribute = term_to_property_attribute(vm->env,array[4]);
 14        }
 15
 16        obj_res->val->ToObject()->Set(term_to_js(obj_res->ctx, vm->isolate, vm->env,array[2]),
 17                                      term_to_js(obj_res->ctx, vm->isolate, tmp_env,value),
 18                                      property_attribute);
 19
 20        SEND(vm->server,
 21             enif_make_tuple3(env,
 22                              enif_make_atom(env,"result"),
 23                              enif_make_copy(env,tick_ref),
 24                              enif_make_copy(env,value)));
 25    }
 26    enif_free_env(tmp_env);
 27    TickHandlerResolution result;
 28    result.type = DONE;
 29    return result;
 30}
 31
 32TickHandler(SetProtoTickHandler) {
 33    val_res_t *obj_res;
 34    if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
 35        LHCS(vm->isolate, obj_res->ctx);
 36
 37        const char *atom_val = obj_res->val->ToObject()->SetPrototype(term_to_js(obj_res->ctx,vm->isolate,vm->env,array[2])) ? "true" : "false";
 38
 39        SEND(vm->server,
 40             enif_make_tuple3(env,
 41                              enif_make_atom(env,"result"),
 42                              enif_make_copy(env,tick_ref),
 43                              enif_make_atom(env,atom_val)));
 44    }
 45    TickHandlerResolution result;
 46    result.type = DONE;
 47    return result;
 48}
 49
 50TickHandler(SetHiddenTickHandler) {
 51    val_res_t *obj_res;
 52    if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
 53        LHCS(vm->isolate, obj_res->ctx);
 54
 55        obj_res->val->ToObject()->SetHiddenValue(term_to_js(obj_res->ctx, vm->isolate, vm->env,array[2])->ToString(),term_to_js(obj_res->ctx,vm->isolate, vm->env,array[3]));
 56
 57        SEND(vm->server,
 58             enif_make_tuple3(env,
 59                              enif_make_atom(env,"result"),
 60                              enif_make_copy(env,tick_ref),
 61                              enif_make_copy(env,array[2])));
 62    }
 63    TickHandlerResolution result;
 64    result.type = DONE;
 65    return result;
 66}
 67
 68TickHandler(SetInternalTickHandler) {
 69    val_res_t *obj_res;
 70    char name[MAX_ATOM_LEN];
 71    unsigned len;
 72
 73    if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
 74        LHCS(vm->isolate, obj_res->ctx);
 75
 76        int index;
 77        enif_get_int(vm->env, array[2], &index);
 78
 79        if (index < 0 || (index + 1 > obj_res->val->ToObject()->InternalFieldCount())) {
 80            SEND(vm->server,
 81                 enif_make_tuple3(env,
 82                                  enif_make_atom(env,"result"),
 83                                  enif_make_copy(env,tick_ref),
 84                                  enif_make_atom(env,"error")));
 85        } else {
 86
 87            if (!strcmp(tick_name,"set_internal_extern")) {
 88                enif_get_atom_length(vm->env, array[4], &len, ERL_NIF_LATIN1);
 89                enif_get_atom(vm->env,array[4],(char *)&name,len + 1, ERL_NIF_LATIN1);
 90                v8::Handle<v8::Object> proto = extern_name_to_proto(vm, name);
 91                obj_res->val->ToObject()->SetInternalField(index,term_to_external(array[3]));
 92            } else {
 93                obj_res->val->ToObject()->SetInternalField(index,term_to_js(obj_res->ctx,vm->isolate, vm->env,array[3]));
 94            }
 95
 96            SEND(vm->server,
 97                 enif_make_tuple3(env,
 98                                  enif_make_atom(env,"result"),
 99                                  enif_make_copy(env,tick_ref),
100                                  enif_make_copy(env,array[3])));
101        }
102    }
103    TickHandlerResolution result;
104    result.type = DONE;
105    return result;
106}
107
108v8::Handle<v8::Value> GetterFun(v8::Local<v8::String> property,const v8::AccessorInfo &info); // fwd
109void SetterFun(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::AccessorInfo &info); // fwd
110
111void weak_accessor_data_cleaner(v8::Persistent<v8::Value> object, void * data) {
112    if (object.IsNearDeath()) {
113        object->ToObject()->DeleteHiddenValue(v8::String::New("_getter"));
114        object->ToObject()->DeleteHiddenValue(v8::String::New("_setter"));
115        object.Dispose();
116        object.Clear();
117    }
118}
119
120TickHandler(SetAccessorTickHandler) {
121    char aname[MAX_ATOM_LEN];
122    const char *atom_val;
123    val_res_t *obj_res;
124    if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
125        LHCS(vm->isolate, obj_res->ctx);
126
127        if (arity > 3) {
128            v8::Handle<v8::Value> name = term_to_js(obj_res->ctx,vm->isolate, vm->env,array[2]);
129            if (!name->IsString()) {
130                goto badarg;
131            }
132            v8::AccessorGetter getter = GetterFun;
133            v8::AccessorSetter setter = 0;
134            v8::Persistent<v8::Object> data = v8::Persistent<v8::Object>::New(v8::Object::New());
135            data.MakeWeak(NULL,weak_accessor_data_cleaner); // so that we'll release externals when we're done
136
137            if (term_to_js(obj_res->ctx,vm->isolate, vm->env,array[3])->IsUndefined()) {
138                goto badarg;
139            } else {
140                data->SetHiddenValue(v8::String::New("_getter"), term_to_external(array[3]));
141            }
142
143            if (arity > 4) {
144                setter = SetterFun;
145                data->SetHiddenValue(v8::String::New("_setter"), term_to_external(array[4]));
146            }
147
148            v8::AccessControl access_control = v8::DEFAULT;
149
150            if (arity > 5 && enif_is_atom(vm->env, array[5])) {
151                unsigned len;
152                enif_get_atom_length(vm->env, array[5], &len, ERL_NIF_LATIN1);
153                enif_get_atom(vm->env,array[5], (char *) &aname,len + 1, ERL_NIF_LATIN1);
154                if (!strcmp(aname,"default")) {
155                    access_control = v8::DEFAULT;
156                } else if (!strcmp(aname,"all_can_read")) {
157                    access_control = v8::ALL_CAN_READ;
158                } else if (!strcmp(aname,"all_can_write")) {
159                    access_control = v8::ALL_CAN_WRITE;
160                } else if (!strcmp(aname,"prohibits_overwriting")) {
161                    access_control = v8::PROHIBITS_OVERWRITING;
162                }
163            }
164
165            v8::PropertyAttribute property_attribute = v8::None;
166
167            if (arity > 6) {
168                property_attribute = term_to_property_attribute(vm->env,array[6]);
169            }
170
171            atom_val = obj_res->val->ToObject()->SetAccessor(name->ToString(), getter, setter, data,
172                                                             access_control, property_attribute) ? "true" : "false";
173            goto send;
174        }
175    badarg:
176        atom_val = "badarg";
177    send:
178        SEND(vm->server,
179             enif_make_tuple3(env,
180                              enif_make_atom(env,"result"),
181                              enif_make_copy(env,tick_ref),
182                              enif_make_atom(env, atom_val)));
183    }
184    TickHandlerResolution result;
185    result.type = DONE;
186    return result;
187}
188
189
190
191v8::Handle<v8::Value> GetterFun(v8::Local<v8::String> property,const v8::AccessorInfo &info) {
192    v8::HandleScope handle_scope;
193    VM * vm = (VM *)__ERLV8__(v8::Context::GetCurrent()->Global());
194
195    v8::Local<v8::Object> data = info.Data()->ToObject();
196
197    // each call gets a unique ref
198    ERL_NIF_TERM ref = enif_make_ref(vm->env);
199
200    // prepare arguments
201    ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * 1);
202    arr[0] = js_to_term(vm->context, vm->isolate, vm->env, property);
203    ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,1);
204    free(arr);
205
206    // send invocation request
207    SEND(vm->server,
208         enif_make_tuple3(env,
209                          enif_make_copy(env,external_to_term(data->GetHiddenValue(v8::String::New("_getter")))),
210                          enif_make_tuple7(env,
211                                           enif_make_atom(env,"erlv8_fun_invocation"),
212                                           enif_make_atom(env,"false"),
213                                           js_to_term(vm->context, vm->isolate, env, info.Holder()),
214                                           js_to_term(vm->context, vm->isolate, env, info.This()),
215                                           enif_make_copy(env, ref),
216                                           enif_make_pid(env, vm->server),
217                                           enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__"))))
218                                           ),
219                          enif_make_copy(env,arglist)));
220    return handle_scope.Close(vm->ticker(ref));
221}
222
223void SetterFun(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::AccessorInfo &info) {
224    v8::HandleScope handle_scope;
225    VM * vm = (VM *)__ERLV8__(v8::Context::GetCurrent()->Global());
226
227    v8::Local<v8::Object> data = info.Data()->ToObject();
228
229    // each call gets a unique ref
230    ERL_NIF_TERM ref = enif_make_ref(vm->env);
231
232    // prepare arguments
233    ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * 2);
234    arr[0] = js_to_term(vm->context, vm->isolate, vm->env, property);
235    arr[1] = js_to_term(vm->context, vm->isolate, vm->env, value);
236    ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,2);
237    free(arr);
238
239    // send invocation request
240    SEND(vm->server,
241         enif_make_tuple3(env,
242                          enif_make_copy(env,external_to_term(data->GetHiddenValue(v8::String::New("_setter")))),
243                          enif_make_tuple7(env,
244                                           enif_make_atom(env,"erlv8_fun_invocation"),
245                                           enif_make_atom(env,"false"),
246                                           js_to_term(vm->context, vm->isolate, env, info.Holder()),
247                                           js_to_term(vm->context, vm->isolate, env, info.This()),
248                                           enif_make_copy(env, ref),
249                                           enif_make_pid(env, vm->server),
250                                           enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__"))))
251                                           ),
252                          enif_make_copy(env,arglist)));
253    vm->ticker(ref);
254}