JerryScript Engine can be embedded into any application, providing the way to run JavaScript in a large range of environments - from desktops to low-memory microcontrollers. This guide is intended to introduce you to JerryScript embedding API and to create a minimal JavaScript shell. The examples are not using all API methods please also check out the API reference document which contains additional examples. ## Before trying out the examples: Get and build JerryScript library Before getting started using the JerryScript library it should be cloned and built for a target os/device. There are quite a few configuration options but for these examples the JerryScript is built **with default configuration** and installed to a user directory on a Linux system. This is done by the following commands: ```sh $ mkdir jerry $ cd jerry $ git clone https://github.com/jerryscript-project/jerryscript.git $ jerryscript/tools/build.py --builddir=$(pwd)/example_build --cmake-param="-DCMAKE_INSTALL_PREFIX=$(pwd)/example_install/" $ make -C $(pwd)/example_build install ``` With this the JerryScript library is installed into the `$(pwd)/example_install/{include,lib}` directories. In this guide we will use `pkg-config` to ease the usage of headers and libraries. In order to do so, the following export is required (executed from the jerry directory): ```sh $ export PKG_CONFIG_PATH=$(pwd)/example_install/lib/pkgconfig/ ``` Test if the `pkg-config` works for JerryScript: ```sh $ pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-ext libjerry-libm ``` ## Example 1. Execute JavaScript from your application The most basic example to test the engine is to create an `api-example-1.c` file containing the following code: [doctest]: # () ```c #include "jerryscript.h" int main (void) { const jerry_char_t script[] = "var str = 'Hello, World!';"; bool ret_value = jerry_run_simple (script, sizeof (script) - 1, JERRY_INIT_EMPTY); return (ret_value ? 0 : 1); } ``` To compile it one can use the following command: ```sh $ gcc api-example-1.c -o api-example-1 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) ``` If everything is correct the application returns with a zero exit code: ``` $ ./api-example-1 $ echo $? ``` ## Example 2. Split engine initialization and script execution. In this example the engine is initialized directly with the `jerry_init` method and cleaned up with the `jerry_cleanup` method. The example JavaScript code is directly parsed and executed via the `jerry_eval` method. Each `jerry_value_t` returned by the API methods is freed with the `jerry_release_value` method. To make sure that the code parsing and execution was ok, the `jerry_value_is_error` method is used to check for any errors. Use the following code for the `api-example-2.c` file: [doctest]: # () ```c #include "jerryscript.h" int main (void) { const jerry_char_t script[] = "var str = 'Hello, World!';"; const jerry_length_t script_size = sizeof (script) - 1; /* Note: sizeof can be used here only because the compiler knows the static character arrays's size. * If this is not the case, strlen should be used instead. */ /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Run the demo script with 'eval' */ jerry_value_t eval_ret = jerry_eval (script, script_size, JERRY_PARSE_NO_OPTS); /* Check if there was any error (syntax or runtime) */ bool run_ok = !jerry_value_is_error (eval_ret); /* Parsed source code must be freed */ jerry_release_value (eval_ret); /* Cleanup engine */ jerry_cleanup (); return (run_ok ? 0 : 1); } ``` To compile it one can use the following command: ```sh $ gcc api-example-2.c -o api-example-2 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) ``` If everything is correct the application returns with a zero exit code: ``` $ ./api-example-2 $ echo $? ``` ## Example 3. Split JavaScript parsing and script execution In this example the `jerry_eval` is replaced with a more common API calls: - script code setup - `jerry_parse`. - script execution - `jerry_run`. The `api-example-3.c` file should contain the following code: [doctest]: # () ```c #include "jerryscript.h" int main (void) { bool run_ok = false; const jerry_char_t script[] = "var str = 'Hello, World!';"; /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Setup Global scope code */ jerry_value_t parsed_code = jerry_parse (NULL, 0, script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); /* Check if there is any JS code parse error */ if (!jerry_value_is_error (parsed_code)) { /* Execute the parsed source code in the Global scope */ jerry_value_t ret_value = jerry_run (parsed_code); /* Check the execution return value if there is any error */ run_ok = !jerry_value_is_error (ret_value); /* Returned value must be freed */ jerry_release_value (ret_value); } /* Parsed source code must be freed */ jerry_release_value (parsed_code); /* Cleanup engine */ jerry_cleanup (); return (run_ok ? 0 : 1); } ``` To compile it one can use the following command: ```sh $ gcc api-example-3.c -o api-example-3 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) ``` If everything is correct the application returns with a zero exit code: ``` $ ./api-example-3 $ echo $? ``` ## Example 4. Adding a C method for JavaScript The previous examples were not that eye catching as there were no visual output by the JavaScript code and C program. In this example a very simple "print" method is added which prints out a static string. This method will be implemented in C and will be called from the JavaScript code. For this a few extra API methods are required: - `jerry_get_global_object` - `jerry_create_string` - `jerry_set_property` - `jerry_create_external_function` The `api-example-4.c` file should contain the following code: [doctest]: # () ```c #include #include "jerryscript.h" static jerry_value_t print_handler (const jerry_value_t function_object, const jerry_value_t function_this, const jerry_value_t arguments[], const jerry_length_t argument_count) { /* No arguments are used in this example */ /* Print out a static string */ printf ("Print handler was called\n"); /* Return an "undefined" value to the JavaScript engine */ return jerry_create_undefined (); } int main (void) { const jerry_char_t script[] = "print ();"; const jerry_length_t script_size = sizeof (script) - 1; /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Add the "print" method for the JavaScript global object */ { /* Get the "global" object */ jerry_value_t global_object = jerry_get_global_object (); /* Create a "print" JS string */ jerry_value_t property_name_print = jerry_create_string ((const jerry_char_t *) "print"); /* Create a function from a native C method (this function will be called from JS) */ jerry_value_t property_value_func = jerry_create_external_function (print_handler); /* Add the "print" property with the function value to the "global" object */ jerry_value_t set_result = jerry_set_property (global_object, property_name_print, property_value_func); /* Check if there was no error when adding the property (in this case it should never happen) */ if (jerry_value_is_error (set_result)) { printf ("Failed to add the 'print' property\n"); } /* Release all jerry_value_t-s */ jerry_release_value (set_result); jerry_release_value (property_value_func); jerry_release_value (property_name_print); jerry_release_value (global_object); } /* Setup Global scope code */ jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS); if (!jerry_value_is_error (parsed_code)) { /* Execute the parsed source code in the Global scope */ jerry_value_t ret_value = jerry_run (parsed_code); /* Returned value must be freed */ jerry_release_value (ret_value); } /* Parsed source code must be freed */ jerry_release_value (parsed_code); /* Cleanup engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: ```sh $ gcc api-example-4.c -o api-example-4 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) ``` If everything is correct the application should print out the message present in the `print_handler` method: ``` $ ./api-example-4 ``` ## Example 5. Passing and processing arguments for native C code In the previous example the `print_handler` simply wrote a static string to the standard output. However in most cases this is not useful, ideally the method's argument(s) should be printed. In this example the `print_handler` is extended to convert the first argument (which probably comes from a JavaScript source) to a JS string and prints it out to the standard output. New API methods used: - `jerry_value_to_string` - `jerry_string_to_utf8_char_buffer` The `api-example-5.c` file should contain the following code: [doctest]: # () ```c #include #include "jerryscript.h" static jerry_value_t print_handler (const jerry_value_t function_object, const jerry_value_t function_this, const jerry_value_t arguments[], const jerry_length_t arguments_count) { /* There should be at least one argument */ if (arguments_count > 0) { /* Convert the first argument to a string (JS "toString" operation) */ jerry_value_t string_value = jerry_value_to_string (arguments[0]); /* A naive allocation of buffer for the string */ jerry_char_t buffer[256]; /* Copy the whole string to the buffer, without a null termination character, * Please note that if the string does not fit into the buffer nothing will be copied. * More details on the API reference page */ jerry_size_t copied_bytes = jerry_string_to_utf8_char_buffer (string_value, buffer, sizeof (buffer) - 1); buffer[copied_bytes] = '\0'; /* Release the "toString" result */ jerry_release_value (string_value); printf ("%s\n", (const char *)buffer); } /* Return an "undefined" value to the JavaScript engine */ return jerry_create_undefined (); } int main (void) { const jerry_char_t script[] = "print ('Hello from JS!');"; const jerry_length_t script_size = sizeof (script) - 1; /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Add the "print" method for the JavaScript global object */ { /* Get the "global" object */ jerry_value_t global_object = jerry_get_global_object (); /* Create a "print" JS string */ jerry_value_t property_name_print = jerry_create_string ((const jerry_char_t *) "print"); /* Create a function from a native C method (this function will be called from JS) */ jerry_value_t property_value_func = jerry_create_external_function (print_handler); /* Add the "print" property with the function value to the "global" object */ jerry_value_t set_result = jerry_set_property (global_object, property_name_print, property_value_func); /* Check if there was no error when adding the property (in this case it should never happen) */ if (jerry_value_is_error (set_result)) { printf ("Failed to add the 'print' property\n"); } /* Release all jerry_value_t-s */ jerry_release_value (set_result); jerry_release_value (property_value_func); jerry_release_value (property_name_print); jerry_release_value (global_object); } /* Setup Global scope code */ jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS); if (!jerry_value_is_error (parsed_code)) { /* Execute the parsed source code in the Global scope */ jerry_value_t ret_value = jerry_run (parsed_code); /* Returned value must be freed */ jerry_release_value (ret_value); } /* Parsed source code must be freed */ jerry_release_value (parsed_code); /* Cleanup engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: ```sh $ gcc api-example-5.c -o api-example-5 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) ``` If everything is correct the application should print out the string passed for the `print` method in the JS code: ``` $ ./api-example-5 ``` ## Example 6. Using JerryScript Extensions Some of the previous examples used a "print" method to write data out to the standard output. For convenience JerryScript provides an extension to add a simple "print" handler which can be used by other applications. In this example the following extension methods are used: - `jerryx_handler_register_global` - `jerryx_handler_print` In further examples this "print" handler will be used. ```c #include "jerryscript.h" #include "jerryscript-ext/handler.h" int main (void) { const jerry_char_t script[] = "print ('Hello from JS with ext!');"; const jerry_length_t script_size = sizeof (script) - 1; /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Register 'print' function from the extensions to the global object */ jerryx_handler_register_global ((const jerry_char_t *) "print", jerryx_handler_print); /* Setup Global scope code */ jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS); if (!jerry_value_is_error (parsed_code)) { /* Execute the parsed source code in the Global scope */ jerry_value_t ret_value = jerry_run (parsed_code); /* Returned value must be freed */ jerry_release_value (ret_value); } /* Parsed source code must be freed */ jerry_release_value (parsed_code); /* Cleanup engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: (**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. ```sh $ gcc api-example-6.c -o api-example-6 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm) ``` If everything is correct the application should print out the string passed for the `print` method in the JS code: ``` $ ./api-example-6 ``` ## Example 7. Interaction with JavaScript environment - adding a string property Previously a C method was registered for the global object, now this examples show how one can add a string property. Use the following code as the `api-example-7.c` file: [doctest]: # () ```c #include "jerryscript.h" #include "jerryscript-ext/handler.h" int main (void) { const jerry_char_t script[] = "print (my_var);"; /* Initializing JavaScript environment */ jerry_init (JERRY_INIT_EMPTY); /* Register 'print' function from the extensions */ jerryx_handler_register_global ((const jerry_char_t *) "print", jerryx_handler_print); /* Getting pointer to the Global object */ jerry_value_t global_object = jerry_get_global_object (); /* Constructing strings */ jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_var"); jerry_value_t prop_value = jerry_create_string ((const jerry_char_t *) "Hello from C!"); /* Setting the string value as a property of the Global object */ jerry_value_t set_result = jerry_set_property (global_object, prop_name, prop_value); /* The 'set_result' should be checked if there was any error */ if (jerry_value_is_error (set_result)) { printf ("Failed to add the 'my_var' property\n"); } jerry_release_value (set_result); /* Releasing string values, as it is no longer necessary outside of engine */ jerry_release_value (prop_name); jerry_release_value (prop_value); /* Releasing the Global object */ jerry_release_value (global_object); /* Now starting script that would output value of just initialized field */ jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); /* Freeing engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: (**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. ```sh $ gcc api-example-7.c -o api-example-7 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm) ``` The sample will output 'Hello from C!'. However, now it is not just a part of the source script, but the value, dynamically supplied to the engine: ``` $ ./api-example-7 ``` ## Example 8. Description of JerryScript value descriptors JerryScript value can be a boolean, number, null, object, string, undefined or some special type of objects (arraybuffer, symbols, etc). There is a special "error" value which wraps another value. This "error" can be created by throwing a JavaScript value from JS code or via API method(s). It is advised to check for this error with the `jerry_value_is_error` method as not all API methods can process error values. To extract the value from the "error" the API method `jerry_get_value_from_error` should be used. If an error object is created via API method (for example with `jerry_create_error`) the "error" value is automatically created. Notice the difference between error value and error object: - The error object is a object which was constructed via one of the `Error` objects (available from the global object or from API). For example in JS such object be created with the following code example: ```js var error_object = new Error ("error message"); ``` - The error value is not an object on its own. This is the exception raised/thrown either via API methods or from JS. For example, creating such error value in JS would look like this: ```js throw "message"; ``` To check what type a given `jerry_value_t` is the `jerry_value_is_*` methods or the `jerry_value_get_type` could be used. For example the following code snippet could print out a few types (not all types are checked): [doctest]: # (test="compile") ```c #include #include #include "jerryscript.h" static void print_value (const jerry_value_t jsvalue) { jerry_value_t value; /* If there is an error extract the object from it */ if (jerry_value_is_error (jsvalue)) { printf ("Error value detected: "); value = jerry_get_value_from_error (jsvalue, false); } else { value = jerry_acquire_value (jsvalue); } if (jerry_value_is_undefined (value)) { printf ("undefined"); } else if (jerry_value_is_null (value)) { printf ("null"); } else if (jerry_value_is_boolean (value)) { if (jerry_get_boolean_value (value)) { printf ("true"); } else { printf ("false"); } } /* Float value */ else if (jerry_value_is_number (value)) { printf ("number: %lf", jerry_get_number_value (value)); } /* String value */ else if (jerry_value_is_string (value)) { jerry_char_t str_buf_p[256]; /* Determining required buffer size */ jerry_size_t req_sz = jerry_get_string_size (value); if (req_sz <= 255) { jerry_string_to_char_buffer (value, str_buf_p, req_sz); str_buf_p[req_sz] = '\0'; printf ("%s", (const char *) str_buf_p); } else { printf ("error: buffer isn't big enough"); } } /* Object reference */ else if (jerry_value_is_object (value)) { printf ("[JS object]"); } printf ("\n"); jerry_release_value (value); } ``` ## Example 8: Simple JavaScript shell Now all building blocks, necessary to construct JavaScript shell, are ready. Shell operation can be described with the following loop: - read command; - if command is 'quit' - exit loop; - else - eval (command); - print result of eval; - loop. See the following `api-example-8-shell.c` file: [doctest]: # (test="link") ```c #include #include #include #include "jerryscript.h" #include "jerryscript-ext/handler.h" static void print_value (const jerry_value_t jsvalue) { jerry_value_t value; /* If there is an error extract the object from it */ if (jerry_value_is_error (jsvalue)) { printf ("Error value detected: "); value = jerry_get_value_from_error (jsvalue, false); } else { value = jerry_acquire_value (jsvalue); } if (jerry_value_is_undefined (value)) { printf ("undefined"); } else if (jerry_value_is_null (value)) { printf ("null"); } else if (jerry_value_is_boolean (value)) { if (jerry_get_boolean_value (value)) { printf ("true"); } else { printf ("false"); } } /* Float value */ else if (jerry_value_is_number (value)) { printf ("number: %lf", jerry_get_number_value (value)); } /* String value */ else if (jerry_value_is_string (value)) { jerry_char_t str_buf_p[256]; /* Determining required buffer size */ jerry_size_t req_sz = jerry_get_string_size (value); if (req_sz <= 255) { jerry_string_to_char_buffer (value, str_buf_p, req_sz); str_buf_p[req_sz] = '\0'; printf ("%s", (const char *) str_buf_p); } else { printf ("error: buffer isn't big enough"); } } /* Object reference */ else if (jerry_value_is_object (value)) { printf ("[JS object]"); } printf ("\n"); jerry_release_value (value); } int main (void) { bool is_done = false; /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Register 'print' function from the extensions */ jerryx_handler_register_global ((const jerry_char_t *) "print", jerryx_handler_print); while (!is_done) { char cmd[256]; char *cmd_tail = cmd; size_t len = 0; printf ("> "); /* Read next command */ while (true) { if (fread (cmd_tail, 1, 1, stdin) != 1 && len == 0) { is_done = true; break; } if (*cmd_tail == '\n') { break; } cmd_tail++; len++; } /* If the command is "quit", break the loop */ if (!strncmp (cmd, "quit\n", sizeof ("quit\n") - 1)) { break; } jerry_value_t ret_val; /* Evaluate entered command */ ret_val = jerry_eval ((const jerry_char_t *) cmd, len, JERRY_PARSE_NO_OPTS); /* Print out the value */ print_value (ret_val); jerry_release_value (ret_val); } /* Cleanup engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: (**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. ```sh $ gcc api-example-8-shell.c -o api-example-8-shell $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm) ``` The application reads lines from standard input and evaluates them, one after another. To try out run: ``` $ ./api-example-8-shell ``` ## Example 9. Creating JS object in global context In this example (`api-example-9.c`) an object with a native function is added to the global object. [doctest]: # () ```c #include "jerryscript.h" #include "jerryscript-ext/handler.h" struct my_struct { const char *msg; } my_struct; /** * Get a string from a native object */ static jerry_value_t get_msg_handler (const jerry_value_t func_value, /**< function object */ const jerry_value_t this_value, /**< this arg */ const jerry_value_t *args_p, /**< function arguments */ const jerry_length_t args_cnt) /**< number of function arguments */ { return jerry_create_string ((const jerry_char_t *) my_struct.msg); } /* get_msg_handler */ int main (void) { /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Register 'print' function from the extensions */ jerryx_handler_register_global ((const jerry_char_t *) "print", jerryx_handler_print); /* Do something with the native object */ my_struct.msg = "Hello, World!"; /* Create an empty JS object */ jerry_value_t object = jerry_create_object (); /* Create a JS function object and wrap into a jerry value */ jerry_value_t func_obj = jerry_create_external_function (get_msg_handler); /* Set the native function as a property of the empty JS object */ jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "myFunc"); jerry_release_value (jerry_set_property (object, prop_name, func_obj)); jerry_release_value (prop_name); jerry_release_value (func_obj); /* Wrap the JS object (not empty anymore) into a jerry api value */ jerry_value_t global_object = jerry_get_global_object (); /* Add the JS object to the global context */ prop_name = jerry_create_string ((const jerry_char_t *) "MyObject"); jerry_release_value (jerry_set_property (global_object, prop_name, object)); jerry_release_value (prop_name); jerry_release_value (object); jerry_release_value (global_object); /* Now we have a "builtin" object called MyObject with a function called myFunc() * * Equivalent JS code: * var MyObject = { myFunc : function () { return "some string value"; } } */ const jerry_char_t script[] = " \ var str = MyObject.myFunc (); \ print (str); \ "; /* Evaluate script */ jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); /* Cleanup engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: (**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. ```sh $ gcc api-example-9.c -o api-example-9 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm) ``` Execute the example with: ``` $ ./api-example-9 ``` The application will generate the following output: ```bash Hello, World ``` ## Example 10. Extending JS Objects with native functions The example creates a JS Object with `jerry_eval`, then it is extended from C with a native function. In addition this native function shows how to get a property value from the object and how to manipulate it. Use the following code for `api-example-10.c`: [doctest]: # () ```c #include "jerryscript.h" #include "jerryscript-ext/handler.h" /** * Add param to 'this.x' */ static jerry_value_t add_handler (const jerry_value_t func_value, /**< function object */ const jerry_value_t this_val, /**< this arg */ const jerry_value_t args_p[], /**< function arguments */ const jerry_length_t args_cnt) /**< number of function arguments */ { /* The the 'this_val' is the 'MyObject' from the JS code below */ /* Note: that the argument count check is ignored for the example's case */ /* Get 'this.x' */ jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "x"); jerry_value_t x_val = jerry_get_property (this_val, prop_name); if (!jerry_value_is_error (x_val)) { /* Convert Jerry API values to double */ double x = jerry_get_number_value (x_val); double d = jerry_get_number_value (args_p[0]); /* Add the parameter to 'x' */ jerry_value_t res_val = jerry_create_number (x + d); /* Set the new value of 'this.x' */ jerry_release_value (jerry_set_property (this_val, prop_name, res_val)); jerry_release_value (res_val); } jerry_release_value (x_val); jerry_release_value (prop_name); return jerry_create_undefined (); } /* add_handler */ int main (void) { /* Initialize engine */ jerry_init (JERRY_INIT_EMPTY); /* Register 'print' function from the extensions */ jerryx_handler_register_global ((const jerry_char_t *) "print", jerryx_handler_print); /* Create a JS object */ const jerry_char_t my_js_object[] = " \ MyObject = \ { x : 12, \ y : 'Value of x is ', \ foo: function () \ { \ return this.y + this.x; \ } \ } \ "; jerry_value_t my_js_obj_val; /* Evaluate script */ my_js_obj_val = jerry_eval (my_js_object, sizeof (my_js_object) - 1, JERRY_PARSE_NO_OPTS); /* Create a JS function object and wrap into a jerry value */ jerry_value_t add_func_obj = jerry_create_external_function (add_handler); /* Set the native function as a property of previously created MyObject */ jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "add2x"); jerry_release_value (jerry_set_property (my_js_obj_val, prop_name, add_func_obj)); jerry_release_value (add_func_obj); jerry_release_value (prop_name); /* Free JavaScript value, returned by eval (my_js_object) */ jerry_release_value (my_js_obj_val); const jerry_char_t script[] = " \ var str = MyObject.foo (); \ print (str); \ MyObject.add2x (5); \ print (MyObject.foo ()); \ "; /* Evaluate script */ jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); /* Free JavaScript value, returned by eval */ jerry_release_value (eval_ret); /* Cleanup engine */ jerry_cleanup (); return 0; } ``` To compile it one can use the following command: (**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. ```sh $ gcc api-example-10.c -o api-example-10 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm) ``` Execute the example with: ``` $ ./api-example-10 ``` ```bash Value of x is 12 Value of x is 17 ``` ## Example 11. Changing the seed of pseudorandom generated numbers If you want to change the seed of `Math.random()` generated numbers, you have to initialize the seed value with `srand`. A recommended method is using `jerry_port_get_current_time()` or something based on a constantly changing value, therefore every run produces truly random numbers. [doctest]: # () ```c #include #include "jerryscript.h" #include "jerryscript-port.h" #include "jerryscript-ext/handler.h" int main (void) { /* Initialize srand value */ union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () }; srand (now.u); /* Generate a random number, and print it */ const jerry_char_t script[] = "var a = Math.random (); print(a)"; /* Initialize the engine */ jerry_init (JERRY_INIT_EMPTY); /* Register the print function */ jerryx_handler_register_global ((const jerry_char_t *) "print", jerryx_handler_print); /* Evaluate the script */ jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); /* Free the JavaScript value returned by eval */ jerry_release_value (eval_ret); /* Cleanup the engine */ jerry_cleanup (); return 0; } ``` ## Further steps For further API description, please visit [API Reference page](https://jerryscript-project.github.io/jerryscript/api-reference/) on [JerryScript home page](https://jerryscript-project.github.io/jerryscript/).