9c8863ec646919f844c1a5895388c86a0e5fd3ea
[platform/upstream/iotjs.git] / src / iotjs_binding.c
1 /* Copyright 2015-present Samsung Electronics Co., Ltd. and other contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16
17 #include "iotjs_def.h"
18 #include "iotjs_binding.h"
19
20 #include <string.h>
21
22
23 static iotjs_jval_t jundefined;
24 static iotjs_jval_t jnull;
25 static iotjs_jval_t jtrue;
26 static iotjs_jval_t jfalse;
27 static iotjs_jval_t jglobal;
28
29 static iotjs_jargs_t jargs_empty;
30
31 static jerry_value_t iotjs_jval_as_raw(const iotjs_jval_t* jval);
32
33
34 iotjs_jval_t iotjs_jval_create_number(double v) {
35   iotjs_jval_t jval;
36   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
37
38   _this->value = jerry_create_number(v);
39   return jval;
40 }
41
42
43 iotjs_jval_t iotjs_jval_create_string(const iotjs_string_t* v) {
44   iotjs_jval_t jval;
45   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
46
47   const jerry_char_t* data = (const jerry_char_t*)(iotjs_string_data(v));
48   jerry_size_t size = iotjs_string_size(v);
49
50   _this->value = jerry_create_string_sz(data, size);
51
52   return jval;
53 }
54
55
56 iotjs_jval_t iotjs_jval_get_string_size(const iotjs_string_t* str) {
57   iotjs_jval_t str_val = iotjs_jval_create_string(str);
58   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, &str_val);
59
60   jerry_size_t size = jerry_get_string_size(_this->value);
61   iotjs_jval_t jval = iotjs_jval_create_number(size);
62
63   iotjs_jval_destroy(&str_val);
64
65   return jval;
66 }
67
68
69 iotjs_jval_t iotjs_jval_create_string_raw(const char* data) {
70   iotjs_jval_t jval;
71   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
72
73   _this->value = jerry_create_string((const jerry_char_t*)data);
74
75   return jval;
76 }
77
78
79 iotjs_jval_t iotjs_jval_create_object() {
80   iotjs_jval_t jval;
81   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
82
83   _this->value = jerry_create_object();
84
85   return jval;
86 }
87
88
89 iotjs_jval_t iotjs_jval_create_array(uint32_t len) {
90   iotjs_jval_t jval;
91   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
92
93   _this->value = jerry_create_array(len);
94
95   return jval;
96 }
97
98
99 iotjs_jval_t iotjs_jval_create_byte_array(uint32_t len, const char* data) {
100   iotjs_jval_t jval;
101   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
102
103   IOTJS_ASSERT(data != NULL);
104
105   _this->value = jerry_create_array(len);
106   for (uint32_t i = 0; i < len; i++) {
107     jerry_value_t val = jerry_create_number((double)data[i]);
108     jerry_set_property_by_index(_this->value, i, val);
109     jerry_release_value(val);
110   }
111
112   return jval;
113 }
114
115
116 iotjs_jval_t iotjs_jval_create_function(JHandlerType handler) {
117   iotjs_jval_t jval;
118   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
119
120   _this->value = jerry_create_external_function(handler);
121   IOTJS_ASSERT(jerry_value_is_constructor(_this->value));
122
123   return jval;
124 }
125
126
127 iotjs_jval_t iotjs_jval_create_error(const char* msg) {
128   return iotjs_jval_create_error_type(IOTJS_ERROR_COMMON, msg);
129 }
130
131
132 iotjs_jval_t iotjs_jval_create_error_type(iotjs_error_t type, const char* msg) {
133   iotjs_jval_t jval;
134   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
135
136   const jerry_char_t* jmsg = (const jerry_char_t*)(msg);
137   _this->value = jerry_create_error((jerry_error_t)type, jmsg);
138   jerry_value_clear_error_flag(&_this->value);
139
140   return jval;
141 }
142
143
144 iotjs_jval_t iotjs_jval_create_copied(const iotjs_jval_t* other) {
145   iotjs_jval_t jval;
146   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
147
148   _this->value = jerry_acquire_value(iotjs_jval_as_raw(other));
149   return jval;
150 }
151
152
153 static iotjs_jval_t iotjs_jval_create_raw(jerry_value_t val) {
154   iotjs_jval_t jval;
155   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jval_t, &jval);
156
157   _this->value = val;
158
159   return jval;
160 }
161
162
163 void iotjs_jval_destroy(iotjs_jval_t* jval) {
164   IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_jval_t, jval);
165   jerry_release_value(_this->value);
166 }
167
168
169 static void iotjs_jval_destroy_norelease(iotjs_jval_t* jval) {
170   IOTJS_VALIDATABLE_STRUCT_DESTRUCTOR_VALIDATE(iotjs_jval_t, jval);
171 }
172
173
174 iotjs_jval_t* iotjs_jval_get_undefined() {
175   return &jundefined;
176 }
177
178
179 iotjs_jval_t* iotjs_jval_get_null() {
180   return &jnull;
181 }
182
183
184 iotjs_jval_t* iotjs_jval_get_boolean(bool v) {
185   return v ? &jtrue : &jfalse;
186 }
187
188
189 iotjs_jval_t* iotjs_jval_get_global_object() {
190   return &jglobal;
191 }
192
193
194 #define TYPE_CHECKER_BODY(jval_type)                        \
195   bool iotjs_jval_is_##jval_type(const iotjs_jval_t* val) { \
196     const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, val); \
197     return jerry_value_is_##jval_type(_this->value);        \
198   }
199
200 FOR_EACH_JVAL_TYPES(TYPE_CHECKER_BODY)
201
202 #undef TYPE_CHECKER_BODY
203
204
205 bool iotjs_jval_as_boolean(const iotjs_jval_t* jval) {
206   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jval);
207   IOTJS_ASSERT(iotjs_jval_is_boolean(jval));
208   return jerry_get_boolean_value(_this->value);
209 }
210
211
212 double iotjs_jval_as_number(const iotjs_jval_t* jval) {
213   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jval);
214   IOTJS_ASSERT(iotjs_jval_is_number(jval));
215   return jerry_get_number_value(_this->value);
216 }
217
218
219 iotjs_string_t iotjs_jval_as_string(const iotjs_jval_t* jval) {
220   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jval);
221   IOTJS_ASSERT(iotjs_jval_is_string(jval));
222
223   jerry_size_t size = jerry_get_string_size(_this->value);
224
225   if (size == 0)
226     return iotjs_string_create();
227
228   char* buffer = iotjs_buffer_allocate(size + 1);
229   jerry_char_t* jerry_buffer = (jerry_char_t*)(buffer);
230
231   size_t check = jerry_string_to_char_buffer(_this->value, jerry_buffer, size);
232
233   IOTJS_ASSERT(check == size);
234   buffer[size] = '\0';
235
236   iotjs_string_t res = iotjs_string_create_with_buffer(buffer, size);
237
238   return res;
239 }
240
241
242 const iotjs_jval_t* iotjs_jval_as_object(const iotjs_jval_t* jval) {
243   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jval);
244   IOTJS_ASSERT(iotjs_jval_is_object(jval));
245   return jval;
246 }
247
248
249 const iotjs_jval_t* iotjs_jval_as_array(const iotjs_jval_t* jval) {
250   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jval);
251   IOTJS_ASSERT(iotjs_jval_is_array(jval));
252   return jval;
253 }
254
255
256 const iotjs_jval_t* iotjs_jval_as_function(const iotjs_jval_t* jval) {
257   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jval);
258   IOTJS_ASSERT(iotjs_jval_is_function(jval));
259   return jval;
260 }
261
262
263 static jerry_value_t iotjs_jval_as_raw(const iotjs_jval_t* jval) {
264   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jval);
265   return _this->value;
266 }
267
268
269 void iotjs_jval_set_method(const iotjs_jval_t* jobj, const char* name,
270                            iotjs_native_handler_t handler) {
271   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
272   IOTJS_ASSERT(iotjs_jval_is_object(jobj));
273
274   iotjs_jval_t jfunc = iotjs_jval_create_function_with_dispatch(handler);
275   iotjs_jval_set_property_jval(jobj, name, &jfunc);
276   iotjs_jval_destroy(&jfunc);
277 }
278
279
280 void iotjs_jval_set_property_jval(const iotjs_jval_t* jobj, const char* name,
281                                   const iotjs_jval_t* val) {
282   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jobj);
283   IOTJS_ASSERT(iotjs_jval_is_object(jobj));
284
285   jerry_value_t prop_name = jerry_create_string((const jerry_char_t*)(name));
286   jerry_value_t value = iotjs_jval_as_raw(val);
287   jerry_value_t ret_val = jerry_set_property(_this->value, prop_name, value);
288   jerry_release_value(prop_name);
289
290   IOTJS_ASSERT(!jerry_value_has_error_flag(ret_val));
291   jerry_release_value(ret_val);
292 }
293
294
295 void iotjs_jval_set_property_null(const iotjs_jval_t* jobj, const char* name) {
296   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
297   iotjs_jval_set_property_jval(jobj, name, iotjs_jval_get_null());
298 }
299
300
301 void iotjs_jval_set_property_undefined(const iotjs_jval_t* jobj,
302                                        const char* name) {
303   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
304   iotjs_jval_set_property_jval(jobj, name, iotjs_jval_get_undefined());
305 }
306
307
308 void iotjs_jval_set_property_boolean(const iotjs_jval_t* jobj, const char* name,
309                                      bool v) {
310   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
311   iotjs_jval_set_property_jval(jobj, name, iotjs_jval_get_boolean(v));
312 }
313
314
315 void iotjs_jval_set_property_number(const iotjs_jval_t* jobj, const char* name,
316                                     double v) {
317   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
318   iotjs_jval_t jval = iotjs_jval_create_number(v);
319   iotjs_jval_set_property_jval(jobj, name, &jval);
320   iotjs_jval_destroy(&jval);
321 }
322
323
324 void iotjs_jval_set_property_string(const iotjs_jval_t* jobj, const char* name,
325                                     const iotjs_string_t* v) {
326   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
327   iotjs_jval_t jval = iotjs_jval_create_string(v);
328   iotjs_jval_set_property_jval(jobj, name, &jval);
329   iotjs_jval_destroy(&jval);
330 }
331
332
333 void iotjs_jval_set_property_string_raw(const iotjs_jval_t* jobj,
334                                         const char* name, const char* v) {
335   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jval_t, jobj);
336   iotjs_jval_t jval = iotjs_jval_create_string_raw(v);
337   iotjs_jval_set_property_jval(jobj, name, &jval);
338   iotjs_jval_destroy(&jval);
339 }
340
341
342 iotjs_jval_t iotjs_jval_get_property(const iotjs_jval_t* jobj,
343                                      const char* name) {
344   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jobj);
345   IOTJS_ASSERT(iotjs_jval_is_object(jobj));
346
347   jerry_value_t prop_name = jerry_create_string((const jerry_char_t*)(name));
348   jerry_value_t res = jerry_get_property(_this->value, prop_name);
349   jerry_release_value(prop_name);
350
351   if (jerry_value_has_error_flag(res)) {
352     jerry_release_value(res);
353     return iotjs_jval_create_copied(iotjs_jval_get_undefined());
354   }
355
356   return iotjs_jval_create_raw(res);
357 }
358
359
360 void iotjs_jval_set_object_native_handle(const iotjs_jval_t* jobj,
361                                          uintptr_t ptr,
362                                          JFreeHandlerType free_handler) {
363   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jobj);
364   IOTJS_ASSERT(iotjs_jval_is_object(jobj));
365
366   jerry_set_object_native_handle(_this->value, ptr, free_handler);
367 }
368
369
370 uintptr_t iotjs_jval_get_object_native_handle(const iotjs_jval_t* jobj) {
371   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jobj);
372   IOTJS_ASSERT(iotjs_jval_is_object(jobj));
373
374   uintptr_t ptr;
375   jerry_get_object_native_handle(_this->value, &ptr);
376   return ptr;
377 }
378
379
380 void iotjs_jval_set_property_by_index(const iotjs_jval_t* jarr, uint32_t idx,
381                                       const iotjs_jval_t* jval) {
382   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jarr);
383   IOTJS_ASSERT(iotjs_jval_is_object(jarr));
384
385   jerry_value_t value = iotjs_jval_as_raw(jval);
386   jerry_value_t ret_val = jerry_set_property_by_index(_this->value, idx, value);
387   IOTJS_ASSERT(!jerry_value_has_error_flag(ret_val));
388   jerry_release_value(ret_val);
389 }
390
391
392 iotjs_jval_t iotjs_jval_get_property_by_index(const iotjs_jval_t* jarr,
393                                               uint32_t idx) {
394   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jval_t, jarr);
395   IOTJS_ASSERT(iotjs_jval_is_object(jarr));
396
397   jerry_value_t res = jerry_get_property_by_index(_this->value, idx);
398
399   if (jerry_value_has_error_flag(res)) {
400     jerry_release_value(res);
401     return iotjs_jval_create_copied(iotjs_jval_get_undefined());
402   }
403
404   return iotjs_jval_create_raw(res);
405 }
406
407
408 iotjs_jval_t iotjs_jhelper_call(const iotjs_jval_t* jfunc,
409                                 const iotjs_jval_t* jthis,
410                                 const iotjs_jargs_t* jargs, bool* throws) {
411   IOTJS_ASSERT(iotjs_jval_is_object(jfunc));
412
413   jerry_value_t* jargv_ = NULL;
414   jerry_length_t jargc_ = iotjs_jargs_length(jargs);
415
416 #ifdef NDEBUG
417   jargv_ = (jerry_value_t*)jargs->unsafe.argv;
418 #else
419   if (jargc_ > 0) {
420     unsigned buffer_size = sizeof(iotjs_jval_t) * jargc_;
421     jargv_ = (jerry_value_t*)iotjs_buffer_allocate(buffer_size);
422     for (unsigned i = 0; i < jargc_; ++i) {
423       jargv_[i] = iotjs_jval_as_raw(iotjs_jargs_get(jargs, i));
424     }
425   }
426 #endif
427
428   jerry_value_t jfunc_ = iotjs_jval_as_raw(jfunc);
429   jerry_value_t jthis_ = iotjs_jval_as_raw(jthis);
430   jerry_value_t res = jerry_call_function(jfunc_, jthis_, jargv_, jargc_);
431
432 #ifndef NDEBUG
433   if (jargv_) {
434     iotjs_buffer_release((char*)jargv_);
435   }
436 #endif
437
438   *throws = jerry_value_has_error_flag(res);
439
440   jerry_value_clear_error_flag(&res);
441
442   return iotjs_jval_create_raw(res);
443 }
444
445
446 iotjs_jval_t iotjs_jhelper_call_ok(const iotjs_jval_t* jfunc,
447                                    const iotjs_jval_t* jthis,
448                                    const iotjs_jargs_t* jargs) {
449   bool throws;
450   iotjs_jval_t jres = iotjs_jhelper_call(jfunc, jthis, jargs, &throws);
451   IOTJS_ASSERT(!throws);
452   return jres;
453 }
454
455
456 iotjs_jval_t iotjs_jhelper_eval(const char* data, size_t size, bool strict_mode,
457                                 bool* throws) {
458   jerry_value_t res = jerry_eval((const jerry_char_t*)data, size, strict_mode);
459
460   *throws = jerry_value_has_error_flag(res);
461
462   jerry_value_clear_error_flag(&res);
463
464   return iotjs_jval_create_raw(res);
465 }
466
467
468 #ifdef ENABLE_SNAPSHOT
469 iotjs_jval_t iotjs_jhelper_exec_snapshot(const void* snapshot_p,
470                                          size_t snapshot_size, bool* throws) {
471   jerry_value_t res = jerry_exec_snapshot(snapshot_p, snapshot_size, false);
472   /* the snapshot buffer can be referenced
473    * until jerry_cleanup is not called */
474
475   *throws = jerry_value_has_error_flag(res);
476
477   jerry_value_clear_error_flag(&res);
478
479   return iotjs_jval_create_raw(res);
480 }
481 #endif
482
483
484 iotjs_jargs_t iotjs_jargs_create(uint16_t capacity) {
485   iotjs_jargs_t jargs;
486   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jargs_t, &jargs);
487
488   _this->capacity = capacity;
489   _this->argc = 0;
490   if (capacity > 0) {
491     unsigned buffer_size = sizeof(iotjs_jval_t) * capacity;
492     _this->argv = (iotjs_jval_t*)iotjs_buffer_allocate(buffer_size);
493   } else {
494     return jargs_empty;
495   }
496
497   return jargs;
498 }
499
500
501 static void iotjs_jargs_initialize_empty(iotjs_jargs_t* jargs) {
502   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jargs_t, jargs);
503   _this->capacity = 0;
504   _this->argc = 0;
505   _this->argv = NULL;
506 }
507
508
509 const iotjs_jargs_t* iotjs_jargs_get_empty() {
510   return &jargs_empty;
511 }
512
513
514 void iotjs_jargs_destroy(iotjs_jargs_t* jargs) {
515   IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_jargs_t, jargs);
516
517   IOTJS_ASSERT(_this->argv == NULL || _this->argc > 0);
518   IOTJS_ASSERT(_this->argc <= _this->capacity);
519
520   if (_this->capacity > 0) {
521     for (unsigned i = 0; i < _this->argc; ++i) {
522       iotjs_jval_destroy(&_this->argv[i]);
523     }
524     iotjs_buffer_release((char*)_this->argv);
525   } else {
526     IOTJS_ASSERT(_this->argv == NULL);
527   }
528 }
529
530
531 uint16_t iotjs_jargs_length(const iotjs_jargs_t* jargs) {
532   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jargs_t, jargs);
533   return _this->argc;
534 }
535
536
537 void iotjs_jargs_append_jval(iotjs_jargs_t* jargs, const iotjs_jval_t* x) {
538   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jargs_t, jargs);
539   IOTJS_ASSERT(_this->argc < _this->capacity);
540   _this->argv[_this->argc++] = iotjs_jval_create_copied(x);
541 }
542
543
544 void iotjs_jargs_append_undefined(iotjs_jargs_t* jargs) {
545   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
546   iotjs_jargs_append_jval(jargs, iotjs_jval_get_undefined());
547 }
548
549
550 void iotjs_jargs_append_null(iotjs_jargs_t* jargs) {
551   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
552   iotjs_jargs_append_jval(jargs, iotjs_jval_get_null());
553 }
554
555
556 void iotjs_jargs_append_bool(iotjs_jargs_t* jargs, bool x) {
557   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
558   iotjs_jargs_append_jval(jargs, iotjs_jval_get_boolean(x));
559 }
560
561
562 void iotjs_jargs_append_number(iotjs_jargs_t* jargs, double x) {
563   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
564   iotjs_jval_t jval = iotjs_jval_create_number(x);
565   iotjs_jargs_append_jval(jargs, &jval);
566   iotjs_jval_destroy(&jval);
567 }
568
569
570 void iotjs_jargs_append_string(iotjs_jargs_t* jargs, const iotjs_string_t* x) {
571   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
572   iotjs_jval_t jval = iotjs_jval_create_string(x);
573   iotjs_jargs_append_jval(jargs, &jval);
574   iotjs_jval_destroy(&jval);
575 }
576
577
578 void iotjs_jargs_append_error(iotjs_jargs_t* jargs, const char* msg) {
579   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
580   iotjs_jval_t error = iotjs_jval_create_error(msg);
581   iotjs_jargs_append_jval(jargs, &error);
582   iotjs_jval_destroy(&error);
583 }
584
585
586 void iotjs_jargs_append_string_raw(iotjs_jargs_t* jargs, const char* x) {
587   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jargs_t, jargs);
588   iotjs_jval_t jval = iotjs_jval_create_string_raw(x);
589   iotjs_jargs_append_jval(jargs, &jval);
590   iotjs_jval_destroy(&jval);
591 }
592
593
594 void iotjs_jargs_replace(iotjs_jargs_t* jargs, uint16_t index,
595                          const iotjs_jval_t* x) {
596   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jargs_t, jargs);
597
598   IOTJS_ASSERT(index < _this->argc);
599
600   iotjs_jval_destroy(&_this->argv[index]);
601   _this->argv[index] = iotjs_jval_create_copied(x);
602 }
603
604
605 const iotjs_jval_t* iotjs_jargs_get(const iotjs_jargs_t* jargs,
606                                     uint16_t index) {
607   const IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jargs_t, jargs);
608
609   IOTJS_ASSERT(index < _this->argc);
610   return &_this->argv[index];
611 }
612
613
614 void iotjs_jhandler_initialize(iotjs_jhandler_t* jhandler,
615                                const jerry_value_t jfunc,
616                                const jerry_value_t jthis,
617                                const jerry_value_t jargv[],
618                                const uint16_t jargc) {
619   IOTJS_VALIDATED_STRUCT_CONSTRUCTOR(iotjs_jhandler_t, jhandler);
620
621   _this->jfunc = iotjs_jval_create_raw(jfunc);
622   _this->jthis = iotjs_jval_create_raw(jthis);
623   _this->jret = iotjs_jval_create_copied(iotjs_jval_get_undefined());
624 #ifdef NDEBUG
625   _this->jargv = (iotjs_jval_t*)jargv;
626 #else
627   if (jargc > 0) {
628     unsigned buffer_size = sizeof(iotjs_jval_t) * jargc;
629     _this->jargv = (iotjs_jval_t*)iotjs_buffer_allocate(buffer_size);
630     for (int i = 0; i < jargc; ++i) {
631       _this->jargv[i] = iotjs_jval_create_raw(jargv[i]);
632     }
633   } else {
634     _this->jargv = NULL;
635   }
636   _this->finished = false;
637 #endif
638
639   _this->jargc = jargc;
640 }
641
642
643 void iotjs_jhandler_destroy(iotjs_jhandler_t* jhandler) {
644   IOTJS_VALIDATED_STRUCT_DESTRUCTOR(iotjs_jhandler_t, jhandler);
645   iotjs_jval_destroy_norelease(&_this->jfunc);
646   iotjs_jval_destroy_norelease(&_this->jthis);
647   iotjs_jval_destroy_norelease(&_this->jret);
648 #ifndef NDEBUG
649   if (_this->jargc > 0) {
650     for (int i = 0; i < _this->jargc; ++i) {
651       iotjs_jval_destroy_norelease(&_this->jargv[i]);
652     }
653     iotjs_buffer_release((char*)(_this->jargv));
654   } else {
655     IOTJS_ASSERT(_this->jargv == NULL);
656   }
657 #endif
658 }
659
660
661 const iotjs_jval_t* iotjs_jhandler_get_function(iotjs_jhandler_t* jhandler) {
662   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jhandler_t, jhandler);
663   return &_this->jfunc;
664 }
665
666
667 const iotjs_jval_t* iotjs_jhandler_get_this(iotjs_jhandler_t* jhandler) {
668   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jhandler_t, jhandler);
669   return &_this->jthis;
670 }
671
672
673 const iotjs_jval_t* iotjs_jhandler_get_arg(iotjs_jhandler_t* jhandler,
674                                            uint16_t index) {
675   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jhandler_t, jhandler);
676   IOTJS_ASSERT(index < _this->jargc);
677   return &_this->jargv[index];
678 }
679
680
681 uint16_t iotjs_jhandler_get_arg_length(iotjs_jhandler_t* jhandler) {
682   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jhandler_t, jhandler);
683   return _this->jargc;
684 }
685
686
687 void iotjs_jhandler_return_jval(iotjs_jhandler_t* jhandler,
688                                 const iotjs_jval_t* ret) {
689   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jhandler_t, jhandler);
690
691 #ifndef NDEBUG
692   IOTJS_ASSERT(_this->finished == false);
693 #endif
694
695   iotjs_jval_destroy(&_this->jret);
696   _this->jret = iotjs_jval_create_copied(ret);
697 #ifndef NDEBUG
698   _this->finished = true;
699 #endif
700 }
701
702
703 void iotjs_jhandler_return_undefined(iotjs_jhandler_t* jhandler) {
704   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jhandler_t, jhandler);
705   iotjs_jhandler_return_jval(jhandler, iotjs_jval_get_undefined());
706 }
707
708
709 void iotjs_jhandler_return_null(iotjs_jhandler_t* jhandler) {
710   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jhandler_t, jhandler);
711   iotjs_jhandler_return_jval(jhandler, iotjs_jval_get_null());
712 }
713
714
715 void iotjs_jhandler_return_boolean(iotjs_jhandler_t* jhandler, bool ret) {
716   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jhandler_t, jhandler);
717   iotjs_jhandler_return_jval(jhandler, iotjs_jval_get_boolean(ret));
718 }
719
720
721 void iotjs_jhandler_return_number(iotjs_jhandler_t* jhandler, double ret) {
722   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jhandler_t, jhandler);
723   iotjs_jval_t jval = iotjs_jval_create_number(ret);
724   iotjs_jhandler_return_jval(jhandler, &jval);
725   iotjs_jval_destroy(&jval);
726 }
727
728
729 void iotjs_jhandler_return_string(iotjs_jhandler_t* jhandler,
730                                   const iotjs_string_t* ret) {
731   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jhandler_t, jhandler);
732   iotjs_jval_t jval = iotjs_jval_create_string(ret);
733   iotjs_jhandler_return_jval(jhandler, &jval);
734   iotjs_jval_destroy(&jval);
735 }
736
737
738 void iotjs_jhandler_return_string_raw(iotjs_jhandler_t* jhandler,
739                                       const char* ret) {
740   IOTJS_VALIDATABLE_STRUCT_METHOD_VALIDATE(iotjs_jhandler_t, jhandler);
741   iotjs_jval_t jval = iotjs_jval_create_string_raw(ret);
742   iotjs_jhandler_return_jval(jhandler, &jval);
743   iotjs_jval_destroy(&jval);
744 }
745
746
747 void iotjs_jhandler_throw(iotjs_jhandler_t* jhandler, const iotjs_jval_t* err) {
748   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_jhandler_t, jhandler);
749 #ifndef NDEBUG
750   IOTJS_ASSERT(_this->finished == false);
751 #endif
752
753   iotjs_jval_destroy(&_this->jret);
754   _this->jret = iotjs_jval_create_copied(err);
755   jerry_value_set_error_flag(&_this->jret.unsafe.value);
756
757 #ifndef NDEBUG
758   _this->finished = true;
759 #endif
760 }
761
762
763 static jerry_value_t iotjs_native_dispatch_function(
764     const jerry_value_t jfunc, const jerry_value_t jthis,
765     const jerry_value_t jargv[], const JRawLengthType jargc) {
766   uintptr_t target_function_ptr = 0x0;
767   if (!jerry_get_object_native_handle(jfunc, &target_function_ptr)) {
768     const jerry_char_t* jmsg = (const jerry_char_t*)("Internal dispatch error");
769     return jerry_create_error((jerry_error_t)IOTJS_ERROR_COMMON, jmsg);
770   }
771
772   IOTJS_ASSERT(target_function_ptr != 0x0);
773
774   iotjs_jhandler_t jhandler;
775   iotjs_jhandler_initialize(&jhandler, jfunc, jthis, jargv, jargc);
776
777   ((iotjs_native_handler_t)target_function_ptr)(&jhandler);
778
779   jerry_value_t ret_val = jhandler.unsafe.jret.unsafe.value;
780   iotjs_jhandler_destroy(&jhandler);
781   return ret_val;
782 }
783
784
785 iotjs_jval_t iotjs_jval_create_function_with_dispatch(
786     iotjs_native_handler_t handler) {
787   iotjs_jval_t jfunc =
788       iotjs_jval_create_function(iotjs_native_dispatch_function);
789   iotjs_jval_set_object_native_handle(&jfunc, (uintptr_t)handler, NULL);
790   return jfunc;
791 }
792
793
794 void iotjs_binding_initialize() {
795   jundefined = iotjs_jval_create_raw(jerry_create_undefined());
796   jnull = iotjs_jval_create_raw(jerry_create_null());
797   jtrue = iotjs_jval_create_raw(jerry_create_boolean(true));
798   jfalse = iotjs_jval_create_raw(jerry_create_boolean(false));
799   jglobal = iotjs_jval_create_raw(jerry_get_global_object());
800
801   IOTJS_ASSERT(iotjs_jval_is_object(&jglobal));
802
803   iotjs_jargs_initialize_empty(&jargs_empty);
804
805 #ifdef NDEBUG
806   assert(sizeof(iotjs_jval_t) == sizeof(jerry_value_t));
807 #endif
808 }
809
810
811 void iotjs_binding_finalize() {
812   iotjs_jval_destroy(&jundefined);
813   iotjs_jval_destroy(&jnull);
814   iotjs_jval_destroy(&jtrue);
815   iotjs_jval_destroy(&jfalse);
816   iotjs_jval_destroy(&jglobal);
817   iotjs_jargs_destroy(&jargs_empty);
818 }