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 <stdio.h>
#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 <stdio.h>
#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 <stdio.h>
#include <stdlib.h>
#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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 <stdlib.h>
#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/).
