• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1JerryScript 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.
2
3This guide is intended to introduce you to JerryScript embedding API and to create a minimal JavaScript shell.
4The examples are not using all API methods please also check out the API reference document which contains additional examples.
5
6
7## Before trying out the examples: Get and build JerryScript library
8
9Before getting started using the JerryScript library it should be cloned and built for a target os/device.
10
11There are quite a few configuration options but for these examples the JerryScript is built
12**with default configuration** and installed to a user directory on a Linux system.
13This is done by the following commands:
14
15```sh
16$ mkdir jerry
17$ cd jerry
18$ git clone https://github.com/jerryscript-project/jerryscript.git
19$ jerryscript/tools/build.py --builddir=$(pwd)/example_build --cmake-param="-DCMAKE_INSTALL_PREFIX=$(pwd)/example_install/"
20$ make -C $(pwd)/example_build install
21```
22
23With this the JerryScript library is installed into the `$(pwd)/example_install/{include,lib}` directories.
24
25In this guide we will use `pkg-config` to ease the usage of headers and libraries.
26In order to do so, the following export is required (executed from the jerry directory):
27
28```sh
29$ export PKG_CONFIG_PATH=$(pwd)/example_install/lib/pkgconfig/
30```
31
32Test if the `pkg-config` works for JerryScript:
33
34```sh
35$ pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-ext libjerry-libm
36```
37
38## Example 1. Execute JavaScript from your application
39
40The most basic example to test the engine is to create an `api-example-1.c` file containing the following code:
41
42[doctest]: # ()
43
44```c
45#include "jerryscript.h"
46
47int
48main (void)
49{
50  const jerry_char_t script[] = "var str = 'Hello, World!';";
51
52  bool ret_value = jerry_run_simple (script, sizeof (script) - 1, JERRY_INIT_EMPTY);
53
54  return (ret_value ? 0 : 1);
55}
56```
57
58To compile it one can use the following command:
59
60```sh
61$ gcc api-example-1.c -o api-example-1 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm)
62```
63
64If everything is correct the application returns with a zero exit code:
65
66```
67$ ./api-example-1
68$ echo $?
69```
70
71## Example 2. Split engine initialization and script execution.
72
73In this example the engine is initialized directly with the `jerry_init` method
74and cleaned up with the `jerry_cleanup` method. The example JavaScript code
75is directly parsed and executed via the `jerry_eval` method. Each `jerry_value_t`
76returned by the API methods is freed with the `jerry_release_value` method.
77
78To make sure that the code parsing and execution was ok, the `jerry_value_is_error`
79method is used to check for any errors.
80
81Use the following code for the `api-example-2.c` file:
82
83[doctest]: # ()
84
85```c
86#include "jerryscript.h"
87
88int
89main (void)
90{
91  const jerry_char_t script[] = "var str = 'Hello, World!';";
92  const jerry_length_t script_size = sizeof (script) - 1;
93  /* Note: sizeof can be used here only because the compiler knows the static character arrays's size.
94   * If this is not the case, strlen should be used instead.
95   */
96
97  /* Initialize engine */
98  jerry_init (JERRY_INIT_EMPTY);
99
100  /* Run the demo script with 'eval' */
101  jerry_value_t eval_ret = jerry_eval (script,
102                                       script_size,
103                                       JERRY_PARSE_NO_OPTS);
104
105  /* Check if there was any error (syntax or runtime) */
106  bool run_ok = !jerry_value_is_error (eval_ret);
107
108  /* Parsed source code must be freed */
109  jerry_release_value (eval_ret);
110
111  /* Cleanup engine */
112  jerry_cleanup ();
113
114  return (run_ok ? 0 : 1);
115}
116```
117
118To compile it one can use the following command:
119
120```sh
121$ gcc api-example-2.c -o api-example-2 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm)
122```
123
124If everything is correct the application returns with a zero exit code:
125
126```
127$ ./api-example-2
128$ echo $?
129```
130
131## Example 3. Split JavaScript parsing and script execution
132
133In this example the `jerry_eval` is replaced with a more common API calls:
134
135- script code setup - `jerry_parse`.
136- script execution - `jerry_run`.
137
138The `api-example-3.c` file should contain the following code:
139
140[doctest]: # ()
141
142```c
143#include "jerryscript.h"
144
145int
146main (void)
147{
148  bool run_ok = false;
149
150  const jerry_char_t script[] = "var str = 'Hello, World!';";
151
152  /* Initialize engine */
153  jerry_init (JERRY_INIT_EMPTY);
154
155  /* Setup Global scope code */
156  jerry_value_t parsed_code = jerry_parse (NULL, 0, script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
157
158  /* Check if there is any JS code parse error */
159  if (!jerry_value_is_error (parsed_code))
160  {
161    /* Execute the parsed source code in the Global scope */
162    jerry_value_t ret_value = jerry_run (parsed_code);
163
164    /* Check the execution return value if there is any error */
165    run_ok = !jerry_value_is_error (ret_value);
166
167    /* Returned value must be freed */
168    jerry_release_value (ret_value);
169  }
170
171  /* Parsed source code must be freed */
172  jerry_release_value (parsed_code);
173
174  /* Cleanup engine */
175  jerry_cleanup ();
176
177  return (run_ok ? 0 : 1);
178}
179```
180
181To compile it one can use the following command:
182
183```sh
184$ gcc api-example-3.c -o api-example-3 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm)
185```
186
187If everything is correct the application returns with a zero exit code:
188
189```
190$ ./api-example-3
191$ echo $?
192```
193
194## Example 4. Adding a C method for JavaScript
195
196The previous examples were not that eye catching as there were no visual output by the JavaScript code
197and C program.
198
199In this example a very simple "print" method is added which prints out a static string.
200This method will be implemented in C and will be called from the JavaScript code.
201For this a few extra API methods are required:
202
203- `jerry_get_global_object`
204- `jerry_create_string`
205- `jerry_set_property`
206- `jerry_create_external_function`
207
208The `api-example-4.c` file should contain the following code:
209
210[doctest]: # ()
211
212```c
213#include <stdio.h>
214#include "jerryscript.h"
215
216static jerry_value_t
217print_handler (const jerry_value_t function_object,
218               const jerry_value_t function_this,
219               const jerry_value_t arguments[],
220               const jerry_length_t argument_count)
221{
222  /* No arguments are used in this example */
223  /* Print out a static string */
224  printf ("Print handler was called\n");
225
226  /* Return an "undefined" value to the JavaScript engine */
227  return jerry_create_undefined ();
228}
229
230int
231main (void)
232{
233  const jerry_char_t script[] = "print ();";
234  const jerry_length_t script_size = sizeof (script) - 1;
235
236  /* Initialize engine */
237  jerry_init (JERRY_INIT_EMPTY);
238
239  /* Add the "print" method for the JavaScript global object */
240  {
241    /* Get the "global" object */
242    jerry_value_t global_object = jerry_get_global_object ();
243    /* Create a "print" JS string */
244    jerry_value_t property_name_print = jerry_create_string ((const jerry_char_t *) "print");
245    /* Create a function from a native C method (this function will be called from JS) */
246    jerry_value_t property_value_func = jerry_create_external_function (print_handler);
247    /* Add the "print" property with the function value to the "global" object */
248    jerry_value_t set_result = jerry_set_property (global_object, property_name_print, property_value_func);
249
250    /* Check if there was no error when adding the property (in this case it should never happen) */
251    if (jerry_value_is_error (set_result)) {
252      printf ("Failed to add the 'print' property\n");
253    }
254
255    /* Release all jerry_value_t-s */
256    jerry_release_value (set_result);
257    jerry_release_value (property_value_func);
258    jerry_release_value (property_name_print);
259    jerry_release_value (global_object);
260  }
261
262  /* Setup Global scope code */
263  jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS);
264
265  if (!jerry_value_is_error (parsed_code))
266  {
267    /* Execute the parsed source code in the Global scope */
268    jerry_value_t ret_value = jerry_run (parsed_code);
269
270    /* Returned value must be freed */
271    jerry_release_value (ret_value);
272  }
273
274  /* Parsed source code must be freed */
275  jerry_release_value (parsed_code);
276
277  /* Cleanup engine */
278  jerry_cleanup ();
279
280  return 0;
281}
282```
283
284
285To compile it one can use the following command:
286
287```sh
288$ gcc api-example-4.c -o api-example-4 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm)
289```
290
291If everything is correct the application should print out the message present in the `print_handler` method:
292
293```
294$ ./api-example-4
295```
296
297## Example 5. Passing and processing arguments for native C code
298
299In the previous example the `print_handler` simply wrote a static string to the standard output.
300However in most cases this is not useful, ideally the method's argument(s) should be printed.
301
302In this example the `print_handler` is extended to convert the first
303argument (which probably comes from a JavaScript source) to a JS string and prints it out to the standard output.
304
305New API methods used:
306
307- `jerry_value_to_string`
308- `jerry_string_to_utf8_char_buffer`
309
310The `api-example-5.c` file should contain the following code:
311
312[doctest]: # ()
313
314```c
315#include <stdio.h>
316#include "jerryscript.h"
317
318static jerry_value_t
319print_handler (const jerry_value_t function_object,
320               const jerry_value_t function_this,
321               const jerry_value_t arguments[],
322               const jerry_length_t arguments_count)
323{
324  /* There should be at least one argument */
325  if (arguments_count > 0)
326  {
327    /* Convert the first argument to a string (JS "toString" operation) */
328    jerry_value_t string_value = jerry_value_to_string (arguments[0]);
329
330    /* A naive allocation of buffer for the string */
331    jerry_char_t buffer[256];
332
333    /* Copy the whole string to the buffer, without a null termination character,
334     * Please note that if the string does not fit into the buffer nothing will be copied.
335     * More details on the API reference page
336     */
337    jerry_size_t copied_bytes = jerry_string_to_utf8_char_buffer (string_value, buffer, sizeof (buffer) - 1);
338    buffer[copied_bytes] = '\0';
339
340    /* Release the "toString" result */
341    jerry_release_value (string_value);
342
343    printf ("%s\n", (const char *)buffer);
344  }
345
346  /* Return an "undefined" value to the JavaScript engine */
347  return jerry_create_undefined ();
348}
349
350int
351main (void)
352{
353  const jerry_char_t script[] = "print ('Hello from JS!');";
354  const jerry_length_t script_size = sizeof (script) - 1;
355
356  /* Initialize engine */
357  jerry_init (JERRY_INIT_EMPTY);
358
359  /* Add the "print" method for the JavaScript global object */
360  {
361    /* Get the "global" object */
362    jerry_value_t global_object = jerry_get_global_object ();
363    /* Create a "print" JS string */
364    jerry_value_t property_name_print = jerry_create_string ((const jerry_char_t *) "print");
365    /* Create a function from a native C method (this function will be called from JS) */
366    jerry_value_t property_value_func = jerry_create_external_function (print_handler);
367    /* Add the "print" property with the function value to the "global" object */
368    jerry_value_t set_result = jerry_set_property (global_object, property_name_print, property_value_func);
369
370    /* Check if there was no error when adding the property (in this case it should never happen) */
371    if (jerry_value_is_error (set_result)) {
372      printf ("Failed to add the 'print' property\n");
373    }
374
375    /* Release all jerry_value_t-s */
376    jerry_release_value (set_result);
377    jerry_release_value (property_value_func);
378    jerry_release_value (property_name_print);
379    jerry_release_value (global_object);
380  }
381
382  /* Setup Global scope code */
383  jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS);
384
385  if (!jerry_value_is_error (parsed_code))
386  {
387    /* Execute the parsed source code in the Global scope */
388    jerry_value_t ret_value = jerry_run (parsed_code);
389
390    /* Returned value must be freed */
391    jerry_release_value (ret_value);
392  }
393
394  /* Parsed source code must be freed */
395  jerry_release_value (parsed_code);
396
397  /* Cleanup engine */
398  jerry_cleanup ();
399
400  return 0;
401}
402```
403
404
405To compile it one can use the following command:
406
407```sh
408$ gcc api-example-5.c -o api-example-5 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm)
409```
410
411If everything is correct the application should print out the string passed for the `print` method in the JS code:
412
413```
414$ ./api-example-5
415```
416
417
418## Example 6. Using JerryScript Extensions
419
420Some of the previous examples used a "print" method to write data out to the standard output.
421For convenience JerryScript provides an extension to add a simple "print" handler which
422can be used by other applications.
423
424In this example the following extension methods are used:
425
426- `jerryx_handler_register_global`
427- `jerryx_handler_print`
428
429In further examples this "print" handler will be used.
430
431```c
432#include "jerryscript.h"
433#include "jerryscript-ext/handler.h"
434
435int
436main (void)
437{
438  const jerry_char_t script[] = "print ('Hello from JS with ext!');";
439  const jerry_length_t script_size = sizeof (script) - 1;
440
441  /* Initialize engine */
442  jerry_init (JERRY_INIT_EMPTY);
443
444  /* Register 'print' function from the extensions to the global object */
445  jerryx_handler_register_global ((const jerry_char_t *) "print",
446                                  jerryx_handler_print);
447
448  /* Setup Global scope code */
449  jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS);
450
451  if (!jerry_value_is_error (parsed_code))
452  {
453    /* Execute the parsed source code in the Global scope */
454    jerry_value_t ret_value = jerry_run (parsed_code);
455
456    /* Returned value must be freed */
457    jerry_release_value (ret_value);
458  }
459
460  /* Parsed source code must be freed */
461  jerry_release_value (parsed_code);
462
463  /* Cleanup engine */
464  jerry_cleanup ();
465
466  return 0;
467}
468```
469
470
471To compile it one can use the following command:
472
473(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call.
474
475```sh
476$ gcc api-example-6.c -o api-example-6 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm)
477```
478
479If everything is correct the application should print out the string passed for the `print` method in the JS code:
480
481```
482$ ./api-example-6
483```
484
485## Example 7. Interaction with JavaScript environment - adding a string property
486
487Previously a C method was registered for the global object, now this examples show how one can add a string
488property.
489
490Use the following code as the `api-example-7.c` file:
491
492[doctest]: # ()
493
494```c
495#include "jerryscript.h"
496#include "jerryscript-ext/handler.h"
497
498int
499main (void)
500{
501  const jerry_char_t script[] = "print (my_var);";
502
503  /* Initializing JavaScript environment */
504  jerry_init (JERRY_INIT_EMPTY);
505
506  /* Register 'print' function from the extensions */
507  jerryx_handler_register_global ((const jerry_char_t *) "print",
508                                  jerryx_handler_print);
509
510  /* Getting pointer to the Global object */
511  jerry_value_t global_object = jerry_get_global_object ();
512
513  /* Constructing strings */
514  jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_var");
515  jerry_value_t prop_value = jerry_create_string ((const jerry_char_t *) "Hello from C!");
516
517  /* Setting the string value as a property of the Global object */
518  jerry_value_t set_result = jerry_set_property (global_object, prop_name, prop_value);
519  /* The 'set_result' should be checked if there was any error */
520  if (jerry_value_is_error (set_result)) {
521    printf ("Failed to add the 'my_var' property\n");
522  }
523  jerry_release_value (set_result);
524
525  /* Releasing string values, as it is no longer necessary outside of engine */
526  jerry_release_value (prop_name);
527  jerry_release_value (prop_value);
528
529  /* Releasing the Global object */
530  jerry_release_value (global_object);
531
532  /* Now starting script that would output value of just initialized field */
533  jerry_value_t eval_ret = jerry_eval (script,
534                                       sizeof (script) - 1,
535                                       JERRY_PARSE_NO_OPTS);
536
537  /* Free JavaScript value, returned by eval */
538  jerry_release_value (eval_ret);
539
540  /* Freeing engine */
541  jerry_cleanup ();
542
543  return 0;
544}
545```
546
547To compile it one can use the following command:
548
549(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call.
550
551```sh
552$ gcc api-example-7.c -o api-example-7 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm)
553```
554
555The 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:
556
557```
558$ ./api-example-7
559```
560
561## Example 8. Description of JerryScript value descriptors
562
563JerryScript value can be a boolean, number, null, object, string, undefined or some special type of objects (arraybuffer, symbols, etc).
564
565There is a special "error" value which wraps another value. This "error" can be created by throwing a JavaScript value from JS code
566or via API method(s). It is advised to check for this error with the `jerry_value_is_error` method as not all API methods
567can process error values. To extract the value from the "error" the API method `jerry_get_value_from_error` should be used.
568If an error object is created via API method (for example with `jerry_create_error`) the "error" value is automatically created.
569
570Notice the difference between error value and error object:
571- The error object is a object which was constructed via one of the `Error` objects (available from the global object or from API).
572  For example in JS such object be created with the following code example:
573
574```js
575var error_object = new Error ("error message");
576```
577
578- The error value is not an object on its own. This is the exception raised/thrown either via API methods or from JS.
579  For example, creating such error value in JS would look like this:
580
581```js
582throw "message";
583```
584
585To check what type a given `jerry_value_t` is the `jerry_value_is_*` methods or the `jerry_value_get_type` could be used.
586For example the following code snippet could print out a few types (not all types are checked):
587
588[doctest]: # (test="compile")
589
590```c
591#include <stdio.h>
592#include <stdlib.h>
593#include "jerryscript.h"
594
595static void
596print_value (const jerry_value_t jsvalue)
597{
598  jerry_value_t value;
599  /* If there is an error extract the object from it */
600  if (jerry_value_is_error (jsvalue))
601  {
602    printf ("Error value detected: ");
603    value = jerry_get_value_from_error (jsvalue, false);
604  }
605  else
606  {
607    value = jerry_acquire_value (jsvalue);
608  }
609
610  if (jerry_value_is_undefined (value))
611  {
612    printf ("undefined");
613  }
614  else if (jerry_value_is_null (value))
615  {
616    printf ("null");
617  }
618  else if (jerry_value_is_boolean (value))
619  {
620    if (jerry_get_boolean_value (value))
621    {
622      printf ("true");
623    }
624    else
625    {
626      printf ("false");
627    }
628  }
629  /* Float value */
630  else if (jerry_value_is_number (value))
631  {
632    printf ("number: %lf", jerry_get_number_value (value));
633  }
634  /* String value */
635  else if (jerry_value_is_string (value))
636  {
637    jerry_char_t str_buf_p[256];
638
639    /* Determining required buffer size */
640    jerry_size_t req_sz = jerry_get_string_size (value);
641
642    if (req_sz <= 255)
643    {
644      jerry_string_to_char_buffer (value, str_buf_p, req_sz);
645      str_buf_p[req_sz] = '\0';
646      printf ("%s", (const char *) str_buf_p);
647    }
648    else
649    {
650      printf ("error: buffer isn't big enough");
651    }
652  }
653  /* Object reference */
654  else if (jerry_value_is_object (value))
655  {
656    printf ("[JS object]");
657  }
658
659  printf ("\n");
660  jerry_release_value (value);
661}
662```
663
664## Example 8: Simple JavaScript shell
665
666Now all building blocks, necessary to construct JavaScript shell, are ready.
667
668Shell operation can be described with the following loop:
669
670- read command;
671- if command is 'quit'
672  - exit loop;
673- else
674  - eval (command);
675  - print result of eval;
676  - loop.
677
678See the following `api-example-8-shell.c` file:
679
680[doctest]: # (test="link")
681
682```c
683#include <stdio.h>
684#include <stdlib.h>
685#include <string.h>
686#include "jerryscript.h"
687#include "jerryscript-ext/handler.h"
688
689static void
690print_value (const jerry_value_t jsvalue)
691{
692  jerry_value_t value;
693  /* If there is an error extract the object from it */
694  if (jerry_value_is_error (jsvalue))
695  {
696    printf ("Error value detected: ");
697    value = jerry_get_value_from_error (jsvalue, false);
698  }
699  else
700  {
701    value = jerry_acquire_value (jsvalue);
702  }
703
704  if (jerry_value_is_undefined (value))
705  {
706    printf ("undefined");
707  }
708  else if (jerry_value_is_null (value))
709  {
710    printf ("null");
711  }
712  else if (jerry_value_is_boolean (value))
713  {
714    if (jerry_get_boolean_value (value))
715    {
716      printf ("true");
717    }
718    else
719    {
720      printf ("false");
721    }
722  }
723  /* Float value */
724  else if (jerry_value_is_number (value))
725  {
726    printf ("number: %lf", jerry_get_number_value (value));
727  }
728  /* String value */
729  else if (jerry_value_is_string (value))
730  {
731    jerry_char_t str_buf_p[256];
732
733    /* Determining required buffer size */
734    jerry_size_t req_sz = jerry_get_string_size (value);
735
736    if (req_sz <= 255)
737    {
738      jerry_string_to_char_buffer (value, str_buf_p, req_sz);
739      str_buf_p[req_sz] = '\0';
740      printf ("%s", (const char *) str_buf_p);
741    }
742    else
743    {
744      printf ("error: buffer isn't big enough");
745    }
746  }
747  /* Object reference */
748  else if (jerry_value_is_object (value))
749  {
750    printf ("[JS object]");
751  }
752
753  printf ("\n");
754  jerry_release_value (value);
755}
756
757int
758main (void)
759{
760  bool is_done = false;
761
762  /* Initialize engine */
763  jerry_init (JERRY_INIT_EMPTY);
764
765  /* Register 'print' function from the extensions */
766  jerryx_handler_register_global ((const jerry_char_t *) "print",
767                                  jerryx_handler_print);
768
769  while (!is_done)
770  {
771    char cmd[256];
772    char *cmd_tail = cmd;
773    size_t len = 0;
774
775    printf ("> ");
776
777    /* Read next command */
778    while (true)
779    {
780      if (fread (cmd_tail, 1, 1, stdin) != 1 && len == 0)
781      {
782        is_done = true;
783        break;
784      }
785      if (*cmd_tail == '\n')
786      {
787        break;
788      }
789
790      cmd_tail++;
791      len++;
792    }
793
794    /* If the command is "quit", break the loop */
795    if (!strncmp (cmd, "quit\n", sizeof ("quit\n") - 1))
796    {
797      break;
798    }
799
800    jerry_value_t ret_val;
801
802    /* Evaluate entered command */
803    ret_val = jerry_eval ((const jerry_char_t *) cmd,
804                          len,
805                          JERRY_PARSE_NO_OPTS);
806
807    /* Print out the value */
808    print_value (ret_val);
809
810    jerry_release_value (ret_val);
811  }
812
813  /* Cleanup engine */
814  jerry_cleanup ();
815
816  return 0;
817}
818```
819
820To compile it one can use the following command:
821
822(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call.
823
824```sh
825$ gcc api-example-8-shell.c -o api-example-8-shell $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm)
826```
827
828The application reads lines from standard input and evaluates them, one after another. To try out run:
829
830```
831$ ./api-example-8-shell
832```
833
834
835## Example 9. Creating JS object in global context
836
837In this example (`api-example-9.c`) an object with a native function is added to the global object.
838
839[doctest]: # ()
840
841```c
842#include "jerryscript.h"
843#include "jerryscript-ext/handler.h"
844
845struct my_struct
846{
847  const char *msg;
848} my_struct;
849
850/**
851 * Get a string from a native object
852 */
853static jerry_value_t
854get_msg_handler (const jerry_value_t func_value, /**< function object */
855                 const jerry_value_t this_value, /**< this arg */
856                 const jerry_value_t *args_p, /**< function arguments */
857                 const jerry_length_t args_cnt) /**< number of function arguments */
858{
859  return jerry_create_string ((const jerry_char_t *) my_struct.msg);
860} /* get_msg_handler */
861
862int
863main (void)
864{
865  /* Initialize engine */
866  jerry_init (JERRY_INIT_EMPTY);
867
868  /* Register 'print' function from the extensions */
869  jerryx_handler_register_global ((const jerry_char_t *) "print",
870                                  jerryx_handler_print);
871
872  /* Do something with the native object */
873  my_struct.msg = "Hello, World!";
874
875  /* Create an empty JS object */
876  jerry_value_t object = jerry_create_object ();
877
878  /* Create a JS function object and wrap into a jerry value */
879  jerry_value_t func_obj = jerry_create_external_function (get_msg_handler);
880
881  /* Set the native function as a property of the empty JS object */
882  jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "myFunc");
883  jerry_release_value (jerry_set_property (object, prop_name, func_obj));
884  jerry_release_value (prop_name);
885  jerry_release_value (func_obj);
886
887  /* Wrap the JS object (not empty anymore) into a jerry api value */
888  jerry_value_t global_object = jerry_get_global_object ();
889
890  /* Add the JS object to the global context */
891  prop_name = jerry_create_string ((const jerry_char_t *) "MyObject");
892  jerry_release_value (jerry_set_property (global_object, prop_name, object));
893  jerry_release_value (prop_name);
894  jerry_release_value (object);
895  jerry_release_value (global_object);
896
897  /* Now we have a "builtin" object called MyObject with a function called myFunc()
898   *
899   * Equivalent JS code:
900   *                    var MyObject = { myFunc : function () { return "some string value"; } }
901   */
902  const jerry_char_t script[] = " \
903    var str = MyObject.myFunc (); \
904    print (str); \
905  ";
906
907  /* Evaluate script */
908  jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
909
910  /* Free JavaScript value, returned by eval */
911  jerry_release_value (eval_ret);
912
913  /* Cleanup engine */
914  jerry_cleanup ();
915
916  return 0;
917}
918```
919
920To compile it one can use the following command:
921
922(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call.
923
924```sh
925$ gcc api-example-9.c -o api-example-9 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm)
926```
927
928Execute the example with:
929
930```
931$ ./api-example-9
932```
933
934The application will generate the following output:
935
936```bash
937Hello, World
938```
939
940## Example 10. Extending JS Objects with native functions
941
942The example creates a JS Object with `jerry_eval`, then it is extended from C with a native function.
943In addition this native function shows how to get a property value from the object and how to manipulate it.
944
945
946Use the following code for `api-example-10.c`:
947
948[doctest]: # ()
949
950```c
951#include "jerryscript.h"
952#include "jerryscript-ext/handler.h"
953
954/**
955 * Add param to 'this.x'
956 */
957static jerry_value_t
958add_handler (const jerry_value_t func_value, /**< function object */
959             const jerry_value_t this_val, /**< this arg */
960             const jerry_value_t args_p[], /**< function arguments */
961             const jerry_length_t args_cnt) /**< number of function arguments */
962{
963  /* The the 'this_val' is the 'MyObject' from the JS code below */
964  /* Note: that the argument count check is ignored for the example's case */
965
966  /* Get 'this.x' */
967  jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "x");
968  jerry_value_t x_val = jerry_get_property (this_val, prop_name);
969
970  if (!jerry_value_is_error (x_val))
971  {
972    /* Convert Jerry API values to double */
973    double x = jerry_get_number_value (x_val);
974    double d = jerry_get_number_value (args_p[0]);
975
976    /* Add the parameter to 'x' */
977    jerry_value_t res_val = jerry_create_number (x + d);
978
979    /* Set the new value of 'this.x' */
980    jerry_release_value (jerry_set_property (this_val, prop_name, res_val));
981    jerry_release_value (res_val);
982  }
983
984  jerry_release_value (x_val);
985  jerry_release_value (prop_name);
986
987  return jerry_create_undefined ();
988} /* add_handler */
989
990int
991main (void)
992{
993  /* Initialize engine */
994  jerry_init (JERRY_INIT_EMPTY);
995
996  /* Register 'print' function from the extensions */
997  jerryx_handler_register_global ((const jerry_char_t *) "print",
998                                  jerryx_handler_print);
999
1000  /* Create a JS object */
1001  const jerry_char_t my_js_object[] = " \
1002    MyObject = \
1003    { x : 12, \
1004      y : 'Value of x is ', \
1005      foo: function () \
1006      { \
1007        return this.y + this.x; \
1008      } \
1009    } \
1010  ";
1011
1012  jerry_value_t my_js_obj_val;
1013
1014  /* Evaluate script */
1015  my_js_obj_val = jerry_eval (my_js_object,
1016                              sizeof (my_js_object) - 1,
1017                              JERRY_PARSE_NO_OPTS);
1018
1019  /* Create a JS function object and wrap into a jerry value */
1020  jerry_value_t add_func_obj = jerry_create_external_function (add_handler);
1021
1022  /* Set the native function as a property of previously created MyObject */
1023  jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "add2x");
1024  jerry_release_value (jerry_set_property (my_js_obj_val, prop_name, add_func_obj));
1025  jerry_release_value (add_func_obj);
1026  jerry_release_value (prop_name);
1027
1028  /* Free JavaScript value, returned by eval (my_js_object) */
1029  jerry_release_value (my_js_obj_val);
1030
1031  const jerry_char_t script[] = " \
1032    var str = MyObject.foo (); \
1033    print (str); \
1034    MyObject.add2x (5); \
1035    print (MyObject.foo ()); \
1036  ";
1037
1038  /* Evaluate script */
1039  jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
1040
1041  /* Free JavaScript value, returned by eval */
1042  jerry_release_value (eval_ret);
1043
1044  /* Cleanup engine */
1045  jerry_cleanup ();
1046
1047  return 0;
1048}
1049```
1050
1051To compile it one can use the following command:
1052
1053(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call.
1054
1055```sh
1056$ gcc api-example-10.c -o api-example-10 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm)
1057```
1058
1059Execute the example with:
1060
1061```
1062$ ./api-example-10
1063```
1064
1065```bash
1066Value of x is 12
1067Value of x is 17
1068```
1069
1070## Example 11. Changing the seed of pseudorandom generated numbers
1071
1072If you want to change the seed of `Math.random()` generated numbers, you have to initialize the seed value with `srand`.
1073A recommended method is using `jerry_port_get_current_time()` or something based on a constantly changing value, therefore every run produces truly random numbers.
1074
1075[doctest]: # ()
1076
1077```c
1078#include <stdlib.h>
1079#include "jerryscript.h"
1080#include "jerryscript-port.h"
1081#include "jerryscript-ext/handler.h"
1082
1083int
1084main (void)
1085{
1086  /* Initialize srand value */
1087  union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
1088  srand (now.u);
1089
1090  /* Generate a random number, and print it */
1091  const jerry_char_t script[] = "var a = Math.random (); print(a)";
1092
1093  /* Initialize the engine */
1094  jerry_init (JERRY_INIT_EMPTY);
1095
1096  /* Register the print function */
1097  jerryx_handler_register_global ((const jerry_char_t *) "print",
1098                                  jerryx_handler_print);
1099
1100  /* Evaluate the script */
1101  jerry_value_t eval_ret = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
1102
1103  /* Free the JavaScript value returned by eval */
1104  jerry_release_value (eval_ret);
1105
1106  /* Cleanup the engine */
1107  jerry_cleanup ();
1108
1109  return 0;
1110}
1111```
1112
1113## Further steps
1114
1115For 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/).
1116