1# Common methods to handle properties 2 3The `jerryscript-ext/handler.h` header defines a set of convenience methods 4which makes the property access a bit straightforward. 5 6## jerryx_set_property_str 7 8**Summary** 9 10Set a property on a target object with a given name. 11 12*Note*: 13- The property name must be a zero terminated UTF-8 string. 14- There should be no '\0' (NULL) character in the name excluding the string terminator. 15- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it 16 is no longer needed. 17 18 19**Prototype** 20 21```c 22jerry_value_t 23jerryx_set_property_str (const jerry_value_t target_object, 24 const char *name, 25 const jerry_value_t value); 26``` 27 28- `target_object` - the object where the property should be set 29- `name` - name of the property 30- `value` - property value to be set 31- return value 32 - JS true value, if success 33 - thrown error, if there was a problem setting the property 34 35**Example** 36 37[doctest]: # () 38 39```c 40#include "jerryscript.h" 41#include "jerryscript-ext/handler.h" 42 43int 44main (int argc, char **argv) 45{ 46 jerry_init (JERRY_INIT_EMPTY); 47 48 jerry_value_t global = jerry_get_global_object (); 49 50 jerry_value_t value = jerry_create_number (3.3); 51 jerry_value_t result = jerryx_set_property_str (global, "value", value); 52 if (jerry_value_is_error (result)) 53 { 54 /* The error type/reason can be extracted via the `jerry_get_value_from_error` method */ 55 printf ("Error during property configuration\r\n"); 56 } 57 58 jerry_release_value (result); 59 jerry_release_value (value); 60 jerry_release_value (global); 61 jerry_cleanup(); 62 63 return 0; 64} 65``` 66 67## jerryx_get_property_str 68 69**Summary** 70 71Get the value of a property from the specified object with the given name. 72 73*Notes*: 74- The property name must be a zero terminated UTF-8 string. 75- There should be no '\0' (NULL) character in the name excluding the string terminator. 76- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it 77 is no longer needed. 78 79 80**Prototype** 81 82``` 83jerry_value_t 84jerryx_get_property_str (const jerry_value_t target_object, 85 const char *name); 86``` 87 88- `target_object` - object on which the property name is accessed 89- `name` - property name as an UTF-8 `char*` 90- return value 91 - value of property, if success 92 - thrown error, if there was a problem accessing the property 93 94**Example** 95 96[doctest]: # () 97 98```c 99#include "jerryscript.h" 100#include "jerryscript-ext/handler.h" 101 102int 103main (int argc, char **argv) 104{ 105 jerry_init (JERRY_INIT_EMPTY); 106 107 jerry_value_t global = jerry_get_global_object (); 108 109 jerry_value_t math_object = jerryx_get_property_str (global, "Math"); 110 111 /* use math_object */ 112 113 jerry_release_value (math_object); 114 jerry_release_value (global); 115 jerry_cleanup(); 116 117 return 0; 118} 119``` 120 121## jerryx_has_property_str 122 123**Summary** 124 125Check if a property exists on an object. 126 127*Notes*: 128- The operation performed is the same as what the `jerry_has_property` method. 129- The property name must be a zero terminated UTF-8 string. 130- There should be no '\0' (NULL) character in the name excluding the string terminator. 131 132 133**Prototype** 134 135``` 136bool 137jerryx_has_property_str (const jerry_value_t target_object, 138 const char *name); 139``` 140 141- `target_object` - object on which the property name is accessed 142- `name` - property name as an UTF-8 `char*` 143- return value 144 - true, if the given property name exsits on the object 145 - false, if there is no such property name or there was an error accessing the property 146 147**Example** 148 149[doctest]: # () 150 151```c 152#include "jerryscript.h" 153#include "jerryscript-ext/handler.h" 154 155int 156main (int argc, char **argv) 157{ 158 jerry_init (JERRY_INIT_EMPTY); 159 160 jerry_value_t global = jerry_get_global_object (); 161 162 bool have_math = jerryx_has_property_str (global, "Math"); 163 164 jerry_release_value (global); 165 jerry_cleanup(); 166 167 return have_math ? 0 : 1; 168} 169``` 170 171# Utility to register multiple properties in bulk 172 173In some cases it is useful to register multiple properties for a given object 174for this the following utility structures and methods are provided. 175 176## jerryx_property_entry 177 178**Summary** 179 180Structure to define an array of properties with `name` and `value` fields which 181can be registered to a target object. 182 183The engine must be initialied before specifying the `jerry_value_t` in the struct. 184 185 186**Prototype** 187 188```c 189typedef struct { 190 const char *name; 191 jerry_value_t value; 192} jerryx_function_list_entry; 193``` 194 195**See also** 196 197- [jerryx_set_properties](#jerryx_set_properties) 198 199 200## jerryx_register_result 201 202**Summary** 203 204Structure returned as the result of the [jerryx_set_properties](#jerryx_set_properties) operation. 205The `result` field will either be a JavaScript undefined value or an error object. 206In every case the `registered` field is used to indicated the number of 207successfully registered methods. 208 209This must be passed for the [jerryx_release_property_entry](#jerryx_release_property_entry) method 210after the property registration. 211 212If any error occured during the property registration the `result` field of the structure 213must be manually released after processing the error value. 214 215**Prototype** 216 217```c 218typedef struct { 219 jerry_value_t result; 220 uint32_t registered; 221} jerryx_register_result; 222``` 223 224**See also** 225 226- [jerryx_set_properties](#jerryx_set_properties) 227- [jerryx_release_property_entry](#jerryx_release_property_entry) 228 229 230## jerryx_set_properties 231 232**Summary** 233 234Set multiple properties on a target object. 235 236The properties are an array of (name, jerry_value_t) pairs and 237this list must end with a (NULL, 0) entry. 238 239Important notes: 240* Each property value in the input array is released after a successful property registration. 241* The method [jerryx_release_property_entry](#jerryx_release_property_entry) must be called if there is any failed registration 242 to release the values in the entries array. 243 It is safe to call this cleanup method in every case not just in case of failure. 244* If the error value is reported via the result it must be freed manually. 245 246**Prototype** 247 248```c 249jerryx_register_result 250jerryx_set_properties (const jerry_value_t target_object, 251 const jerryx_property_entry entries[]); 252``` 253 254- `target_object` - object on which the entries will be set. 255- `entries` - array of (name, jerry_value_t) pairs. 256- return a [jerryx_register_result](#jerryx_register_result). 257 - if everything is ok, the struct's `result` field is set to a JS undefined value. 258 - otherwise the `result` field is an error object indicating the problem. 259 - in every case the `registered` field contains the number of successfully registered properties. 260 261**Example** 262 263[doctest]: # () 264 265```c 266#include "jerryscript.h" 267#include "jerryscript-ext/handler.h" 268 269static jerry_value_t 270handler (const jerry_value_t function_obj, 271 const jerry_value_t this_val, 272 const jerry_value_t args_p[], 273 const jerry_length_t args_cnt) 274{ 275 printf ("native handler called!\n"); 276 277 return jerry_create_boolean (true); 278} 279 280int 281main (int argc, char **argv) 282{ 283 jerry_init (JERRY_INIT_EMPTY); 284 285 jerryx_property_entry methods[] = 286 { 287 { "demo", jerry_create_external_function (handler) }, 288 { NULL, 0 }, 289 }; 290 291 jerry_value_t global = jerry_get_global_object (); 292 jerryx_register_result reg = jerryx_set_properties (global, methods); 293 /* if `reg.result` is undefined all methods are registered */ 294 if (jerry_value_is_error (reg.result)) 295 { 296 printf ("Only registered %d properties\r\n", reg.registered); 297 /* clean up not registered property values */ 298 jerryx_release_property_entry (methods, reg); 299 300 /* clean up the error */ 301 jerry_release_value (reg.result); 302 } 303 304 jerry_release_value (global); 305 306 jerry_cleanup(); 307 308 return 0; 309} 310``` 311 312**Convenience macros** 313 314To make property registration convenient, there are a set of macros to use 315when setting a property entry: 316 317* `JERRYX_PROPERTY_NUMBER(NAME, NUMBER)` - creates a number entry. 318* `JERRYX_PROPERTY_STRING(NAME, STR)` - creates an UTF-8 string entry. This string must be zero terminated. 319* `JERRYX_PROPERTY_STRING_SZ(NAME, STR, SIZE)` - creates an UTF-8 string entry using only `SIZE` bytes from the string. 320* `JERRYX_PROPERTY_BOOLEAN(NAME, VALUE)` - creates a boolean entry. 321* `JERRYX_PROPERTY_FUNCTION(NAME, NATIVE)` - creates a native C function entry. 322* `JERRYX_PROPERTY_UNDEFINED(NAME)` - creates an undefined property entry. 323* `JERRYX_PROPERTY_LIST_END()` - indicates the end of the property list. 324 325**Example usage of Convenience macros** 326 327[doctest]: # () 328 329```c 330#include "jerryscript.h" 331#include "jerryscript-ext/handler.h" 332 333static jerry_value_t 334handler (const jerry_value_t function_obj, 335 const jerry_value_t this_val, 336 const jerry_value_t args_p[], 337 const jerry_length_t args_cnt) 338{ 339 printf ("native handler called!\n"); 340 341 return jerry_create_boolean (true); 342} 343 344int 345main (int argc, char **argv) 346{ 347 jerry_init (JERRY_INIT_EMPTY); 348 349 /** 350 * Create a array of properties to be registered. 351 * This must be done after initializing the engine as creating `jerry_value_t` 352 * elements are invalid before `jerry_init`. 353 */ 354 jerryx_property_entry methods[] = 355 { 356 JERRYX_PROPERTY_FUNCTION ("demo", handler), 357 JERRYX_PROPERTY_NUMBER ("test_num", 2.3), 358 JERRYX_PROPERTY_UNDEFINED ("this_is_undefined"), 359 JERRYX_PROPERTY_LIST_END(), 360 }; 361 362 jerry_value_t global = jerry_get_global_object (); 363 jerryx_register_result reg = jerryx_set_properties (global, methods); 364 /* if `reg.result` is undefined all methods are registered */ 365 if (jerry_value_is_error (reg.result)) 366 { 367 printf ("Only registered %d properties\r\n", reg.registered); 368 /* clean up not registered property values */ 369 jerryx_release_property_entry (methods, reg); 370 371 /* clean up the error */ 372 jerry_release_value (reg.result); 373 } 374 375 jerry_release_value (global); 376 377 jerry_cleanup(); 378 379 return 0; 380} 381``` 382 383 384**See also** 385 386- [jerryx_property_entry](#jerryx_property_entry) 387- [jerryx_release_property_entry](#jerryx_release_property_entry) 388- [jerryx_register_result](#jerryx_register_result) 389 390## jerryx_release_property_entry 391 392**Summary** 393 394Release all `jerry_value_t` in a `jerryx_property_entry` array based on a previous [jerryx_set_properties](#jerryx_set_properties) call 395and also the error value (if any) in the `jerryx_register_result` structure. 396In case of a successful registration it is safe to call this method. 397 398After the method call the `ęntries` array should not be used as all values are released. 399 400**Prototype** 401 402``` 403void 404jerryx_release_property_entry (const jerryx_property_entry entries[], 405 const jerryx_register_result register_result); 406``` 407 408- `entires` - array of [jerryx_property_entry](#jerryx_property_entry). 409- `register_result` - result of a previous [jerryx_set_properties](#jerryx_set_properties) call. 410 411**Example** 412 413For example usage see [jerryx_set_properties](#jerryx_set_properties). 414 415 416# Common external function handlers 417 418## jerryx_handler_assert_fatal 419 420**Summary** 421 422Hard assert for scripts. The routine calls `jerry_port_fatal` on assertion failure. 423 424If the `JERRY_FEATURE_LINE_INFO` runtime feature is enabled (build option: `JERRY_LINE_INFO`) 425a backtrace is also printed out. 426 427**Prototype** 428 429```c 430jerry_value_t 431jerryx_handler_assert_fatal (const jerry_value_t func_obj_val, const jerry_value_t this_p, 432 const jerry_value_t args_p[], const jerry_length_t args_cnt); 433``` 434 435- `func_obj_val` - the function object that was called (unused). 436- `this_p` - the `this` value of the call (unused). 437- `args_p` - the array of function arguments. 438- `args_cnt` - the number of function arguments. 439- return value - `jerry_value_t` representing boolean true, if only one argument 440 was passed and that argument was a boolean true. Note that the function does 441 not return otherwise. 442 443**See also** 444 445- [jerryx_handler_register_global](#jerryx_handler_register_global) 446 447 448## jerryx_handler_assert_throw 449 450**Summary** 451 452Soft assert for scripts. The routine throws an error on assertion failure. 453 454**Prototype** 455 456```c 457jerry_value_t 458jerryx_handler_assert_throw (const jerry_value_t func_obj_val, const jerry_value_t this_p, 459 const jerry_value_t args_p[], const jerry_length_t args_cnt); 460``` 461 462- `func_obj_val` - the function object that was called (unused). 463- `this_p` - the `this` value of the call (unused). 464- `args_p` - the array of function arguments. 465- `args_cnt` - the number of function arguments. 466- return value - `jerry_value_t` representing boolean true, if only one argument 467 was passed and that argument was a boolean true, an error otherwise. 468 469**See also** 470 471- [jerryx_handler_register_global](#jerryx_handler_register_global) 472 473 474## jerryx_handler_assert 475 476**Summary** 477 478An alias to `jerryx_handler_assert_fatal`. 479 480**See also** 481 482- [jerryx_handler_assert_fatal](#jerryx_handler_assert_fatal) 483 484 485## jerryx_handler_gc 486 487**Summary** 488 489Expose garbage collector to scripts. If the first argument of the function 490is logical true, it performs a high pressure gc. Otherwise a low pressure 491gc is performed, which is also the default if no parameters passed. 492 493**Prototype** 494 495```c 496jerry_value_t 497jerryx_handler_gc (const jerry_value_t func_obj_val, const jerry_value_t this_p, 498 const jerry_value_t args_p[], const jerry_length_t args_cnt); 499``` 500 501- `func_obj_val` - the function object that was called (unused). 502- `this_p` - the `this` value of the call (unused). 503- `args_p` - the array of function arguments (unused). 504- `args_cnt` - the number of function arguments (unused). 505- return value - `jerry_value_t` representing `undefined`. 506 507**See also** 508 509- [jerryx_handler_register_global](#jerryx_handler_register_global) 510 511 512## jerryx_handler_print 513 514**Summary** 515 516Provide a `print` implementation for scripts. The routine converts all of its 517arguments to strings and outputs them char-by-char using 518`jerry_port_print_char`. The NUL character is output as "\u0000", 519other characters are output bytewise. 520 521*Note*: This implementation does not use standard C `printf` to print its 522output. This allows more flexibility but also extends the core JerryScript 523engine port API. Applications that want to use `jerryx_handler_print` must 524ensure that their port implementation also provides 525`jerry_port_print_char`. 526 527**Prototype** 528 529```c 530jerry_value_t 531jerryx_handler_print (const jerry_value_t func_obj_val, const jerry_value_t this_p, 532 const jerry_value_t args_p[], const jerry_length_t args_cnt); 533``` 534 535- `func_obj_val` - the function object that was called (unused). 536- `this_p` - the `this` value of the call (unused). 537- `args_p` - the array of function arguments. 538- `args_cnt` - the number of function arguments. 539- return value - `jerry_value_t` representing `undefined` if all arguments could 540 be converted to strings, an `Error` otherwise. 541 542**See also** 543 544- [jerryx_handler_register_global](#jerryx_handler_register_global) 545- [jerry_port_print_char](05.PORT-API.md#jerry_port_print_char) 546 547 548# Handler registration helper 549 550## jerryx_handler_register_global 551 552**Summary** 553 554Register a JavaScript function in the global object. 555 556*Note*: Returned value must be freed with `jerry_release_value`, when it is no 557longer needed. 558 559**Prototype** 560 561```c 562jerry_value_t 563jerryx_handler_register_global (const jerry_char_t *name_p, 564 jerry_external_handler_t handler_p); 565``` 566 567- `name_p` - the name of the function to be registered. 568- `handler_p` - the address of the external function handler. 569- return value - `jerry_value_t` representing boolean true, if the operation was 570 successful, an `Error` otherwise. 571 572**Example** 573 574[doctest]: # (test="compile") 575 576```c 577#include "jerryscript.h" 578#include "jerryscript-ext/handler.h" 579 580static const struct { 581 const char *name_p; 582 jerry_external_handler_t handler_p; 583} common_functions[] = 584{ 585 { "assert", jerryx_handler_assert }, 586 { "gc", jerryx_handler_gc }, 587 { "print", jerryx_handler_print }, 588 { NULL, NULL } 589}; 590 591static void 592register_common_functions (void) 593{ 594 jerry_value_t ret = jerry_create_undefined (); 595 596 for (int i = 0; common_functions[i].name_p != NULL && !jerry_value_is_error (ret); i++) 597 { 598 ret = jerryx_handler_register_global ((const jerry_char_t *) common_functions[i].name_p, 599 common_functions[i].handler_p); 600 } 601 602 jerry_release_value (ret); 603} 604``` 605