# Reference ## Termination It is questionable whether a library should be able to terminate an application. Any API function can signal an error (ex.: cannot allocate memory), so the engine use the termination approach with this port function. ```c /** * Signal the port that jerry experienced a fatal failure from which it cannot * recover. * * @param code gives the cause of the error. * * Note: * Jerry expects the function not to return. * * Example: a libc-based port may implement this with exit() or abort(), or both. */ void jerry_port_fatal (jerry_fatal_code_t code); ``` Error codes ```c typedef enum { ERR_OUT_OF_MEMORY = 10, ERR_REF_COUNT_LIMIT = 12, ERR_DISABLED_BYTE_CODE = 13, ERR_FAILED_INTERNAL_ASSERTION = 120 } jerry_fatal_code_t; ``` ## I/O These are the only I/O functions jerry calls. ```c /** * Jerry log levels. The levels are in severity order * where the most serious levels come first. */ typedef enum { JERRY_LOG_LEVEL_ERROR, /**< the engine will terminate after the message is printed */ JERRY_LOG_LEVEL_WARNING, /**< a request is aborted, but the engine continues its operation */ JERRY_LOG_LEVEL_DEBUG, /**< debug messages from the engine, low volume */ JERRY_LOG_LEVEL_TRACE /**< detailed info about engine internals, potentially high volume */ } jerry_log_level_t; /** * Display or log a debug/error message, and sends it to the debugger client as well. * The function should implement a printf-like interface, where the first argument * specifies the log level and the second argument specifies a format string on how * to stringify the rest of the parameter list. * * This function is only called with messages coming from the jerry engine as * the result of some abnormal operation or describing its internal operations * (e.g., data structure dumps or tracing info). * * It should be the port that decides whether error and debug messages are logged to * the console, or saved to a database or to a file. * * Example: a libc-based port may implement this with vfprintf(stderr) or * vfprintf(logfile), or both, depending on log level. * * Note: * This port function is called by jerry-core when JERRY_LOGGING is * enabled. It is also common practice though to use this function in * application code. */ void jerry_port_log (jerry_log_level_t level, const char *fmt, ...); ``` The `jerry_port_print_char` is currenlty not used by the jerry-core directly. However, it provides a port specifc way for `jerry-ext` components to print information. ```c /** * Print a character to stdout. */ void jerry_port_print_char (char c); ``` ### ES2015 Module system The port API provides functions that can be used by the module system to open and close source files, and normalize file paths. The `jerry_port_get_native_module` port function can be used to provide native modules to the engine. This function will be called when an import/export statement is encountered with an unknown module specifier, which embedders can use to supply native module objects based on the module name argument. ```c /** * Opens file with the given path and reads its source. * @return the source of the file */ uint8_t * jerry_port_read_source (const char *file_name_p, /**< file name */ size_t *out_size_p) /**< [out] read bytes */ { // open file from given path // return its source } /* jerry_port_read_source */ /** * Release the previously opened file's content. */ void jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */ { free (buffer_p); } /* jerry_port_release_source */ /** * Normalize a file path * * @return length of the path written to the output buffer */ size_t jerry_port_normalize_path (const char *in_path_p, /**< input file path */ char *out_buf_p, /**< output buffer */ size_t out_buf_size, /**< size of output buffer */ char *base_file_p) /**< base file path */ { // normalize in_path_p by expanding relative paths etc. // if base_file_p is not NULL, in_path_p is relative to that file // write to out_buf_p the normalized path // return length of written path } /* jerry_port_normalize_path */ /** * Get the module object of a native module. * * Note: * This port function is called by jerry-core when ES2015_MODULE_SYSTEM * is enabled. * * @param name String value of the module specifier. * * @return Undefined, if 'name' is not a native module * jerry_value_t containing the module object, otherwise */ jerry_value_t jerry_port_get_native_module (jerry_value_t name) /**< module specifier */ { (void) name; return jerry_create_undefined (); } ``` ## Date ```c /** * Get local time zone adjustment, in milliseconds, for the given timestamp. * The timestamp can be specified in either UTC or local time, depending on * the value of is_utc. Adding the value returned from this function to * a timestamp in UTC time should result in local time for the current time * zone, and subtracting it from a timestamp in local time should result in * UTC time. * * Ideally, this function should satisfy the stipulations applied to LocalTZA * in section 20.3.1.7 of the ECMAScript version 9.0 spec. * * See Also: * ECMA-262 v9, 20.3.1.7 * * Note: * This port function is called by jerry-core when * JERRY_BUILTIN_DATE is set to 1. Otherwise this function is * not used. * * @param unix_ms The unix timestamp we want an offset for, given in * millisecond precision (could be now, in the future, * or in the past). As with all unix timestamps, 0 refers to * 1970-01-01, a day is exactly 86 400 000 milliseconds, and * leap seconds cause the same second to occur twice. * @param is_utc Is the given timestamp in UTC time? If false, it is in local * time. * * @return milliseconds between local time and UTC for the given timestamp, * if available *. 0 if not available / we are in UTC. */ double jerry_port_get_local_time_zone_adjustment (double unix_ms, bool is_utc); /** * Get system time * * Note: * This port function is called by jerry-core when * JERRY_BUILTIN_DATE is set to 1. It is also common practice * in application code to use this function for the initialization of the * random number generator. * * @return milliseconds since Unix epoch */ double jerry_port_get_current_time (void); ``` ## External context Allow user to provide external buffer for isolated engine contexts, so that user can configure the heap size at runtime and run multiple JS applications simultaneously. ```c /** * Get the current context of the engine. Each port should provide its own * implementation of this interface. * * Note: * This port function is called by jerry-core when * JERRY_EXTERNAL_CONTEXT is enabled. Otherwise this function is not * used. * * @return the pointer to the engine context. */ struct jerry_context_t *jerry_port_get_current_context (void); ``` ## Sleep ```c /** * Makes the process sleep for a given time. * * Note: * This port function is called by jerry-core when JERRY_DEBUGGER is set to 1. * Otherwise this function is not used. * * @param sleep_time milliseconds to sleep. */ void jerry_port_sleep (uint32_t sleep_time); ``` # How to port JerryScript This section describes a basic port implementation which was created for Unix based systems. ## Termination ```c #include #include "jerryscript-port.h" /** * Default implementation of jerry_port_fatal. */ void jerry_port_fatal (jerry_fatal_code_t code) { exit (code); } /* jerry_port_fatal */ ``` ## I/O ```c #include #include "jerryscript-port.h" /** * Provide log message implementation for the engine. * * Note: * This example ignores the log level. */ void jerry_port_log (jerry_log_level_t level, /**< log level */ const char *format, /**< format string */ ...) /**< parameters */ { va_list args; va_start (args, format); vfprintf (stderr, format, args); va_end (args); } /* jerry_port_log */ ``` ```c /** * Print a character to stdout with putchar. */ void jerry_port_print_char (char c) { putchar (c); } /* jerr_port_print_char */ ``` ## Date ```c #include #include #include "jerryscript-port.h" /** * Default implementation of jerry_port_get_local_time_zone_adjustment. */ double jerry_port_get_local_time_zone_adjustment (double unix_ms, /**< ms since unix epoch */ bool is_utc) /**< is the time above in UTC? */ { struct tm tm; time_t now = (time_t) (unix_ms / 1000); localtime_r (&now, &tm); if (!is_utc) { now -= tm.tm_gmtoff; localtime_r (&now, &tm); } return ((double) tm.tm_gmtoff) * 1000; } /* jerry_port_get_local_time_zone_adjustment */ /** * Default implementation of jerry_port_get_current_time. */ double jerry_port_get_current_time (void) { struct timeval tv; if (gettimeofday (&tv, NULL) != 0) { return 0; } return ((double) tv.tv_sec) * 1000.0 + ((double) tv.tv_usec) / 1000.0; } /* jerry_port_get_current_time */ ``` ## External context ```c #include "jerryscript-port.h" #include "jerryscript-port-default.h" /** * Pointer to the current context. * Note that it is a global variable, and is not a thread safe implementation. */ static jerry_context_t *current_context_p = NULL; /** * Set the current_context_p as the passed pointer. */ void jerry_port_default_set_current_context (jerry_context_t *context_p) /**< points to the created context */ { current_context_p = context_p; } /* jerry_port_default_set_current_context */ /** * Get the current context. * * @return the pointer to the current context */ jerry_context_t * jerry_port_get_current_context (void) { return current_context_p; } /* jerry_port_get_current_context */ ``` ## Sleep ```c #include "jerryscript-port.h" #include "jerryscript-port-default.h" #ifdef HAVE_TIME_H #include #elif defined (HAVE_UNISTD_H) #include #endif /* HAVE_TIME_H */ #if defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) void jerry_port_sleep (uint32_t sleep_time) { #ifdef HAVE_TIME_H nanosleep (&(const struct timespec) { (time_t) sleep_time / 1000, ((long int) sleep_time % 1000) * 1000000L /* Seconds, nanoseconds */ } , NULL); #elif defined (HAVE_UNISTD_H) usleep ((useconds_t) sleep_time * 1000); #endif /* HAVE_TIME_H */ (void) sleep_time; } /* jerry_port_sleep */ #endif /* defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) */ ```