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