/c_src/erlv8_set.cc
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}