Notable changes:
- Updated and the port API interface, new functions have been added
and some have been changed. The port library is now cleaned up to
not have any dependency on jerry-core, as it should be. The port library
is now strictly a collection of functions that implement
embedding/platform specific behavior.
- The default port implementation has been split for windows and unix.
Implemented port functions have been categorized and reorganized,
and marked with attribute((weak)) for better reusability.
- External context allocation has been moved to the port API instead
of a core API callback. The iterface has also been extended with a
function to free the allocated context. When external context is
enabled, jerry_init now automatically calls the port implementation
to allocate the context and jerry_cleanup automatically calls the port
to free the context.
- jerry_port_log has been changed to no longer require formatting to
be implemented by the port. The reason beind this is that it was vague what
format specifiers were used by the engine, and in what manner. The port
function now takes a zero-terminated string, and should only implement
how the string should be logged.
- Logging and log message formatting is now handled by the core jerry library
where it can be implemented as necessary. Logging can be done through a new
core API function, which uses the port to output the final log message.
- Log level has been moved into jerry-core, and an API function has
been added to set the log level. It should be the library that
filters log messages based on the requested log level, instead of
logging everything and requiring the user to do so.
- Module resolving logic has been moved into jerry-core. There's no
reason to have it in the port library and requiring embedders to
duplicate the code. It also added an unnecessary dependency on
jerry-core to the port. Platform specific behavior is still used through
the port API, like resolving module specifiers, and reading source file
contents. If necessary, the resolving logic can still be overridden as
previously.
- The jerry-ext library has also been cleaned up, and many utility
functions have been added that previously were implemented in
jerry-main. This allows easier reusability for some common operations,
like printing unhandled exceptions or providing a repl console.
- Debugger interaction with logged/printed messages has been fixed, so
that it's no longer the port implementations responsibility to send
the output to the debugger, as the port should have no notion of what a
debugger is. The printing and logging functions will now pass the
result message to the debugger, if connected.
- Cleaned up TZA handling in the date port implementation, and simplified
the API function prototype.
- Moved property access helper functions that use ASCII strings as
keys from jerry-ext to the core API.
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
29 KiB
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:
$ 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):
$ export PKG_CONFIG_PATH=$(pwd)/example_install/lib/pkgconfig/
Test if the pkg-config works for JerryScript:
$ pkg-config --cflags --libs libjerry-core libjerry-port libjerry-ext libjerry-math
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_value_free method.
To make sure that the code parsing and execution was ok, the jerry_value_is_exception
method is used to check for any errors.
Use the following code for the api-example-2.c file:
#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_exception (eval_ret);
/* Parsed source code must be freed */
jerry_value_free (eval_ret);
/* Cleanup engine */
jerry_cleanup ();
return (run_ok ? 0 : 1);
}
To compile it one can use the following command:
$ gcc api-example-2.c -o api-example-2 $(pkg-config --cflags --libs libjerry-core libjerry-port libjerry-math)
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:
#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 (script, sizeof (script) - 1, NULL);
/* Check if there is any JS code parse error */
if (!jerry_value_is_exception (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_exception (ret_value);
/* Returned value must be freed */
jerry_value_free (ret_value);
}
/* Parsed source code must be freed */
jerry_value_free (parsed_code);
/* Cleanup engine */
jerry_cleanup ();
return (run_ok ? 0 : 1);
}
To compile it one can use the following command:
$ gcc api-example-3.c -o api-example-3 $(pkg-config --cflags --libs libjerry-core libjerry-port libjerry-math)
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_current_realmjerry_string_szjerry_object_setjerry_function_external
The api-example-4.c file should contain the following code:
#include <stdio.h>
#include "jerryscript.h"
static jerry_value_t
print_handler (const jerry_call_info_t *call_info_p,
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_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_current_realm ();
/* Create a "print" JS string */
jerry_value_t property_name_print = jerry_string_sz ("print");
/* Create a function from a native C method (this function will be called from JS) */
jerry_value_t property_value_func = jerry_function_external (print_handler);
/* Add the "print" property with the function value to the "global" object */
jerry_value_t set_result = jerry_object_set (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_exception (set_result)) {
printf ("Failed to add the 'print' property\n");
}
/* Release all jerry_value_t-s */
jerry_value_free (set_result);
jerry_value_free (property_value_func);
jerry_value_free (property_name_print);
jerry_value_free (global_object);
}
/* Setup Global scope code */
jerry_value_t parsed_code = jerry_parse (script, script_size, NULL);
if (!jerry_value_is_exception (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_value_free (ret_value);
}
/* Parsed source code must be freed */
jerry_value_free (parsed_code);
/* Cleanup engine */
jerry_cleanup ();
return 0;
}
To compile it one can use the following command:
$ gcc api-example-4.c -o api-example-4 $(pkg-config --cflags --libs libjerry-core libjerry-port libjerry-math)
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_stringjerry_string_to_buffer
The api-example-5.c file should contain the following code:
#include <stdio.h>
#include "jerryscript.h"
static jerry_value_t
print_handler (const jerry_call_info_t *call_info_p,
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_buffer (string_value, JERRY_ENCODING_UTF8, buffer, sizeof (buffer) - 1);
buffer[copied_bytes] = '\0';
/* Release the "toString" result */
jerry_value_free (string_value);
printf ("%s\n", (const char *)buffer);
}
/* Return an "undefined" value to the JavaScript engine */
return jerry_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_current_realm ();
/* Create a "print" JS string */
jerry_value_t property_name_print = jerry_string_sz ("print");
/* Create a function from a native C method (this function will be called from JS) */
jerry_value_t property_value_func = jerry_function_external (print_handler);
/* Add the "print" property with the function value to the "global" object */
jerry_value_t set_result = jerry_object_set (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_exception (set_result)) {
printf ("Failed to add the 'print' property\n");
}
/* Release all jerry_value_t-s */
jerry_value_free (set_result);
jerry_value_free (property_value_func);
jerry_value_free (property_name_print);
jerry_value_free (global_object);
}
/* Setup Global scope code */
jerry_value_t parsed_code = jerry_parse (script, script_size, NULL);
if (!jerry_value_is_exception (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_value_free (ret_value);
}
/* Parsed source code must be freed */
jerry_value_free (parsed_code);
/* Cleanup engine */
jerry_cleanup ();
return 0;
}
To compile it one can use the following command:
$ gcc api-example-5.c -o api-example-5 $(pkg-config --cflags --libs libjerry-core libjerry-port libjerry-math)
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_register_globaljerryx_handler_print
In further examples this "print" handler will be used.
#include "jerryscript.h"
#include "jerryscript-ext/handlers.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_register_global ("print", jerryx_handler_print);
/* Setup Global scope code */
jerry_value_t parsed_code = jerry_parse (script, script_size, NULL);
if (!jerry_value_is_exception (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_value_free (ret_value);
}
/* Parsed source code must be freed */
jerry_value_free (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 entry for the pkg-config call.
$ gcc api-example-6.c -o api-example-6 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port libjerry-math)
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:
#include <stdio.h>
#include "jerryscript.h"
#include "jerryscript-ext/handlers.h"
#include "jerryscript-ext/properties.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_register_global ("print", jerryx_handler_print);
/* Getting pointer to the Global object */
jerry_value_t global_object = jerry_current_realm ();
/* Constructing strings */
jerry_value_t prop_name = jerry_string_sz ("my_var");
jerry_value_t prop_value = jerry_string_sz ("Hello from C!");
/* Setting the string value as a property of the Global object */
jerry_value_t set_result = jerry_object_set (global_object, prop_name, prop_value);
/* The 'set_result' should be checked if there was any error */
if (jerry_value_is_exception (set_result)) {
printf ("Failed to add the 'my_var' property\n");
}
jerry_value_free (set_result);
/* Releasing string values, as it is no longer necessary outside of engine */
jerry_value_free (prop_name);
jerry_value_free (prop_value);
/* Releasing the Global object */
jerry_value_free (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_value_free (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 entry for the pkg-config call.
$ gcc api-example-7.c -o api-example-7 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port libjerry-math)
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_exception method as not all API methods
can process error values. To extract the value from the "error" the API method jerry_exception_value should be used.
If an error object is created via API method (for example with jerry_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
Errorobjects (available from the global object or from API). For example in JS such object be created with the following code example:
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:
throw "message";
To check what type a given jerry_value_t is the jerry_value_is_* methods or the jerry_value_type could be used.
For example the following code snippet could print out a few types (not all types are checked):
#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_exception (jsvalue))
{
printf ("Error value detected: ");
value = jerry_exception_value (jsvalue, false);
}
else
{
value = jerry_value_copy (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_value_is_true (value))
{
printf ("true");
}
else
{
printf ("false");
}
}
/* Float value */
else if (jerry_value_is_number (value))
{
printf ("number: %lf", jerry_value_as_number (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_string_size (value, JERRY_ENCODING_CESU8);
if (req_sz <= 255)
{
jerry_string_to_buffer (value, JERRY_ENCODING_CESU8, 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_value_free (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:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jerryscript.h"
#include "jerryscript-ext/handlers.h"
#include "jerryscript-ext/properties.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_exception (jsvalue))
{
printf ("Error value detected: ");
value = jerry_exception_value (jsvalue, false);
}
else
{
value = jerry_value_copy (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_value_is_true (value))
{
printf ("true");
}
else
{
printf ("false");
}
}
/* Float value */
else if (jerry_value_is_number (value))
{
printf ("number: %lf", jerry_value_as_number (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_string_size (value, JERRY_ENCODING_CESU8);
if (req_sz <= 255)
{
jerry_string_to_buffer (value, JERRY_ENCODING_CESU8, 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_value_free (value);
}
int
main (void)
{
bool is_done = false;
/* Initialize engine */
jerry_init (JERRY_INIT_EMPTY);
/* Register 'print' function from the extensions */
jerryx_register_global ("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_value_free (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 entry for the pkg-config call.
$ gcc api-example-8-shell.c -o api-example-8-shell $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port libjerry-math)
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.
#include "jerryscript.h"
#include "jerryscript-ext/handlers.h"
#include "jerryscript-ext/properties.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_call_info_t *call_info_p, /**< call information */
const jerry_value_t *args_p, /**< function arguments */
const jerry_length_t args_cnt) /**< number of function arguments */
{
return jerry_string_sz (my_struct.msg);
} /* get_msg_handler */
int
main (void)
{
/* Initialize engine */
jerry_init (JERRY_INIT_EMPTY);
/* Register 'print' function from the extensions */
jerryx_register_global ("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_object ();
/* Create a JS function object and wrap into a jerry value */
jerry_value_t func_obj = jerry_function_external (get_msg_handler);
/* Set the native function as a property of the empty JS object */
jerry_value_t prop_name = jerry_string_sz ("myFunc");
jerry_value_free (jerry_object_set (object, prop_name, func_obj));
jerry_value_free (prop_name);
jerry_value_free (func_obj);
/* Wrap the JS object (not empty anymore) into a jerry api value */
jerry_value_t global_object = jerry_current_realm ();
/* Add the JS object to the global context */
prop_name = jerry_string_sz ("MyObject");
jerry_value_free (jerry_object_set (global_object, prop_name, object));
jerry_value_free (prop_name);
jerry_value_free (object);
jerry_value_free (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_value_free (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 entry for the pkg-config call.
$ gcc api-example-9.c -o api-example-9 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port libjerry-math)
Execute the example with:
$ ./api-example-9
The application will generate the following output:
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:
#include "jerryscript.h"
#include "jerryscript-ext/handlers.h"
#include "jerryscript-ext/properties.h"
/**
* Add param to 'this.x'
*/
static jerry_value_t
add_handler (const jerry_call_info_t *call_info_p, /**< call information */
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_string_sz ("x");
jerry_value_t x_val = jerry_object_get (call_info_p->this_value, prop_name);
if (!jerry_value_is_exception (x_val))
{
/* Convert Jerry API values to double */
double x = jerry_value_as_number (x_val);
double d = jerry_value_as_number (args_p[0]);
/* Add the parameter to 'x' */
jerry_value_t res_val = jerry_number (x + d);
/* Set the new value of 'this.x' */
jerry_value_free (jerry_object_set (call_info_p->this_value, prop_name, res_val));
jerry_value_free (res_val);
}
jerry_value_free (x_val);
jerry_value_free (prop_name);
return jerry_undefined ();
} /* add_handler */
int
main (void)
{
/* Initialize engine */
jerry_init (JERRY_INIT_EMPTY);
/* Register 'print' function from the extensions */
jerryx_register_global ("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_function_external (add_handler);
/* Set the native function as a property of previously created MyObject */
jerry_value_t prop_name = jerry_string_sz ("add2x");
jerry_value_free (jerry_object_set (my_js_obj_val, prop_name, add_func_obj));
jerry_value_free (add_func_obj);
jerry_value_free (prop_name);
/* Free JavaScript value, returned by eval (my_js_object) */
jerry_value_free (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_value_free (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 entry for the pkg-config call.
$ gcc api-example-10.c -o api-example-10 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port libjerry-math)
Execute the example with:
$ ./api-example-10
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_current_time() or something based on a constantly changing value, therefore every run produces truly random numbers.
#include <stdlib.h>
#include "jerryscript.h"
#include "jerryscript-port.h"
#include "jerryscript-ext/handlers.h"
#include "jerryscript-ext/properties.h"
int
main (void)
{
/* Initialize srand value */
union { double d; unsigned u; } now = { .d = jerry_port_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_register_global ("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_value_free (eval_ret);
/* Cleanup the engine */
jerry_cleanup ();
return 0;
}
Further steps
For further API description, please visit API Reference page on JerryScript home page.