diff --git a/01.GETTING-STARTED.md b/00.GETTING-STARTED.md similarity index 90% rename from 01.GETTING-STARTED.md rename to 00.GETTING-STARTED.md index daf87c042..9252a2443 100644 --- a/01.GETTING-STARTED.md +++ b/00.GETTING-STARTED.md @@ -67,7 +67,7 @@ python tools/build.py --cmake-param=CMAKE_PARAM python tools/build.py --profile=es5.1|es2015-subset|minimal ``` -See also the related [README.md](https://github.com/pando-project/jerryscript/blob/master/jerry-core/profiles/README.md). +See also the related [README.md](https://github.com/jerryscript-project/jerryscript/blob/master/jerry-core/profiles/README.md). **Use (compiler-default, external) libc** @@ -130,6 +130,15 @@ python tools/build.py --cpointer-32bit=on --mem-heap=1024 *Note*: The heap size will be allocated statically at compile time, when JerryScript memory allocator is used. +**To build with libfuzzer support** + +```bash +CC=clang python tools/build.py --libfuzzer=on --compile-flag=-fsanitize=address --lto=off +``` + +Check the documentation of libfuzzer to get the runtime settings of the created fuzzer +binary: https://llvm.org/docs/LibFuzzer.html. + **To get a list of all the available buildoptions for Linux** ```bash diff --git a/01.CONFIGURATION.md b/01.CONFIGURATION.md new file mode 100644 index 000000000..b19286c79 --- /dev/null +++ b/01.CONFIGURATION.md @@ -0,0 +1,299 @@ +--- +layout: page +title: Configuration +category: navbar +permalink: /configuration/ +--- + +* toc +{:toc} + +# Configuration + +JerryScript provides a large number of configuration options which can be used to enable or disable specific features, allowing users to fine tune the engine to best suit their needs. +A configuration option's value can be changed either by providing specific C preprocessor definitions, by adding CMake defininitions, or by using the arguments of the `tools/build.py` script. +This document lists the available configuration options, shows the configuration name for C, CMake, and python, and provides a brief description that explains the effect of the options. + + +### All-in-one build + +Enables the All-in-one build process, which aggregates the contents of each source file, and uses this combined file to compile the JerryScript library. +This process can provide comparable results to link time optimization, and can be useful when LTO is not available otherwise. + +| Options | | +|---------|----------------------------------------------| +| C: | `` | +| CMake: | `-DENABLE_ALL_IN_ONE=ON/OFF` | +| Python: | `--all-in-one=ON/OFF` | + +### Jerry debugger + +Enables debugger support in the engine, which can be used to debug running JavaScript code. For more information on using the debugger see [Debugger](07.DEBUGGER.md). +The debugger is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_DEBUGGER=0/1` | +| CMake: | `-DJERRY_DEBUGGER=ON/OFF` | +| Python: | `--jerry-debugger=ON/OFF` | + +### Line information + +By default, all source code information is discarded after parsing is complete. This option can be used to augment the created bytecode to provide line information during runtime, +that can be used by the debugger to identify the currently executed source context. See [Debugger](07.DEBUGGER.md). + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_LINE_INFO=0/1` | +| CMake: | `-DJERRY_LINE_INFO=ON/OFF` | +| Python: | `--line-info=ON/OFF` | + +### Profiles + +This option can be used to enable/disable available JavaScript language features by providing profile files. Profile files contain a list of C definitions that configure each individual feature. +The `path` value for CMake and Python arguments should be a file path to the profile file, or one of `es2015-subset`, `es5.1`, or `minimal`, which are the pre-defined profiles. +To see how a profile file should be created, or what configuration options are available in C, see the profile [README](https://github.com/jerryscript-project/jerryscript/blob/master/jerry-core/profiles/README.md). + +| Options | | +|---------|----------------------------------------------| +| C: | `` | +| CMake: | `-DJERRY_PROFILE="path"` | +| Python: | `--profile="path"` | + +### External context + +Enables external context support in the engine. By default, JerryScript uses a statically allocated context to store the current state of the engine internals. +When this option is enabled, an externally allocated memory region can be provided through the port API to the engine, to be used as the context. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_EXTERNAL_CONTEXT=0/1` | +| CMake: | `-DJERRY_EXTERNAL_CONTEXT=ON/OFF` | +| Python: | `--external-context=ON/OFF` | + +### Snapshot execution + +This option can be used to enable snapshot execution in the engine. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_SNAPSHOT_EXEC=0/1` | +| CMake: | `-DJERRY_SNAPSHOT_EXEC=ON/OFF` | +| Python: | `--snapshot-exec=ON/OFF` | + +### Snapshot saving + +This option can be used to enable snapshot saving in the engine. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_SNAPSHOT_SAVE=0/1` | +| CMake: | `-DJERRY_SNAPSHOT_SAVE=ON/OFF` | +| Python: | `--snapshot-save=ON/OFF` | + +### Jerry parser + +This option can be used to enable or disable the parser. When the parser is disabled all features that depend on source parsing are unavailable (eg. `jerry_parse`, `eval`, Function constructor). +This option can be useful in combination with the snapshot feature. The parser is enabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_PARSER=0/1` | +| CMake: | `-DJERRY_PARSER=ON/OFF` | +| Python: | `--js-parser=ON/OFF` | + +### Dump bytecode + +This option can be used to display created bytecode in a human readable format. See [Internals](04.INTERNALS.md#byte-code) for more details. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_PARSER_DUMP_BYTE_CODE=0/1` | +| CMake: | `-DJERRY_PARSER_DUMP_BYTE_CODE=ON/OFF` | +| Python: | `--show-opcodes=ON/OFF` | + +### Dump RegExp bytecode + +This option can be used to display created RegExp bytecode in a human readable format. The RegExp bytecode is different from the bytecode used by the virtual machine. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_REGEXP_DUMP_BYTE_CODE=0/1` | +| CMake: | `-DJERRY_REGEXP_DUMP_BYTE_CODE=ON/OFF` | +| Python: | `--show-regexp-opcodes=ON/OFF` | + +### Strict RegExp + +This option can be used to enable strict RegExp mode. The standard RegExp syntax is a lot stricter than what is common in current JavaScript implementations. +When enabled, this flag disables all of the non-standard, quality-of-life RegExp features, that are implemented to provide compatibility with other commonly used engines. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_REGEXP_STRICT_MODE=0/1` | +| CMake: | `-DJERRY_REGEXP_STRICT_MODE=ON/OFF` | +| Python: | `--regexp-strict-mode=ON/OFF` | + +### Error messages + +Enables error messages for thrown Error objects. By default, error messages are omitted to reduce memory usage. +Enabling this feature provides detailed error messages where available, like line information for Syntax errors, variable names for Reference errors, Type/Range error messages for built-in routines, etc. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_ERROR_MESSAGES=0/1` | +| CMake: | `--DJERRY_ERROR_MESSAGES=ON/OFF` | +| Python: | `--error-messages=ON/OFF` | + +### Logging + +This option can be used to enable log messages during runtime. When enabled the engine will use the `jerry_port_log` port API function to print relevant log messages. +This feature is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_LOGGING=0/1` | +| CMake: | `-DJERRY_LOGGING=ON/OFF` | +| Python: | `--logging=ON/OFF` | + +### LCache + +This option enables the LCache, allowing faster access to object properties. The LCache usases a statically allocated hash-map, which increases memory consumption. +See [Internals](04.INTERNALS.md#lcache) for further details. +This option is enabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_LCACHE=0/1` | +| CMake: | `` | +| Python: | `` | + +### Property hashmaps + +This option enables the creation of hashmaps for object properties, which allows faster property access, at the cost of increased memory consumption. +See [Internals](04.INTERNALS.md#property-hashmap) for further details. +This option is enabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_PROPRETY_HASHMAP=0/1` | +| CMake: | `` | +| Python: | `` | + +### Memory statistics + +This option can be used to provide memory usage statistics either upon engine termination, or during runtime using the `jerry_get_memory_stats` jerry API function. +The feature can create a significant performance overhead, and should only be used for measurement purposes. This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_MEM_STATS=0/1` | +| CMake: | `-DJERRY_MEM_STATS=ON/OFF` | +| Python: | `--mem-stats=ON/OFF` | + +### Heap size + +This option can be used to adjust the size of the internal heap, represented in kilobytes. The provided value should be an integer. Values larger than 512 require 32-bit compressed pointers to be enabled. +The default value is 512. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_GLOBAL_HEAP_SIZE=(int)` | +| CMake: | `--DJERRY_GLOBAL_HEAP_SIZE=(int)` | +| Python: | `--heap-size=(int)` | + +### Stack limit + +This option can be used to cap the stack usage of the engine, and prevent stack overflows due to recursion. The provided value should be an integer, which represents the allowed stack usage in kilobytes. +The default value is 0 (unlimited). + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_STACK_LIMIT=(int)` | +| CMake: | `-DJERRY_STACK_LIMIT=(int)` | +| Python: | `--stack-limit=(int)` | + +### 32-bit compressed pointers + +Enables 32-bit pointers instead of the default 16-bit compressed pointers. This allows the engine to use a much larger heap, but also comes with slightly increased memory usage, as objects can't be packed as tightly. +This option must be enabled when using the system allocator. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_CPOINTER_32_BIT=0/1` | +| CMake: | `-DJERRY_CPOINTER_32_BIT=ON/OFF` | +| Python: | `--cpointer-32bit=ON/OFF` | + +### System allocator + +This option enables the use of malloc/free instead of the internal JerryScript allocator. This feature requires 32-bit compressed pointers, and is unsupported on 64-bit architectures. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_SYSTEM_ALLOCATOR=0/1` | +| CMake: | `-DJERRY_SYSTEM_ALLOCATOR=ON/OFF` | +| Python: | `--system-allocator=ON/OFF` | + +### Valgrind support + +This option enables valgrind support for the internal allocator. When enabled, valgrind will be able to properly identify allocated memory regions, and report leaks or out-of-bounds memory accesses. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_VALGRIND=0/1` | +| CMake: | `-DJERRY_VALGRIND=ON/OFF` | +| Python: | `--valgrind=ON/OFF` | + +### Memory stress test + +This option can be used to stress test memory management, by running garbage collection before every allocation attempt. +This option is disabled by default. + +| Options | | +|---------|----------------------------------------------| +| C: | `-DJERRY_MEM_GC_BEFORE_EACH_ALLOC=0/1` | +| CMake: | `-DJERRY_MEM_GC_BEFORE_EACH_ALLOC=ON/OFF` | +| Python: | `--mem-stress-test=ON/OFF` | + + +# Single source build mode + +There is a special mode to use/"build" JerryScript. That is generating a single C file which can be +included into projects quickly. To achive this the following command can be executed to create +a set of files into the `gen_src` directory (Note that the command is executed in the jerryscript root directory +but can be adapted to run outside of the project root dir): + +```sh +$ python tools/srcgenerator.py --output-dir gen_src --jerry-core --jerry-port-default --jerry-libm +``` + +The command creates the following files in the `gen_src` dir: + +* `jerryscript.c` +* `jerryscript.h` +* `jerryscript-config.h` +* `jerryscript-port-default.c` +* `jerryscript-port-default.h` +* `jerryscript-libm.c` +* `math.h` + +**Important**: the `jerryscript-config.h` contains the configurations mentioned above and +should be adapted to the required use-case. See the file contents for more details and for the +default configuration. (Note: This config file is created from the the `jerry-core/config.h` file.) + +These files can be directly compiled with an application using the JerryScript API. +For example with the following command: + +```sh +$ gcc -Wall -o demo_app demo_app.c gen_src/jerryscript.c gen_src/jerryscript-port-default.c jerryscript-libm.c -Igen_src/ +``` + +Please note that the headers must be available on the include path. + +In addition there is a `-DENABLE_ALL_IN_ONE_SOURCE=ON` CMake option to use this kind of sources during the build. diff --git a/02.API-REFERENCE.md b/02.API-REFERENCE.md index 9617e33c1..29a8ac0db 100644 --- a/02.API-REFERENCE.md +++ b/02.API-REFERENCE.md @@ -18,8 +18,10 @@ Enum that contains the following elements: - JERRY_INIT_SHOW_OPCODES - dump byte-code to log after parse - JERRY_INIT_SHOW_REGEXP_OPCODES - dump regexp byte-code to log after compilation - JERRY_INIT_MEM_STATS - dump memory statistics - - JERRY_INIT_MEM_STATS_SEPARATE - dump memory statistics and reset peak values after parse - - JERRY_INIT_DEBUGGER - deprecated, an unused placeholder now + - JERRY_INIT_MEM_STATS_SEPARATE - **deprecated**, dump memory statistics and reset peak values after parse + - JERRY_INIT_DEBUGGER - **deprecated**, an unused placeholder now + +*Changed in version 2.0*: JERRY_INIT_MEM_STATS_SEPARATE and JERRY_INIT_DEBUGGER are now deprecated and not used internally. ## jerry_type_t @@ -36,6 +38,8 @@ Enum that contains JerryScript API value types: - JERRY_TYPE_ERROR - error/abort type - JERRY_TYPE_SYMBOL - symbol type +*New in version 2.0*. + ## jerry_error_t Possible types of an error: @@ -51,6 +55,8 @@ Possible types of an error: There is also a special value `JERRY_ERROR_NONE` which is not an error type this value can only be returned by the [jerry_get_error_type](#jerry_get_error_type). +*Changed in version 2.0*: The `JERRY_ERROR_NONE` was added to be used by the [jerry_get_error_type](#jerry_get_error_type) method. + ## jerry_feature_t Possible compile time enabled feature types: @@ -75,6 +81,8 @@ Possible compile time enabled feature types: - JERRY_FEATURE_SYMBOL - symbol support - JERRY_FEATURE_DATAVIEW - DataView support +*New in version 2.0*. + ## jerry_regexp_flags_t RegExp object optional flags: @@ -85,6 +93,8 @@ RegExp object optional flags: multiple lines (i.e., match the beginning or end of each line (delimited by \n or \r), not only the very beginning or end of the whole input string) +*New in version 2.0*. + ## jerry_parse_opts_t Option bits for [jerry_parse](#jerry_parse) and @@ -93,18 +103,22 @@ Option bits for [jerry_parse](#jerry_parse) and - JERRY_PARSE_NO_OPTS - no options passed - JERRY_PARSE_STRICT_MODE - enable strict mode +*New in version 2.0*. + ## jerry_gc_mode_t Set garbage collection operational mode - - JERRY_GC_SEVERITY_LOW - free unused objects - - JERRY_GC_SEVERITY_HIGH - free as much memory as possible + - JERRY_GC_PRESSURE_LOW - free unused objects + - JERRY_GC_PRESSURE_HIGH - free as much memory as possible -The difference between `JERRY_GC_SEVERITY_LOW` and `JERRY_GC_SEVERITY_HIGH` +The difference between `JERRY_GC_PRESSURE_LOW` and `JERRY_GC_PRESSURE_HIGH` is that the former keeps memory allocated for performance improvements such as property hash tables for large objects. The latter frees all possible memory blocks but the performance may drop after the garbage collection. +*New in version 2.0*. + ## jerry_generate_snapshot_opts_t Flags for [jerry_generate_snapshot](#jerry_generate_snapshot) and @@ -133,6 +147,8 @@ strings are set by [jerry_register_magic_strings](#jerry_register_magic_strings) when the snapshot is generated and executed. Furthermore the `JERRY_SNAPSHOT_EXEC_COPY_DATA` option is not allowed. +*New in version 2.0*. + ## jerry_exec_snapshot_opts_t Flags for [jerry_exec_snapshot](#jerry_exec_snapshot) and @@ -153,6 +169,7 @@ parts of the snapshot buffer into memory. The `JERRY_SNAPSHOT_EXEC_COPY_DATA` option is not allowed for static snapshots. +*New in version 2.0*. ## jerry_char_t @@ -264,6 +281,8 @@ typedef struct } jerry_context_data_manager_t; ``` +*New in version 2.0*. + ## jerry_context_alloc_t **Summary** @@ -279,6 +298,7 @@ typedef void *(*jerry_context_alloc_t) (size_t size, void *cb_data_p); - `size` - allocation size - `cb_data_p` - pointer to user data +*New in version 2.0*. ## jerry_context_t @@ -292,6 +312,8 @@ An opaque declaration of the JerryScript context structure. typedef struct jerry_context_t jerry_context_t; ``` +*New in version 2.0*. + ## jerry_binary_operation_t @@ -304,12 +326,24 @@ Enum that contains the supported binary operation types - JERRY_BIN_OP_GREATER_EQUAL - greater or equal relation (>=) - JERRY_BIN_OP_INSTANCEOF - instanceof operation +*New in version 2.0*. + +**See also** + +- [jerry_binary_operation](#jerry_binary_operation) ## jerry_property_descriptor_t **Summary** -Description of ECMA property descriptor +Description of ECMA property descriptor. This struct can be used +for the [jerry_define_own_property](#jerry_define_own_property) method to +configure how the property should be registered. + +The naming scheme is similar to the JavaScript `Object.defineProperty` method. + +Fields should be used in pairs. That is if the `is_value_defined` is set to `true` +the `value` field should contain the value for the property. **Prototype** @@ -354,9 +388,13 @@ typedef struct } jerry_property_descriptor_t; ``` +**See also** + +- [jerry_define_own_property](#jerry_define_own_property) + ## jerry_heap_stats_t -**summary** +**Summary** Description of JerryScript heap memory stats. It is for memory profiling. @@ -374,6 +412,12 @@ typedef struct } jerry_heap_stats_t; ``` +*New in version 2.0*. + +**See also** + +- [jerry_get_memory_stats](#jerry_get_memory_stats) + ## jerry_external_handler_t **Summary** @@ -389,11 +433,22 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_ const jerry_length_t args_count); ``` +- `function_object` - the JavaScript function object which was invoked. +- `this_val` - the `this` value provided for the function call. +- `args_p` - the function arguments, array of JavaScript values. +- `args_count` - the number of arguments. +- return value + - The function's return value. If there is no return value, use [jerry_create_undefined()](#jerry_create_undefined). + +**See also** + +- [jerry_create_external_function](#jerry_create_external_function) + ## jerry_object_native_free_callback_t **Summary** -Native free callback of an object. It is used in jerry_object_native_info_t. +Native free callback of an object. It is used in `jerry_object_native_info_t` and for external Array buffers. **Prototype** @@ -401,6 +456,13 @@ Native free callback of an object. It is used in jerry_object_native_info_t. typedef void (*jerry_object_native_free_callback_t) (void *native_p); ``` +*New in version 2.0*: Renamed from `jerry_object_free_callback_t`. + +**See also** + +- [jerry_object_native_info_t](#jerry_object_native_info_t) +- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) + ## jerry_object_native_info_t **Summary** @@ -426,6 +488,8 @@ typedef struct } jerry_object_native_info_t; ``` +*New in version 2.0*. + **See also** - [jerry_set_object_native_pointer](#jerry_set_object_native_pointer) @@ -435,7 +499,9 @@ typedef struct **Summary** -Function type applied for each data property of an object +Function type used as a callback for the [jerry_foreach_object_property](#jerry_foreach_object_property) +method. A function with this type must return "true" to continue the iteration or "false" to finish the +iteration on the object's properties. **Prototype** @@ -445,11 +511,24 @@ typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_na void *user_data_p); ``` +- `property_name` - a property name, this is not always a string. +- `property_value` - the value for the given property. +- `user_data_p` - optional user data pointer supplied via the (jerry_foreach_object_property)[#jerry_foreach_object_property] method. +- return value + - true, to continue the iteration + - false, to stop the iteration + +**See also** + +- [jerry_foreach_object_property](#jerry_foreach_object_property) + ## jerry_objects_foreach_t **Summary** -Function type applied for each object in the engine +Function type used as a callback for the (jerry_objects_foreach)[#jerry_objects_foreach] method. +A function with this type must return "true" to continue the iteration or "false" to finish the +iteration on the object's properties. **Prototype** @@ -458,11 +537,25 @@ typedef bool (*jerry_objects_foreach_t) (const jerry_value_t object, void *user_data_p); ``` +- `object` - the current JavaScript object in the for-each iteration. +- `user_data_p` - optional user data pointer supplied via the (jerry_objects_foreach)[#jerry_objects_foreach] method. +- return value + - true, to continue the iteration + - false, to stop the iteration + +*New in version 2.0*. + +**See also** + +- [jerry_objects_foreach](#jerry_objects_foreach) + ## jerry_objects_foreach_by_native_info_t **Summary** -Function type applied for each matching object in the engine +Function type used as a callback for the (jerry_objects_foreach_by_native_info)[#jerry_objects_foreach_by_native_info] +method. A function with this type must return "true" to continue the iteration or "false" to finish the +iteration on the object's properties. **Prototype** @@ -472,6 +565,19 @@ typedef bool (*jerry_objects_foreach_by_native_info_t) (const jerry_value_t obje void *user_data_p); ``` +- `object` - the current JavaScript object in the for-each iteration. +- `object_data_p` - the current object's native data pointer. +- `user_data_p` - optional user data pointer supplied via the (jerry_objects_foreach_by_native_info)[#jerry_objects_foreach_by_native_info] method. +- return value + - true, to continue the iteration + - false, to stop the iteration + +*New in version 2.0*. + +**See also** + +- [jerry_objects_foreach_by_native_info](#jerry_objects_foreach_by_native_info) + ## jerry_vm_exec_stop_callback_t **Summary** @@ -489,6 +595,8 @@ In this case the function must throw the same error again. typedef jerry_value_t (*jerry_vm_exec_stop_callback_t) (void *user_p); ``` +*New in version 2.0*. + **See also** - [jerry_set_vm_exec_stop_callback](#jerry_set_vm_exec_stop_callback) @@ -513,6 +621,12 @@ Possible values: API functions can return the `JERRY_TYPEDARRAY_INVALID` value if the TypedArray support is not in the engine. +*New in version 2.0*. + +**See also** + +- [jerry_get_typedarray_type](#jerry_get_typedarray_type) + # General engine functions @@ -521,7 +635,7 @@ TypedArray support is not in the engine. **Summary** Initializes the JerryScript engine, making it possible to run JavaScript code and perform operations -on JavaScript values. +on JavaScript values. This is required for almost all API functions. **Prototype** @@ -530,14 +644,7 @@ void jerry_init (jerry_init_flag_t flags) ``` -`flags` - combination of various engine configuration flags: - -- `JERRY_INIT_EMPTY` - no flags, just initialize in default configuration. -- `JERRY_INIT_SHOW_OPCODES` - print compiled byte-code. -- `JERRY_INIT_SHOW_REGEXP_OPCODES` - print compiled regexp byte-code. -- `JERRY_INIT_MEM_STATS` - dump memory statistics. -- `JERRY_INIT_MEM_STATS_SEPARATE` - dump memory statistics and reset peak values after parse. -- `JERRY_INIT_DEBUGGER` - deprecated, an unused placeholder now +`flags` - combination of various engine configuration flags [jerry_init_flag_t](#jerry_init_flag_t). **Example** @@ -554,11 +661,13 @@ main (void) // ... jerry_cleanup (); + return 0; } ``` **See also** +- [jerry_init_flag_t](#jerry_init_flag_t) - [jerry_cleanup](#jerry_cleanup) @@ -605,6 +714,8 @@ jerry_get_context_data (const jerry_context_data_manager *manager_p); by `manager_p`, which will be stored for future identical calls to `jerry_get_context_data ()`, and which will be deinitialized using the `deinit_cb` callback provided by `manager_p` when the context will be destroyed. +*New in version 2.0*. + **Example** [doctest]: # (test="compile") @@ -667,9 +778,10 @@ someplace_in_the_code (void) Registers an external magic string array. -*Note*: The strings in the array must be sorted by size at first, then lexicographically. -*Note*: The maximum number of external magic strings is limited to 2147483648 (UINT32_MAX / 2). - If there are more than 2147483648 external magic strings the extra is cropped. +*Notes*: + - The strings in the array must be sorted by size at first, then lexicographically. + - The maximum number of external magic strings is limited to 2147483648 (UINT32_MAX / 2). + If there are more than 2147483648 external magic strings the extra is cropped. **Prototype** @@ -681,8 +793,10 @@ jerry_register_magic_strings (const jerry_char_t * const *ex_str_items_p, ``` - `ex_str_items_p` - character arrays, representing external magic strings' contents -- `count` - number of the strings -- `str_lengths_p` - lengths of the strings +- `count` - number of elements in `ext_str_items_p` array +- `str_lengths_p` - array of lengths for each magic string + +*Changed in version 2.0*: The first function argument type was changed. **Example** @@ -728,6 +842,14 @@ main (void) Get heap memory stats. +**Notes**: +- The engine must be initialized with the `JERRY_INIT_MEM_STATS` option to allow + heap statistic collections. See [jerry_init](#jerry_init) +- This API depends on a build option (`JERRY_MEM_STATS`) and can be checked + in runtime with the `JERRY_FEATURE_MEM_STATS` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + + **Prototype** ```c @@ -737,12 +859,17 @@ jerry_get_memory_stats (jerry_heap_stats_t *out_stats_p); - `out_stats_p` - out parameter, that provides the heap statistics. - return value - - true, if run was successful - - false, otherwise. Usually it is because the MEM_STATS feature is not enabled. + - true, if stats were written into the `out_stats_p` pointer. + - false, otherwise. Usually it is because the `JERRY_FEATURE_MEM_STATS` feature is not enabled. + +*New in version 2.0*. **Example** ```c +jerry_init (JERRY_INIT_MEM_STATS); +// ... + jerry_heap_stats_t stats = {0}; bool get_stats_ret = jerry_get_memory_stats (&stats); ``` @@ -767,6 +894,8 @@ jerry_gc (jerry_gc_mode_t mode); - `mode` - operational mode, see [jerry_gc_mode_t](#jerry_gc_mode_t) +*Changed in version 2.0*: Added `mode` argument. + **Example** [doctest]: # () @@ -782,7 +911,7 @@ main (void) jerry_value_t object_value = jerry_create_object (); jerry_release_value (object_value); - jerry_gc (JERRY_GC_SEVERITY_LOW); + jerry_gc (JERRY_GC_PRESSURE_LOW); jerry_cleanup (); } @@ -790,6 +919,7 @@ main (void) **See also** +- [jerry_gc_mode_t](#jerry_gc_mode_t) - [jerry_init](#jerry_init) - [jerry_cleanup](#jerry_cleanup) @@ -832,6 +962,7 @@ main (void) const jerry_char_t script[] = "print ('Hello, World!');"; jerry_run_simple (script, sizeof (script) - 1, JERRY_INIT_EMPTY); + return 0; } ``` @@ -874,6 +1005,8 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a - function object value, if script was parsed successfully, - thrown error, otherwise +*Changed in version 2.0*: Added `resource_name_p`, and `resource_name_length` arguments. + **Example** [doctest]: # () @@ -892,12 +1025,14 @@ main (void) jerry_release_value (parsed_code); jerry_cleanup (); + return 0; } ``` **See also** - [jerry_run](#jerry_run) +- [jerry_parse_function](#jerry_parse_function) ## jerry_parse_function @@ -937,13 +1072,89 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u - function object value, if script was parsed successfully, - thrown error, otherwise +*New in version 2.0*. + +**Example** + +[doctest]: # (name="02.API-REFERENCE-parse-func.c") + +```c +#include +#include +#include "jerryscript.h" + +int +main (void) +{ + int return_value = 1; + + /* Initialize engine */ + jerry_init (JERRY_INIT_EMPTY); + + /* Parse the 'function (a,b) { return a + b; }' function */ + const char function_args[] = "a, b"; + const char function_source[] = "return a + b"; + + jerry_value_t parsed_function = jerry_parse_function (NULL, + 0, + (const jerry_char_t *) function_args, + strlen (function_args), + (const jerry_char_t *) function_source, + strlen (function_source), + JERRY_PARSE_NO_OPTS); + + if (!jerry_value_is_error (parsed_function)) + { + /* Run the parsed function */ + jerry_value_t args[] = { + jerry_create_number (3), + jerry_create_number (55), + }; + jerry_size_t argc = sizeof (args) / sizeof (args[0]); + jerry_value_t ret_value = jerry_call_function (parsed_function, + jerry_create_undefined(), + args, + argc); + + /* Process result value */ + if (jerry_value_is_number (ret_value)) { + double value = jerry_get_number_value (ret_value); + printf ("Function result: %lf\n", value); + + return_value = !(value == (3 + 55)); + } + + /* Release the function arguments */ + for (jerry_size_t idx = 0; idx < argc; idx++) { + jerry_release_value (args[idx]); + } + + /* Returned value must be freed */ + jerry_release_value (ret_value); + } + + /* Parsed function must be freed */ + jerry_release_value (parsed_function); + + /* Cleanup engine */ + jerry_cleanup (); + + return return_value; +} +``` + +**See also** + +- [jerry_call_function](#jerry_call_function) + + ## jerry_run **Summary** Run an EcmaScript function created by `jerry_parse`. -*Note*: +*Notes*: - The code should be previously parsed with `jerry_parse`. - Returned value must be freed with [jerry_release_value](#jerry_release_value) when it is no longer needed. @@ -1021,7 +1232,7 @@ jerry_eval (const jerry_char_t *source_p, - `source_p` - source code to evaluate, it must be a valid utf8 string. - `source_size` - length of the source code - `parse_opts` - any combination of [jerry_parse_opts_t](#jerry_parse_opts_t) flags. -- return value - result of eval, may be error value. +- return value - result of eval, may be an error value. **Example** @@ -1056,6 +1267,8 @@ jerry_run_all_enqueued_jobs (void) - return value - result of last executed job, may be error value. +*New in version 2.0*. + **Example** [doctest]: # () @@ -1079,6 +1292,7 @@ main (void) jerry_release_value (parsed_code); jerry_cleanup (); + return 0; } ``` @@ -1143,6 +1357,8 @@ jerry_value_is_abort (const jerry_value_t value); - true, if the given `jerry_value_t` has the error and abort value set - false, otherwise +*New in version 2.0*. + **Example** ```c @@ -1208,7 +1424,11 @@ jerry_value_is_array (const jerry_value_t value) Returns whether the given `jerry_value_t` is an ArrayBuffer object. -*Note*: This API depends on the ES2015-subset profile. +*Notes*: +- This API depends on a build option (`JERRY_ES2015_BUILTIN_TYPEDARRAY`) and can be checked + in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. **Prototype** @@ -1217,11 +1437,13 @@ bool jerry_value_is_arraybuffer (const jerry_value_t value) ``` -- `value` - api value +- `value` - api value to check. - return value - true, if the given `jerry_value_t` is an ArrayBuffer object. - false, otherwise +*New in version 2.0*. + **Example** ```c @@ -1327,7 +1549,11 @@ jerry_value_is_constructor (const jerry_value_t value) Returns whether the given `jerry_value_t` is a DataView object value. -*Note*: This API depends on the ES2015-subset profile. +*Notes*: +- This API depends on a build option (`JERRY_ES2015_BUILTIN_DATAVIEW`) and can be checked + in runtime with the `JERRY_FEATURE_DATAVIEW` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. **Prototype** @@ -1341,6 +1567,8 @@ jerry_value_is_dataview (const jerry_value_t value) - true, if the given `jerry_value_t` is a DataView object - false, otherwise +*New in version 2.0*. + **Example** [doctest]: # () @@ -1365,12 +1593,14 @@ main (void) jerry_release_value (arraybuffer); jerry_cleanup (); + return 0; } ``` **See also** - [jerry_release_value](#jerry_release_value) +- [jerry_create_dataview](#jerry_create_dataview) ## jerry_value_is_error @@ -1391,6 +1621,8 @@ jerry_value_is_error (const jerry_value_t value); - true, if the given `jerry_value_t` is error value. - false, otherwise +*New in version 2.0*. + **Example** ```c @@ -1574,7 +1806,12 @@ jerry_value_is_object (const jerry_value_t value) Returns whether the given `jerry_value_t` is a promise value. -*Note*: This API depends on the ES2015-subset profile. +*Notes*: +- This API depends on a build option (`JERRY_ES2015_BUILTIN_PROMISE`) and can be checked + in runtime with the `JERRY_FEATURE_PROMISE` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. + **Prototype** @@ -1588,6 +1825,8 @@ jerry_value_is_promise (const jerry_value_t value) - true, if the given `jerry_value_t` is a promise - false, otherwise +*New in version 2.0*. + **Example** ```c @@ -1607,6 +1846,7 @@ jerry_value_is_promise (const jerry_value_t value) **See also** - [jerry_release_value](#jerry_release_value) +- [jerry_create_promise](#jerry_create_promise) ## jerry_value_is_string @@ -1654,7 +1894,11 @@ jerry_value_is_string (const jerry_value_t value) Returns whether the given `jerry_value_t` is a symbol value. -*Note*: This API depends on the ES2015-subset profile. +*Notes*: +- This API depends on a build option (`JERRY_ES2015_BUILTIN_SYMBOL`) and can be checked + in runtime with the `JERRY_FEATURE_SYMBOL` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. **Prototype** @@ -1668,6 +1912,8 @@ jerry_value_is_symbol (const jerry_value_t value) - true, if the given `jerry_value_t` is a symbol - false, otherwise +*New in version 2.0*. + **Example** [doctest]: # () @@ -1693,13 +1939,14 @@ main (void) jerry_release_value (symbol_value); jerry_cleanup (); + return 0; } ``` **See also** - [jerry_release_value](#jerry_release_value) - +- [jerry_create_symbol](#jerry_create_symbol) ## jerry_value_is_typedarray @@ -1707,6 +1954,12 @@ main (void) Checks whether the given `jerry_value_t` is a TypedArray object or not. +*Notes*: +- This API depends on a build option (`JERRY_ES2015_BUILTIN_TYPEDARRAY`) and can be checked + in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. + **Prototype** ```c @@ -1719,19 +1972,32 @@ jerry_value_is_typedarray (const jerry_value_t value) - true, if the given `jerry_value_t` is a TypedArray object. - false, otherwise +*New in version 2.0*. + **Example** +[doctest]: # () + ```c +#include "jerryscript.h" + +int +main (void) { - jerry_value_t value; - ... // create or acquire value + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t value = jerry_create_typedarray (JERRY_TYPEDARRAY_UINT16, 15); if (jerry_value_is_typedarray (value)) { - ... + /* "value" is a typedarray. */ } jerry_release_value (value); + + jerry_cleanup (); + + return 0; } ``` @@ -1796,6 +2062,12 @@ jerry_type_t jerry_value_get_type (const jerry_value_t value); ``` +- `value` - JavaScript value to check. +- return value + - One of the [jerry_type_t](#jerry_type_t) value. + +*New in version 2.0*. + **Example** ```c @@ -1806,7 +2078,7 @@ jerry_value_get_type (const jerry_value_t value); if (type_info == JERRY_TYPE_NUMBER) { - ... + /* ... */ } jerry_release_value (number); @@ -1814,6 +2086,7 @@ jerry_value_get_type (const jerry_value_t value); ``` **See also** + - [jerry_type_t](#jerry_type_t) ## jerry_is_feature_enabled @@ -1834,22 +2107,25 @@ jerry_is_feature_enabled (const jerry_feature_t feature); - true, if the given `jerry_feature_t` is enabled - false, otherwise +*New in version 2.0*. + **Example** ```c { - ... + /* ... */ jerry_feature_t feature = JERRY_FEATURE_SNAPSHOT_SAVE; if (jerry_is_feature_enabled (feature)) { - ... + /* ... */ } } ``` **See also** + - [jerry_feature_t](#jerry_feature_t) @@ -1880,6 +2156,8 @@ jerry_binary_operation (jerry_binary_operation_t op, - error, if argument has an error flag or operation is unsuccessful or unsupported - true/false, the result of the binary operation on the given operands otherwise +*New in version 2.0*. + **Example - JERRY_BIN_OP_EQUAL** ```c @@ -1965,11 +2243,14 @@ main (void) ``` **See also** + - [jerry_binary_operation_t](#jerry_binary_operation_t) # Error manipulation functions +*Changed in version 2.0*: The error handling and manipulation was modified and the old methods were replaced. + ## jerry_create_abort_from_value **Summary** @@ -1994,6 +2275,8 @@ jerry_create_abort_from_value (jerry_value_t value, bool release); - `release` - raw boolean, defines whether input value must be released - return value - abort (api) value +*New in version 2.0*. + **Example 1** ```c @@ -2053,6 +2336,8 @@ jerry_create_error_from_value (jerry_value_t value, bool release); - `release` - raw boolean, defines whether input value must be released - return value - error (api) value +*New in version 2.0*. + **Example 1** ```c @@ -2087,7 +2372,7 @@ jerry_create_error_from_value (jerry_value_t value, bool release); - [jerry_value_t](#jerry_value_t) - [jerry_get_value_from_error](#jerry_get_value_from_error) -- [jerry_create_abort_from_value](#jerry_create_abort_from_value +- [jerry_create_abort_from_value](#jerry_create_abort_from_value) ## jerry_get_error_type @@ -2113,6 +2398,8 @@ jerry_get_error_type (const jerry_value_t value); - JERRY_ERROR_NONE if the input is not an error object - one of the [jerry_error_t](#jerry_error_t) value +*New in version 2.0*. + **Example** ```c @@ -2160,6 +2447,8 @@ jerry_get_value_from_error (jerry_value_t value, bool release) - `release` - raw boolean, defines whether input value must be released - return value - api value +*New in version 2.0*. + **Example 1** ```c @@ -2249,6 +2538,8 @@ jerry_get_boolean_value (const jerry_value_t value); Gets the number value of the given `jerry_value_t` parameter as a raw double. +If the argument passed is not a number `0.0` will be returned. + **Prototype** ```c @@ -2257,7 +2548,9 @@ jerry_get_number_value (const jerry_value_t value); ``` - `value` - api value -- return value - the number value of the given `jerry_value_t` parameter as a raw double. +- return value + - the number value of the given `jerry_value_t` parameter as a raw double. + - `0.0` if the api value passed is not a number. **Example** @@ -2291,6 +2584,7 @@ jerry_get_number_value (const jerry_value_t value); **Summary** Get the size of a string. Returns zero, if the value parameter is not a string. +This is effectively the number of bytes required to store the string's characters. **Prototype** @@ -2328,6 +2622,7 @@ jerry_get_string_size (const jerry_value_t value); **Summary** Get the size of an utf8-encoded string. Returns zero, if the value parameter is not a string. +This is effectively the number of bytes required to store the utf8 encoded string's characters. *Note*: The difference from [jerry_get_string_size](#jerry_get_string_size) is that it returns with utf-8 string size instead of the cesu-8 string size. @@ -2341,6 +2636,8 @@ jerry_get_utf8_string_size (const jerry_value_t value); - `value` - api value - return value - number of bytes in the buffer needed to represent the utf8-encoded string. +*New in version 2.0*. + **Example** ```c @@ -2369,6 +2666,11 @@ jerry_get_utf8_string_size (const jerry_value_t value); Get the length of a string. Returns zero, if the value parameter is not a string. +*Notes:* +- The difference from [jerry_get_string_size](#jerry_get_string_size) is that it + returns the number of bytes used for the string. +- This is **not** the number of bytes required to store the string. + **Prototype** ```c @@ -2407,8 +2709,10 @@ jerry_get_string_length (const jerry_value_t value); Get the length of an UTF-8 encoded string. Returns zero, if the value parameter is not a string. -*Note*: The difference from [jerry_get_string_length](#jerry_get_string_length) is that it -returns with utf-8 string length instead of the cesu-8 string length. +*Notes*: +- The difference from [jerry_get_string_length](#jerry_get_string_length) is that it + returns with utf-8 string length instead of the cesu-8 string length. +- This is **not** the number of bytes required to store the string. **Prototype** @@ -2420,6 +2724,8 @@ jerry_get_utf8_string_length (const jerry_value_t value); - `value` - input string value - return value - number of characters in the string +*New in version 2.0*. + **Example** ```c @@ -2476,17 +2782,37 @@ jerry_string_to_char_buffer (const jerry_value_t value, **Example** +[doctest]: # () + ```c +#include +#include +#include "jerryscript.h" + +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t value; - ... // create or acquire value + // create or acquire value + value = jerry_create_string ((const jerry_char_t *) "Demo string"); - jerry_size_t req_sz = jerry_get_string_size (value); - jerry_char_t str_buf_p[req_sz]; + // Read the string into a byte buffer. + jerry_size_t string_size = jerry_get_string_size (value); + jerry_char_t *string_buffer_p = (jerry_char_t *) malloc (sizeof (jerry_char_t) * string_size); - jerry_string_to_char_buffer (value, str_buf_p, req_sz); + jerry_size_t copied_bytes = jerry_string_to_char_buffer (value, string_buffer_p, string_size); + string_buffer_p[copied_bytes] = '\0'; jerry_release_value (value); + + jerry_cleanup (); + + printf ("Test string: %s\n", string_buffer_p); + free (string_buffer_p); + + return 0; } ``` @@ -2529,6 +2855,8 @@ jerry_string_to_utf8_char_buffer (const jerry_value_t value, - `buffer_size` - size of the buffer - return value - number of bytes, actually copied to the buffer +*New in version 2.0*. + **Example** ```c @@ -2539,7 +2867,7 @@ jerry_string_to_utf8_char_buffer (const jerry_value_t value, jerry_size_t req_sz = jerry_get_utf8_string_size (value); jerry_char_t str_buf_p[req_sz]; - jerry_string_to_utf8_char_buffer (value, str_buf_p, req_sz); + jerry_size_t bytes_copied = jerry_string_to_utf8_char_buffer (value, str_buf_p, req_sz); jerry_release_value (value); } @@ -2584,6 +2912,8 @@ jerry_substring_to_char_buffer (const jerry_value_t value, - `buffer_size` - size of the buffer - return value - number of bytes, actually copied to the buffer +*New in version 2.0*. + **Example** ```c @@ -2641,6 +2971,8 @@ jerry_substring_to_utf8_char_buffer (const jerry_value_t value, - `buffer_size` - size of the buffer - return value - number of bytes, actually copied to the buffer +*New in version 2.0*. + **Example** ```c @@ -2903,7 +3235,7 @@ jerry_value_to_string (const jerry_value_t value); # Functions for promise objects -These APIs all depend on the ES2015-subset profile. +These APIs all depend on the ES2015-subset profile (or on some build options). ## jerry_resolve_or_reject_promise @@ -2911,8 +3243,14 @@ These APIs all depend on the ES2015-subset profile. Resolve or reject the promise with an argument. -*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it -is no longer needed. +*Note*: +- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it + is no longer needed. +- This API depends on a build option (`JERRY_ES2015_BUILTIN_PROMISE`) and can be checked + in runtime with the `JERRY_FEATURE_PROMISE` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. + **Prototype** @@ -2930,6 +3268,8 @@ jerry_resolve_or_reject_promise (jerry_value_t promise, - undefined jerry value - resolve or reject successed - jerry value with error flag - otherwise +*New in version 2.0*. + **Example** ```c @@ -2963,16 +3303,23 @@ jerry_resolve_or_reject_promise (jerry_value_t promise, # Functions for symbols -These APIs all depend on the ES2015-subset profile. +These APIs all depend on the ES2015-subset profile (or on build options). ## jerry_get_symbol_descriptive_string **Summary** Call the SymbolDescriptiveString ecma builtin operation on the API value. +Based on ECMA 262 v6 19.4.3.2.1 this is in the form of `Symbol()`. -*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it -is no longer needed. +*Notes*: +- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it + is no longer needed. +- This API depends on a build option (`JERRY_ES2015_BUILTIN_SYMBOL`) and can be checked + in runtime with the `JERRY_FEATURE_SYMBOL` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. +- If the symbol support is not enabled an error will be returned. **Prototype** @@ -2986,6 +3333,8 @@ jerry_get_symbol_descriptive_string (const jerry_value_t value); - string value containing the symbol's descriptive string - if success - thrown error, otherwise +*New in version 2.0*. + **Example** [doctest]: # () @@ -3011,6 +3360,7 @@ main (void) jerry_release_value (symbol_value); jerry_cleanup (); + return 0; } ``` @@ -3152,6 +3502,8 @@ jerry_create_arraybuffer (jerry_length_t size); - `size` - size of the ArrayBuffer to create **in bytes** - return value - the new ArrayBuffer as a `jerry_value_t` +*New in version 2.0*. + **Example** ```c @@ -3204,6 +3556,8 @@ jerry_create_arraybuffer_external (const jerry_length_t size - the new ArrayBuffer as a `jerry_value_t` - if the `size` is zero or `buffer_p` is a null pointer will return RangeError +*New in version 2.0*. + **Example** ```c @@ -3375,6 +3729,8 @@ jerry_create_dataview (const jerry_value_t array_buffer, - value of the constructed DataView object - if success - created error - otherwise +*New in version 2.0*. + **Example** [doctest]: # () @@ -3396,6 +3752,7 @@ main (void) jerry_release_value (arraybuffer); jerry_cleanup (); + return 0; } ``` @@ -3426,7 +3783,13 @@ jerry_create_external_function (jerry_external_handler_t handler_p); **Example** +[doctest]: # () + ```c +#include +#include +#include "jerryscript.h" + static jerry_value_t handler (const jerry_value_t function_obj, const jerry_value_t this_val, @@ -3438,7 +3801,11 @@ handler (const jerry_value_t function_obj, return jerry_create_boolean (true); } +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t func_val = jerry_create_external_function (handler); jerry_value_t glob_obj = jerry_get_global_object (); @@ -3450,6 +3817,16 @@ handler (const jerry_value_t function_obj, jerry_release_value (func_val); jerry_release_value (glob_obj); + + // Test the method by calling it + const char *test_src = "handler_field ();"; + jerry_value_t ret_val = jerry_eval ((const jerry_char_t *) test_src, + strlen (test_src), + JERRY_PARSE_NO_OPTS); + // release the eval result + jerry_release_value (ret_val); + jerry_cleanup (); + return 0; } ``` @@ -3661,6 +4038,8 @@ jerry_create_promise (void) - return value - value of the newly created promise +*New in version 2.0*. + **Example** ```c @@ -3779,6 +4158,8 @@ jerry_create_string_from_utf8 (const jerry_char_t *str_p); - `str_p` - pointer to string - return value - value of the created string +*New in version 2.0*. + **Example** ```c @@ -3820,6 +4201,8 @@ jerry_create_string_sz (const jerry_char_t *str_p, - `str_size` - size of the string - return value - value of the created string +*New in version 2.0*. + **Example** ```c @@ -3865,6 +4248,8 @@ jerry_create_symbol (const jerry_value_t value) - value of the created symbol, if success - thrown error, otherwise +*New in version 2.0*. + **Example** [doctest]: # () @@ -3918,6 +4303,8 @@ jerry_create_regexp (const jerry_char_t *pattern_p, uint16_t flags); - `flags` - optional flags for the RegExp object, see [jerry_regexp_flags_t](#jerry_regexp_flags_t) - return value - the RegExp object as a `jerry_value_t` +*New in version 2.0*. + **Example** ```c @@ -3956,6 +4343,8 @@ jerry_create_regexp_sz (const jerry_char_t *pattern_p, jerry_size_t pattern_size - `flags` - optional flags for the RegExp object, see [jerry_regexp_flags_t](#jerry_regexp_flags_t) - return value - the RegExp object as a `jerry_value_t` +*New in version 2.0*. + **Example** ```c @@ -3982,10 +4371,13 @@ Create a jerry_value_t representing an TypedArray object. For the new object the type of the TypedArray (see: [jerry_typedarray_type_t](#jerry_typedarray_type_t)) and element count can be specified. -*Note*: - - This API depends on the ES2015-subset profile. - - Returned value must be freed with [jerry_release_value](#jerry_release_value) - when it is no longer needed. +*Notes*: +- Returned value must be freed with [jerry_release_value](#jerry_release_value) + when it is no longer needed. +- This API depends on a build option (`JERRY_ES2015_BUILTIN_TYPEDARRAY`) and can be checked + in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. **Prototype** @@ -3998,6 +4390,8 @@ jerry_create_typedarray (jerry_typedarray_type_t type_name, jerry_length_t item_ - `item_count` - number of items in the new TypedArray - return value - the new TypedArray as a `jerry_value_t` +*New in version 2.0*. + **Example** ```c @@ -4033,10 +4427,13 @@ type of TypedArray otherwise an error is generated. The JavaScript equivalent of this function is: `new %TypedArray%(arraybuffer)` where `%TypedArray%` is one of the allowed TypedArray functions. -*Note*: - - This API depends on the ES2015-subset profile. - - Returned value must be freed with [jerry_release_value](#jerry_release_value) - when it is no longer needed. +*Notes*: +- Returned value must be freed with [jerry_release_value](#jerry_release_value) + when it is no longer needed. +- This API depends on a build option (`JERRY_ES2015_BUILTIN_TYPEDARRAY`) and can be checked + in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. **Prototype** @@ -4052,6 +4449,8 @@ jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name, - the new TypedArray as a `jerry_value_t` - Error if the ArrayBuffer does not have enough space for the given type of TypedArray +*New in version 2.0*. + **Example** ```c @@ -4089,10 +4488,13 @@ type of TypedArray otherwise an error is generated. The JavaScript equivalent of this function is: `new %TypedArray%(arraybuffer, byteOffset, length)` where `%TypedArray%` is one of the allowed TypedArray functions. -*Note*: - - This API depends on the ES2015-subset profile. - - Returned value must be freed with [jerry_release_value](#jerry_release_value) - when it is no longer needed. +*Notes*: +- Returned value must be freed with [jerry_release_value](#jerry_release_value) + when it is no longer needed. +- This API depends on a build option (`JERRY_ES2015_BUILTIN_TYPEDARRAY`) and can be checked + in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). +- The ES2015-subset profile enables this by default. **Prototype** @@ -4112,6 +4514,8 @@ jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name, - the new TypedArray as a `jerry_value_t` - Error if the ArrayBuffer does not have enough space for the given type of TypedArray +*New in version 2.0*. + **Example** ```c @@ -4190,10 +4594,20 @@ jerry_has_property (const jerry_value_t obj_val, - true, if the property exists - false, otherwise +*Changed in version 2.0*: The return value type is now a JavaScript value and not a primitive boolean value. + **Example** +[doctest]: # () + ```c +#include "jerryscript.h" + +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t global_object = jerry_get_global_object (); jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "handler_field"); @@ -4203,6 +4617,10 @@ jerry_has_property (const jerry_value_t obj_val, jerry_release_value (has_prop_js); jerry_release_value (prop_name); jerry_release_value (global_object); + + jerry_cleanup (); + + return 0; } ``` @@ -4235,19 +4653,33 @@ jerry_has_own_property (const jerry_value_t obj_val, - true, if the property exists - false, otherwise +*Changed in version 2.0*: The return value type is now a JavaScript value and not a primitive boolean value. + **Example** +[doctest]: # () + ```c +#include "jerryscript.h" + +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t global_object = jerry_get_global_object (); jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "handler_field"); jerry_value_t has_prop_js = jerry_has_own_property (global_object, prop_name); bool has_prop = jerry_get_boolean_value (has_prop_js); - jerry_release_value (jas_prop_js); + jerry_release_value (has_prop_js); jerry_release_value (prop_name); jerry_release_value (global_object); + + jerry_cleanup (); + + return 0; } ``` @@ -4284,7 +4716,8 @@ jerry_delete_property (const jerry_value_t obj_val, jerry_value_t global_object = jerry_get_global_object (); jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_prop"); - jerry_delete_property (global_object, prop_name); + bool delete_result = jerry_delete_property (global_object, prop_name); + /* use "delete_result" */ jerry_release_value (prop_name); jerry_release_value (global_object); @@ -4319,6 +4752,8 @@ jerry_delete_property_by_index (const jerry_value_t obj_val, - true, if property was deleted successfully - false, otherwise +*New in version 2.0*. + **Example** ```c @@ -4327,7 +4762,7 @@ jerry_delete_property_by_index (const jerry_value_t obj_val, ... // create or acquire object - jerry_delete_property_by_index (object, 5); + bool delete_result = jerry_delete_property_by_index (object, 5); jerry_release_value (object); } @@ -4369,15 +4804,28 @@ jerry_get_property (const jerry_value_t obj_val, **Example** +[doctest]: # () + ```c +#include "jerryscript.h" + +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t global_object = jerry_get_global_object (); - jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_prop"); + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "Object"); jerry_value_t prop_value = jerry_get_property (global_object, prop_name); + /* use "prop_value" then release it. */ + + jerry_release_value (prop_value); jerry_release_value (prop_name); jerry_release_value (global_object); + + return 0; } ``` @@ -4563,7 +5011,8 @@ jerry_set_property_by_index (const jerry_value_t obj_val, **Summary** -Initialize property descriptor. +Initialize property descriptor. This means that all fields in the `jerry_property_descriptor_t` +struct will be set to zero or false depending on the field's type. **Prototype** @@ -4587,8 +5036,11 @@ jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p) } ``` +For a more complete example see [jerry_define_own_property](#jerry_define_own_property). + **See also** +- [jerry_property_descriptor_t](#jerry_property_descriptor_t) - [jerry_define_own_property](#jerry_define_own_property) - [jerry_get_own_property_descriptor](#jerry_get_own_property_descriptor) - [jerry_free_property_descriptor_fields](#jerry_free_property_descriptor_fields) @@ -4612,7 +5064,7 @@ jerry_define_own_property (const jerry_value_t obj_val, const jerry_property_descriptor_t *prop_desc_p); ``` -- `obj_val` - object value +- `obj_val` - target object where the property should be registered - `prop_name_val` - property name - `prop_desc_p` - pointer to property descriptor - return value @@ -4621,32 +5073,152 @@ jerry_define_own_property (const jerry_value_t obj_val, **Example** +Registering a simple value property via the `jerry_define_own_property` method: + +[doctest]: # (name="02.API-REFERENCE-define-property.c") + ```c +#include "jerryscript.h" + +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t global_obj_val = jerry_get_global_object (); + // configure the property jerry_property_descriptor_t prop_desc; jerry_init_property_descriptor_fields (&prop_desc); jerry_value_t value_to_set; - ... // create or acquire value to set + // create or acquire value to set + // For example: + value_to_set = jerry_create_number (33); + // set the property descriptor fields: + // set the "is_value_defined" field to "true" to indicate the "value" + // field should be used during the property registration. prop_desc.is_value_defined = true; + + // set the "value" field to the number 33 prop_desc.value = value_to_set; + // add the property as "my_prop" for the global object jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_prop"); jerry_value_t return_value = jerry_define_own_property (global_obj_val, prop_name, &prop_desc); + if (jerry_value_is_error (return_value)) + { + // there was an error + } + + // if there was no error at this point the global object should have a "my_prop" property + jerry_release_value (return_value); jerry_release_value (prop_name); jerry_free_property_descriptor_fields (&prop_desc); jerry_release_value (global_obj_val); + + jerry_cleanup (); + return 0; +} +``` + + +Registering a getter/setter property via the `jerry_define_own_property` method: + +[doctest]: # (name="02.API-REFERENCE-define-property-getset.c") + +```c +#include +#include +#include "jerryscript.h" + +static int counter = 0; + +static jerry_value_t +method_getter (const jerry_value_t this_obj, + const jerry_value_t func_obj, + const jerry_value_t args[], + const jerry_length_t argc) +{ + counter++; + printf("Getter called, returning: %d\n", counter); + + return jerry_create_number (counter); +} + +static jerry_value_t +method_setter (const jerry_value_t this_obj, + const jerry_value_t func_obj, + const jerry_value_t args[], + const jerry_length_t argc) +{ + // Note: the arguments count and type should be checked + // in this example it is ommitted! + + double new_value = jerry_get_number_value (args[0]); + counter = (int) new_value; + + printf("Setter called, setting: %d\n", counter); + + return jerry_create_undefined (); +} + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t global_obj_val = jerry_get_global_object (); + + // configure the property + jerry_property_descriptor_t prop_desc; + jerry_init_property_descriptor_fields (&prop_desc); + + // set the property descriptor fields: + + prop_desc.is_get_defined = true; + prop_desc.getter = jerry_create_external_function (method_getter); + prop_desc.is_set_defined = true; + prop_desc.setter = jerry_create_external_function (method_setter); + + // add the property as "my_prop" for the global object + jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "my_prop"); + jerry_value_t return_value = jerry_define_own_property (global_obj_val, prop_name, &prop_desc); + if (jerry_value_is_error (return_value)) + { + // there was an error + } + + // if there was no error at this point the global object should have a "my_prop" property + + jerry_release_value (return_value); + jerry_release_value (prop_name); + + jerry_free_property_descriptor_fields (&prop_desc); + jerry_release_value (global_obj_val); + + // run an example js code to use the getter/setters + + const char *src_p = "this.my_prop; this.my_prop; this.my_prop = 4; this.my_prop"; + jerry_value_t eval_result = jerry_eval ((const jerry_char_t *) src_p, strlen (src_p), JERRY_PARSE_NO_OPTS); + + // "eval_result" is the last result of "this.my_prop" that is "5" currently. + double result_number = jerry_get_number_value (eval_result); + printf("output: %lf\n", result_number); + + jerry_cleanup (); + + return result_number != 5.0; } ``` **See also** +- [jerry_property_descriptor_t](#jerry_property_descriptor_t) - [jerry_init_property_descriptor_fields](#jerry_init_property_descriptor_fields) - [jerry_get_own_property_descriptor](#jerry_get_own_property_descriptor) - [jerry_free_property_descriptor_fields](#jerry_free_property_descriptor_fields) @@ -4694,6 +5266,7 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, **See also** +- [jerry_property_descriptor_t](#jerry_property_descriptor_t) - [jerry_init_property_descriptor_fields](#jerry_init_property_descriptor_fields) - [jerry_define_own_property](#jerry_define_own_property) - [jerry_free_property_descriptor_fields](#jerry_free_property_descriptor_fields) @@ -4765,14 +5338,14 @@ jerry_call_function (const jerry_value_t func_obj_val, ```c { - jerry_value_t val; + jerry_value_t target_function; - ... // receiving val + ... // create or get "target_function" - if (jerry_value_is_function (val)) + if (jerry_value_is_function (target_function)) { jerry_value_t this_val = jerry_create_undefined (); - jerry_value_t ret_val = jerry_call_function (val, this_val, NULL, 0); + jerry_value_t ret_val = jerry_call_function (target_function, this_val, NULL, 0); if (!jerry_value_is_error (ret_val)) { @@ -4783,7 +5356,7 @@ jerry_call_function (const jerry_value_t func_obj_val, jerry_release_value (this_val); } - jerry_release_value (val); + jerry_release_value (target_function); } ``` @@ -4999,6 +5572,8 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, - true, if there is native pointer associated of the specified object with the given native type info - false, otherwise +*New in version 2.0*: Changed from `jerry_get_object_native_handle`. + **Example** [doctest]: # () @@ -5189,7 +5764,8 @@ You can get them by calling jerry_get_object_native_pointer later. *Note*: If a non-NULL free callback is specified in the native type information, it will be called by the garbage collector when the object is freed. - The type info is always overwrites the previous value, so passing + This callback **must not** invoke API functions. + The type info always overwrites the previous value, so passing a NULL value deletes the current type info. **Prototype** @@ -5207,6 +5783,8 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val, be a long-lived pointer, usually a pointer to a `static const jerry_object_native_info_t` makes most sense. +*New in version 2.0*: Changed from `jerry_set_object_native_handle`. + **Example** See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) for a @@ -5240,6 +5818,8 @@ jerry_delete_object_native_pointer (const jerry_value_t obj_val, - `obj_val` - object to delete native pointer from. - `info_p` - native pointer's type information. +*New in version 2.0*. + **Example** See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) for a @@ -5257,7 +5837,10 @@ best-practice example. **Summary** -Applies the given function to every property in the given object. +Applies the given function to every enumerable(!) property in the given object. + +The "iterator" `foreach_p` method should return `true` value to continue the iteration. +If the method returns `false` the iteration will end. **Prototype** @@ -5279,25 +5862,74 @@ jerry_foreach_object_property (jerry_value_t obj_val, **Example** + +[doctest]: # (name="02.API-REFERENCE-foreach-property.c") + ```c -bool +#include +#include "jerryscript.h" + +/* Example structure used as user data for the property iteration. */ +struct iteration_data { + int string_property_count; +}; + +/* + * Example foreach function to print out property names. + */ +static bool foreach_function (const jerry_value_t prop_name, const jerry_value_t prop_value, void *user_data_p) { + if (jerry_value_is_string (prop_name)) { + jerry_char_t string_buffer[128]; + jerry_size_t copied_bytes = jerry_substring_to_char_buffer (prop_name, + 0, + 127, + string_buffer, + 127); + string_buffer[copied_bytes] = '\0'; - ... // implementation of the foreach function + printf ("Property: %s\n", string_buffer); + struct iteration_data *data = (struct iteration_data *) user_data_p; + data->string_property_count++; + } + + /* return true to continue iteration */ + return true; } +int +main (void) { - jerry_value_t object; - ... // receive or construct object + jerry_init (JERRY_INIT_EMPTY); - double data = 3.14; // example data + /* Construct an example object with a single property. */ + jerry_value_t object = jerry_create_object (); + { + jerry_value_t test_property = jerry_create_string ((const jerry_char_t *) "DemoProp"); + jerry_value_t test_value = jerry_create_number (3); + /* By default all properties added to an object are enumerable. */ + jerry_value_t set_result = jerry_set_property (object, test_property, test_value); + /* The `set_result` should be checked if it is an error or not. */ + jerry_release_value (set_result); + jerry_release_value (test_value); + jerry_release_value (test_property); + } - jerry_foreach_object_property (object, foreach_function, &data); + /* Iterate on the object's properties with the given user data. */ + struct iteration_data user_data = { 0 }; + bool iteration_result = jerry_foreach_object_property (object, foreach_function, &user_data); + /* Check and process the `iteration_result` if required. */ + + jerry_release_value (object); + + jerry_cleanup (); + + return user_data.string_property_count == 0; } ``` @@ -5309,7 +5941,10 @@ foreach_function (const jerry_value_t prop_name, **Summary** -Iterate over objects. +Iterate over all objects available in the engine. + +The "iterator" `foreach_p` method should return `true` value to continue the search. +If the method returns `false` the search for the object is finished. *Note*: Values obtained in `foreach_p` must be retained using [jerry_acquire_value](#jerry_acquire_value). @@ -5327,9 +5962,17 @@ jerry_objects_foreach (jerry_objects_foreach_t foreach_p, - `true`, if the search function terminated the traversal by returning `false` - `false`, if the end of the list of objects was reached +*New in version 2.0*. + **Example** +[doctest]: # (name="02.API-REFERENCE-objects-foreach.c") + ```c +#include +#include "jerryscript.h" + +/* Create a custom structure to guide the search and store the result. */ typedef struct { jerry_value_t property_name; @@ -5340,31 +5983,74 @@ typedef struct * Find the first object with the given property. */ static bool -find_my_object(const jerry_value_t candidate, - void *user_data_p) +find_my_object (const jerry_value_t candidate, + void *user_data_p) { find_my_object_info_t *info_p = (find_my_object_info_t *) user_data_p; - jerry_value_t has_property = jerry_object_has_property (candidate, info_p->property_name); - bool keep_searching = (jerry_value_is_error (has_property) || !jerry_get_boolean_value ()); - if (!keep_searching) + + /* Check if the given object has the required property. */ + jerry_value_t has_property = jerry_has_property (candidate, info_p->property_name); + bool object_found = jerry_get_boolean_value (has_property); + + if (object_found) { /* We found it, so we acquire the value and record it. */ info_p->result = jerry_acquire_value (candidate); } + jerry_release_value (has_property); - return keep_searching; + + /* If the object was not found continue the search. */ + return !object_found; } /* find_my_object */ +int +main (void) { + int return_value = 0; + + /* Initialize JerryScript engine. */ + jerry_init (JERRY_INIT_EMPTY); + + /* Create the test object. */ + { + jerry_value_t test_object = jerry_create_object (); + + { + jerry_value_t test_property = jerry_create_string ((const jerry_char_t *) "DemoProp"); + jerry_value_t test_value = jerry_create_number (3); + jerry_value_t set_result = jerry_set_property (test_object, test_property, test_value); + /* The `set_result` should be checked if it is an error or not. */ + jerry_release_value (set_result); + jerry_release_value (test_value); + jerry_release_value (test_property); + } + + { + /* Register the test object into the global object. */ + jerry_value_t global_object = jerry_get_global_object (); + jerry_value_t demo_property = jerry_create_string ((const jerry_char_t *) "DemoObject"); + jerry_value_t set_result = jerry_set_property (global_object, demo_property, test_object); + /* The `set_result` should be checked if it is an error or not. */ + jerry_release_value (set_result); + jerry_release_value (demo_property); + jerry_release_value (global_object); + } + + jerry_release_value (test_object); + } + + /* Look up the test object base on a property name. */ find_my_object_info_t search_info = { - .property_name = jerry_create_string ("desired_property") + .property_name = jerry_create_string ((const jerry_char_t *) "DemoProp") }; - if (jerry_object_foreach (find_my_object, &search_info)) + if (jerry_objects_foreach (find_my_object, &search_info)) { /* The search was successful. Do something useful with search_info.result. */ - ... + // ... + printf ("Object found\n"); /* Release the found object after we're done using it. */ jerry_release_value (search_info.result); @@ -5372,11 +6058,19 @@ find_my_object(const jerry_value_t candidate, else { /* The search has failed. */ + printf ("Object not found\n"); + + return_value = 1; } - jerry_release_value (search_info.desired_property); + jerry_release_value (search_info.property_name); + + /* Engine cleanup */ + jerry_cleanup (); + return return_value; } ``` + **See also** - [jerry_objects_foreach_t](#jerry_objects_foreach_t) @@ -5385,7 +6079,10 @@ find_my_object(const jerry_value_t candidate, **Summary** -Iterate over objects matching a certain native data type. +Iterate over all objects in the engine matching a certain native data type. + +The "iterator" `foreach_p` method should return `true` value to continue the search. +If the method returns `false` the search for the object is finished. *Note*: Values obtained in `foreach_p` must be retained using [jerry_acquire_value](#jerry_acquire_value). @@ -5399,13 +6096,22 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i ``` - `native_info_p` - native pointer's type information. +- `foreach_p` - function that will be invoked for each object. - return value - `true`, if the search function terminated the traversal by returning `false` - `false`, if the end of the list of objects was reached +*New in version 2.0*. + **Example** +[doctest]: # (name="02.API-REFERENCE-objects-foreach-nativeptr.c") + ```c +#include +#include +#include "jerryscript.h" + typedef struct { int foo; @@ -5415,68 +6121,105 @@ typedef struct typedef struct { jerry_value_t found_object; - void *match_data_p; + native_obj_t *found_native_data_p; + + int match_foo_value; } find_object_data_t; static void native_freecb (void *native_p) { - ... // free the native pointer + /* `native_p` was allocated via malloc. */ + free (native_p); } /* native_freecb */ -// NOTE: The address (!) of type_info acts as a way to uniquely "identify" the -// C type `native_obj_t *`. +/* + * NOTE: The address (!) of type_info acts as a way to uniquely "identify" the + * C type `native_obj_t *`. + */ static const jerry_object_native_info_t native_obj_type_info = { .free_cb = native_freecb }; -// Function creating JS object that is "backed" by a native_obj_t *: +/* + * Function creating JS object that is "backed" by a `native_obj_t`. + */ +static void +add_object_with_nativeptr (int foo_value) { - ... - // construct object and native_set value: - jerry_value_t object = ...; + jerry_value_t test_object = jerry_create_object (); native_obj_t *native_obj_p = malloc (sizeof (*native_obj_p)); - jerry_set_object_native_pointer (object, native_obj_p, &native_obj_type_info); + native_obj_p->foo = foo_value; + native_obj_p->bar = true; - ... -} + jerry_set_object_native_pointer (test_object, native_obj_p, &native_obj_type_info); -// Native method that retrieves the JavaScript object by way of its native data: -static bool find_object (const jerry_value_t candidate, void *data_p, void *user_data_p) + /* Register the test object into the global object. */ + jerry_value_t global_object = jerry_get_global_object (); + jerry_value_t demo_property = jerry_create_string ((const jerry_char_t *) "DemoObject"); + jerry_value_t set_result = jerry_set_property (global_object, demo_property, test_object); + /* The `set_result` should be checked if it is an error or not. */ + jerry_release_value (set_result); + jerry_release_value (demo_property); + jerry_release_value (global_object); + + jerry_release_value (test_object); +} /* create_object_with_nativeptr */ + +/* + * Example native method that searches for a JavaScript object + * with a `native_obj_type_info` has the correct value. + */ +static bool +find_object (const jerry_value_t candidate, void *data_p, void *user_data_p) { find_object_data_t *find_data_p = (find_object_data_t *) user_data_p; + native_obj_t *native_obj_p = (native_obj_t *) data_p; - if (find_data_p->match_data_p == data_p) + if (find_data_p->match_foo_value == native_obj_p->foo) { - // If the object was found, acquire it and store it in the user data. + /* If the object was found, acquire it and store it in the user data. */ find_data_p->found_object = jerry_acquire_value (candidate); + find_data_p->found_native_data_p = native_obj_p; - // Stop traversing over the objects. + /* Stop traversing over the objects. */ return false; } - // Indicate that the object was not found, so traversal must continue. + /* Indicate that the object was not found, so traversal must continue. */ return true; } /* find_object */ -... + +int +main (void) { + jerry_init (JERRY_INIT_EMPTY); + + add_object_with_nativeptr (4); + add_object_with_nativeptr (3); + add_object_with_nativeptr (2); + find_object_data_t find_data = { - .match_data = native_obj + .match_foo_value = 3, }; if (jerry_objects_foreach_by_native_info (&native_obj_type_info, find_object, &find_data)) { - // The object was found and is now stored in find_data.found_object. After using it, it must be released. - ... + /* The object was found and is now stored in `find_data.found_object`. After using it, it must be released. */ + printf ("Object found, native foo value: %d\n", find_data.found_native_data_p->foo); + jerry_release_value (find_data.found_object); } else { - // The object was not found. + printf ("Object not found\n"); } - ... + + jerry_cleanup (); + + return 0; } ``` @@ -5495,7 +6238,10 @@ static bool find_object (const jerry_value_t candidate, void *data_p, void *user **Summary** -Validate UTF-8 string. +Check if a given character buffer is a valid UTF-8 string. + +**Notes**: Calling this method is safe in any time. It can be called +even before engine initialization. **Prototype** @@ -5505,8 +6251,13 @@ jerry_is_valid_utf8_string (const jerry_char_t *utf8_buf_p, /**< UTF-8 string */ jerry_size_t buf_size) /**< string size */ ``` -- `utf8_buf_p` - UTF-8 input string -- `buf_size` - input string size +- `utf8_buf_p` - UTF-8 input string buffer. +- `buf_size` - input string buffer size in bytes. +- return value + - true, if the provided string was a valid UTF-8 string. + - false, if the string is not valid as an UTF-8 string. + +*New in version 2.0*. **Example** @@ -5525,6 +6276,8 @@ main (void) { jerry_run_simple (script, script_size, JERRY_INIT_EMPTY); } + + return 0; } ``` @@ -5542,7 +6295,10 @@ main (void) **Summary** -Validate CESU-8 string. +Check if a given character buffer is a valid CESU-8 string. + +**Notes**: Calling this method is safe in any time. It can be called +even before engine initialization. **Prototype** @@ -5552,8 +6308,13 @@ jerry_is_valid_cesu8_string (const jerry_char_t *cesu8_buf_p, /**< CESU-8 string jerry_size_t buf_size) /**< string size */ ``` -- `cesu8_buf_p` - CESU-8 input string -- `buf_size` - input string size +- `cesu8_buf_p` - CESU-8 input string buffer. +- `buf_size` - input string buffer size in bytes. +- return value + - true, if the provided string was a valid CESU-8 string. + - false, if the string is not valid as a CESU-8 string. + +*New in version 2.0*. **Example** @@ -5581,6 +6342,7 @@ main (void) } jerry_cleanup (); + return 0; } ``` @@ -5616,6 +6378,8 @@ void *jerry_heap_alloc (size_t size); - return value: non-NULL pointer, if the memory is successfully allocated, NULL otherwise. +*New in version 2.0*. + **See also** - [jerry_heap_free](#jerry_heap_free) @@ -5635,6 +6399,8 @@ void jerry_heap_free (void *mem_p, size_t size); - `mem_p`: value returned by `jerry_heap_alloc`. - `size`: same size as passed to `jerry_heap_alloc`. +*New in version 2.0*. + **See also** - [jerry_heap_alloc](#jerry_heap_alloc) @@ -5664,6 +6430,8 @@ jerry_create_context (uint32_t heap_size, - pointer to the newly created JerryScript context if success - NULL otherwise. +*New in version 2.0*. + **Example** [doctest]: # (test="compile") @@ -5768,14 +6536,16 @@ jerry_generate_snapshot (const jerry_char_t *resource_name_p, - `source_p` - script source, it must be a valid utf8 string. - `source_size` - script source size, in bytes. - `generate_snapshot_opts` - any combination of [jerry_generate_snapshot_opts_t](#jerry_generate_snapshot_opts_t) flags. -- `buffer_p` - buffer (aligned to 4 bytes) to save snapshot to. -- `buffer_size` - the buffer's size. +- `buffer_p` - output buffer (aligned to 4 bytes) to save snapshot to. +- `buffer_size` - the output buffer's size in bytes. - return value - the size of the generated snapshot in bytes as number value, if it was generated succesfully (i.e. there are no syntax errors in source code, buffer size is sufficient, and snapshot support is enabled in - current configuration through JERRY_ENABLE_SNAPSHOT_SAVE) + current configuration through JERRY_SNAPSHOT_SAVE) - thrown error, otherwise. +*New in version 2.0*. + **Example** [doctest]: # () @@ -5804,6 +6574,7 @@ main (void) jerry_release_value (generate_result); jerry_cleanup (); + return 0; } ``` @@ -5851,13 +6622,15 @@ jerry_generate_function_snapshot (const jerry_char_t *resource_name_p, - `args_size` - function argument size, in bytes. - `generate_snapshot_opts` - any combination of [jerry_generate_snapshot_opts_t](#jerry_generate_snapshot_opts_t) flags. - `buffer_p` - buffer (aligned to 4 bytes) to save snapshot to. -- `buffer_size` - the buffer's size. +- `buffer_size` - the buffer's size in bytes. - return value - the size of the generated snapshot in bytes as number value, if it was generated succesfully (i.e. there are no syntax errors in source code, buffer size is sufficient, and snapshot support is enabled in - current configuration through JERRY_ENABLE_SNAPSHOT_SAVE) + current configuration through JERRY_SNAPSHOT_SAVE) - thrown error, otherwise. +*New in version 2.0*. + **Example** [doctest]: # () @@ -5889,6 +6662,7 @@ main (void) jerry_release_value (generate_result); jerry_cleanup (); + return 0; } ``` @@ -5927,6 +6701,8 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, - result of bytecode, if run was successful - thrown error, otherwise +*Changed in version 2.0*: Added `func_index` and `exec_snapshot_opts` arguments. Removed the `copy_bytecode` last argument. + **Example** [doctest]: # () @@ -5965,6 +6741,7 @@ main (void) jerry_release_value (res); jerry_cleanup (); + return 0; } ``` @@ -5996,13 +6773,15 @@ jerry_load_function_snapshot (const uint32_t *snapshot_p, uint32_t exec_snapshot_opts); ``` -- `snapshot_p` - pointer to snapshot -- `snapshot_size` - size of snapshot in bytes -- `func_index` - index of function to load +- `snapshot_p` - pointer to snapshot. +- `snapshot_size` - size of snapshot in bytes. +- `func_index` - index of function to load from the snapshot. - `exec_snapshot_opts` - any combination of [jerry_exec_snapshot_opts_t](#jerry_exec_snapshot_opts_t) flags. - return value - - function object built from the snapshot - - thrown error, otherwise + - function object built from the snapshot. + - thrown error, otherwise. + +*New in version 2.0*. **Example** @@ -6095,9 +6874,11 @@ jerry_get_literals_from_snapshot (const uint32_t *snapshot_p, - `is_c_format` - the output format would be C-style (true) or a simple list (false). - return value - the size of the literal-list, if it was generated succesfully (i.e. the list of literals isn't empty, - and literal-save support is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE) + and literal-save support is enabled in current configuration through JERRY_SNAPSHOT_SAVE) - 0 otherwise. +*New in version 2.0*. + **Example** [doctest]: # (test="link") @@ -6139,6 +6920,7 @@ main (void) } jerry_cleanup (); + return 0; } ``` @@ -6185,6 +6967,8 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, - `user_p` - user pointer passed to the `stop_cb` function - `frequency` - frequency of calling the `stop_cb` function +*New in version 2.0*. + **Example** [doctest]: # (test="link") @@ -6242,8 +7026,12 @@ The array length is zero if the backtrace is not available. This function is typically called from native callbacks. -*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it +*Notes*: +- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it is no longer needed. +- This feature depends on build option (`JERRY_LINE_INFO`) and can be checked + in runtime with the `JERRY_FEATURE_LINE_INFO` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). **Prototype** @@ -6256,6 +7044,96 @@ jerry_get_backtrace (uint32_t max_depth); - return value - a newly constructed JS array +*New in version 2.0*. + +**Example** + +[doctest]: # (name="02.API-REFERENCE-jsbacktrace.c") + +```c +#include +#include +#include "jerryscript.h" + +static jerry_value_t +backtrace_handler (const jerry_value_t function_obj, + const jerry_value_t this_val, + const jerry_value_t args_p[], + const jerry_length_t args_count) +{ + if (!jerry_is_feature_enabled (JERRY_FEATURE_LINE_INFO)) + { + printf ("Line info disabled, no backtrace will be printed\n"); + } + + /* If the line info feature is disabled an empty array will be returned. */ + jerry_value_t backtrace_array = jerry_get_backtrace (5); + uint32_t array_length = jerry_get_array_length (backtrace_array); + + for (uint32_t idx = 0; idx < array_length; idx++) + { + jerry_value_t property = jerry_get_property_by_index (backtrace_array, idx); + + jerry_char_t string_buffer[64]; + jerry_size_t copied_bytes = jerry_substring_to_char_buffer (property, + 0, + 63, + string_buffer, + 63); + string_buffer[copied_bytes] = '\0'; + printf(" %d: %s\n", idx, string_buffer); + + jerry_release_value (property); + } + + jerry_release_value (backtrace_array); + + return jerry_create_undefined (); +} /* backtrace_handler */ + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t global = jerry_get_global_object (); + + /* Register the "dump_backtrace" method. */ + { + jerry_value_t func = jerry_create_external_function (backtrace_handler); + jerry_value_t name = jerry_create_string ((const jerry_char_t *) "backtrace"); + jerry_value_t result = jerry_set_property (global, name, func); + jerry_release_value (result); + jerry_release_value (name); + jerry_release_value (func); + } + + jerry_release_value (global); + + const char *source = ("function f() { g (); }\n" + "function g() { h (); }\n" + "function h() { backtrace (); }\n" + "f ();\n"); + const char *resource = "demo_memoryjs"; + + jerry_value_t program = jerry_parse ((const jerry_char_t *) resource, + strlen (resource), + (const jerry_char_t *) source, + strlen (source), + JERRY_PARSE_NO_OPTS); + if (!jerry_value_is_error (program)) + { + jerry_value_t run_result = jerry_run (program); + jerry_release_value (run_result); + } + + jerry_release_value (program); + jerry_cleanup (); + + return 0; +} +``` + **See also** - [jerry_create_external_function](#jerry_create_external_function) @@ -6284,6 +7162,8 @@ jerry_get_arraybuffer_byte_length (const jerry_value_t value); - size of the ArrayBuffer in bytes - 0 if the `value` parameter is not an ArrayBuffer +*New in version 2.0*. + **Example** ```c @@ -6334,6 +7214,8 @@ jerry_arraybuffer_read (const jerry_value_t value, - 0 if the `value` is not an ArrayBuffer object - 0 if the `buf_size` is zero or there is nothing to read +*New in version 2.0*. + **Example** ```c @@ -6396,6 +7278,8 @@ jerry_arraybuffer_write (const jerry_value_t value, - 0 if the `value` is not an ArrayBuffer object - 0 if the `buf_size` is zero or there is nothing to write +*New in version 2.0*. + **Example** ```c @@ -6436,16 +7320,13 @@ jerry_arraybuffer_write (const jerry_value_t value, **Summary** The function allows access to the contents of the Array Buffer directly. -Only allowed for Array Buffers which were created with -[jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) -function calls. In any other case this function will return `NULL`. - -After using the pointer the [jerry_release_value](#jerry_release_value) -function must be called. **WARNING!** This operation is for expert use only! The programmer must ensure that the returned memory area is used correctly. That is -there is no out of bounds reads or writes. +there is no out of bounds reads or writes. The lifetime of the underlying +data buffer is managed by the ArrayBuffer value. Make sure to acquire the +value with [`jerry_acquire_value`](#jerry_acquire_value) if the data +buffer is needed later. **Prototype** @@ -6457,26 +7338,24 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value); - `value` - Array Buffer object. - return value - pointer to the Array Buffer's data area. - - NULL if the `value` is not an Array Buffer object with external memory. + - NULL if the `value` is not an Array Buffer object. + +*New in version 2.0*. **Example** ```c { - jerry_value_t buffer; - - // acquire buffer somewhere which was created by a jerry_create_array_buffer_external call. + // create the ArrayBuffer + jerry_value_t buffer = jerry_create_arraybuffer (16); uint8_t *const data = jerry_get_arraybuffer_pointer (buffer); - for (int i = 0; i < 22; i++) + for (int i = 0; i < 16; i++) { data[i] = (uint8_t) (i + 4); } - // required after jerry_get_arraybuffer_pointer call. - jerry_release_value (buffer); - // use the Array Buffer // release buffer as it is not needed after this point @@ -6516,6 +7395,8 @@ jerry_get_dataview_buffer (const jerry_value_t value, - DataView object's underlying ArrayBuffer object - TypeError if the `value` is not a DataView object +*New in version 2.0*. + **Example** [doctest]: # () @@ -6574,6 +7455,8 @@ jerry_get_typedarray_type (jerry_value_t value); - the type of the TypedArray - JERRY_TYPEDARRAY_INVALID if the object was not a TypedArray +*New in version 2.0*. + **Example** ```c @@ -6615,6 +7498,8 @@ jerry_get_typedarray_length (jerry_value_t value); - length (element count) of the TypedArray object - 0 if the object is not a TypedArray +*New in version 2.0*. + **Example** ```c @@ -6664,6 +7549,8 @@ jerry_get_typedarray_buffer (jerry_value_t value, - TypedArray object's underlying ArrayBuffer object - TypeError if the `value` is not a TypedArray object +*New in version 2.0*. + **Example** ```c @@ -6709,6 +7596,8 @@ jerry_json_parse (const jerry_char_t *string_p, - jerry_value_t containing the same as json.parse() - jerry_value_t containing error massage +*New in version 2.0*. + **Example** ```c @@ -6740,6 +7629,8 @@ jerry_json_stringify (const jerry_value_t object_to_stringify); - jerry_value_t containing the same as json.stringify() - jerry_value_t containing error massage +*New in version 2.0*. + **Example** ```c diff --git a/03.API-EXAMPLE.md b/03.API-EXAMPLE.md index 257614971..bfbb741d1 100644 --- a/03.API-EXAMPLE.md +++ b/03.API-EXAMPLE.md @@ -10,9 +10,44 @@ permalink: /api-example/ 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 through creation of simple JavaScript shell. +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. -## Step 1. Execute JavaScript from your application + +## 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]: # () @@ -30,39 +65,213 @@ main (void) } ``` -The application will return with zero exit code. +To compile it one can use the following command: -## Step 2. Split engine initialization and script execution +```sh +$ gcc api-example-1.c -o api-example-1 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) +``` -Here we perform the same actions, as `jerry_run_simple`, while splitting into several steps: +If everything is correct the application returns with a zero exit code: -- engine initialization -- script code setup -- script execution -- engine cleanup +``` +$ ./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" -#include "jerryscript-ext/handler.h" int main (void) { - const jerry_char_t script[] = "print ('Hello, World!');"; + 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); - /* Register 'print' function from the extensions */ - jerryx_handler_register_global ((const jerry_char_t *) "print", - jerryx_handler_print); + /* Run the demo script with 'eval' */ + jerry_value_t eval_ret = jerry_eval (script, + script_size, + JERRY_PARSE_NO_OPTS); + + /* Check if there was any error (syntax or runtime) */ + bool run_ok = !jerry_value_is_error (eval_ret); + + /* Parsed source code must be freed */ + jerry_release_value (eval_ret); + + /* Cleanup engine */ + jerry_cleanup (); + + return (run_ok ? 0 : 1); +} +``` + +To compile it one can use the following command: + +```sh +$ gcc api-example-2.c -o api-example-2 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) +``` + +If everything is correct the application returns with a zero exit code: + +``` +$ ./api-example-2 +$ echo $? +``` + +## Example 3. Split JavaScript parsing and script execution + +In this example the `jerry_eval` is replaced with a more common API calls: + +- script code setup - `jerry_parse`. +- script execution - `jerry_run`. + +The `api-example-3.c` file should contain the following code: + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + bool run_ok = false; + + const jerry_char_t script[] = "var str = 'Hello, World!';"; + + /* Initialize engine */ + jerry_init (JERRY_INIT_EMPTY); /* Setup Global scope code */ jerry_value_t parsed_code = jerry_parse (NULL, 0, script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); + /* Check if there is any JS code parse error */ + if (!jerry_value_is_error (parsed_code)) + { + /* Execute the parsed source code in the Global scope */ + jerry_value_t ret_value = jerry_run (parsed_code); + + /* Check the execution return value if there is any error */ + run_ok = !jerry_value_is_error (ret_value); + + /* Returned value must be freed */ + jerry_release_value (ret_value); + } + + /* Parsed source code must be freed */ + jerry_release_value (parsed_code); + + /* Cleanup engine */ + jerry_cleanup (); + + return (run_ok ? 0 : 1); +} +``` + +To compile it one can use the following command: + +```sh +$ gcc api-example-3.c -o api-example-3 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) +``` + +If everything is correct the application returns with a zero exit code: + +``` +$ ./api-example-3 +$ echo $? +``` + +## Example 4. Adding a C method for JavaScript + +The previous examples were not that eye catching as there were no visual output by the JavaScript code +and C program. + +In this example a very simple "print" method is added which prints out a static string. +This method will be implemented in C and will be called from the JavaScript code. +For this a few extra API methods are required: + +- `jerry_get_global_object` +- `jerry_create_string` +- `jerry_set_property` +- `jerry_create_external_function` + +The `api-example-4.c` file should contain the following code: + +[doctest]: # () + +```c +#include +#include "jerryscript.h" + +static jerry_value_t +print_handler (const jerry_value_t function_object, + const jerry_value_t function_this, + const jerry_value_t arguments[], + const jerry_length_t argument_count) +{ + /* No arguments are used in this example */ + /* Print out a static string */ + printf ("Print handler was called\n"); + + /* Return an "undefined" value to the JavaScript engine */ + return jerry_create_undefined (); +} + +int +main (void) +{ + const jerry_char_t script[] = "print ();"; + const jerry_length_t script_size = sizeof (script) - 1; + + /* Initialize engine */ + jerry_init (JERRY_INIT_EMPTY); + + /* Add the "print" method for the JavaScript global object */ + { + /* Get the "global" object */ + jerry_value_t global_object = jerry_get_global_object (); + /* Create a "print" JS string */ + jerry_value_t property_name_print = jerry_create_string ((const jerry_char_t *) "print"); + /* Create a function from a native C method (this function will be called from JS) */ + jerry_value_t property_value_func = jerry_create_external_function (print_handler); + /* Add the "print" property with the function value to the "global" object */ + jerry_value_t set_result = jerry_set_property (global_object, property_name_print, property_value_func); + + /* Check if there was no error when adding the property (in this case it should never happen) */ + if (jerry_value_is_error (set_result)) { + printf ("Failed to add the 'print' property\n"); + } + + /* Release all jerry_value_t-s */ + jerry_release_value (set_result); + jerry_release_value (property_value_func); + jerry_release_value (property_name_print); + jerry_release_value (global_object); + } + + /* Setup Global scope code */ + jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS); + if (!jerry_value_is_error (parsed_code)) { /* Execute the parsed source code in the Global scope */ @@ -82,46 +291,118 @@ main (void) } ``` -Our code is more complex now, but it introduces possibilities to interact with JerryScript step-by-step: setup native objects, call JavaScript functions, etc. -## Step 3. Execution in 'eval'-mode +To compile it one can use the following command: + +```sh +$ gcc api-example-4.c -o api-example-4 $(pkg-config --cflags --libs libjerry-core libjerry-port-default libjerry-libm) +``` + +If everything is correct the application should print out the message present in the `print_handler` method: + +``` +$ ./api-example-4 +``` + +## Example 5. Passing and processing arguments for native C code + +In the previous example the `print_handler` simply wrote a static string to the standard output. +However in most cases this is not useful, ideally the method's argument(s) should be printed. + +In this example the `print_handler` is extended to convert the first +argument (which probably comes from a JavaScript source) to a JS string and prints it out to the standard output. + +New API methods used: + +- `jerry_value_to_string` +- `jerry_string_to_utf8_char_buffer` + +The `api-example-5.c` file should contain the following code: [doctest]: # () ```c +#include #include "jerryscript.h" -#include "jerryscript-ext/handler.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_1[] = "var s = 'Hello, World!';"; - const jerry_char_t script_2[] = "print (s);"; + 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); - /* Register 'print' function from the extensions */ - jerryx_handler_register_global ((const jerry_char_t *) "print", - jerryx_handler_print); + /* 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); - jerry_value_t eval_ret; + /* 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"); + } - /* Evaluate script1 */ - eval_ret = jerry_eval (script_1, - sizeof (script_1) - 1, - JERRY_PARSE_NO_OPTS); + /* 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); + } - /* Free JavaScript value, returned by eval */ - jerry_release_value (eval_ret); + /* Setup Global scope code */ + jerry_value_t parsed_code = jerry_parse (NULL, 0, script, script_size, JERRY_PARSE_NO_OPTS); - /* Evaluate script2 */ - eval_ret = jerry_eval (script_2, - sizeof (script_2) - 1, - 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); - /* Free JavaScript value, returned by eval */ - jerry_release_value (eval_ret); + /* 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 (); @@ -130,9 +411,93 @@ main (void) } ``` -This way, we execute two independent script parts in one execution environment. The first part initializes string variable, and the second outputs the variable. -## Step 4. Interaction with JavaScript environment +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]: # () @@ -143,8 +508,7 @@ This way, we execute two independent script parts in one execution environment. int main (void) { - const jerry_char_t str[] = "Hello, World!"; - const jerry_char_t script[] = "print (s);"; + const jerry_char_t script[] = "print (my_var);"; /* Initializing JavaScript environment */ jerry_init (JERRY_INIT_EMPTY); @@ -157,11 +521,16 @@ main (void) jerry_value_t global_object = jerry_get_global_object (); /* Constructing strings */ - jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "s"); - jerry_value_t prop_value = jerry_create_string (str); + 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_release_value (jerry_set_property (global_object, prop_name, prop_value)); + 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); @@ -185,16 +554,46 @@ main (void) } ``` -The sample will also output 'Hello, World!'. However, now it is not just a part of the source script, but the value, dynamically supplied to the engine. +To compile it one can use the following command: -## Step 5. Description of JerryScript value descriptors +(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. -JerryScript value can be a boolean, number, null, object, string or undefined. The value has an error flag, -that indicates whether is an error or not. Every type has an error flag not only objects. The error flag should -be cleared before the value is passed as an argument, otherwise it can lead to a type error. The error objects -created by API functions has the error flag set. +```sh +$ gcc api-example-7.c -o api-example-7 $(pkg-config --cflags --libs libjerry-core libjerry-ext libjerry-port-default libjerry-libm) +``` -The following example function will output a JavaScript value: +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") @@ -204,8 +603,20 @@ The following example function will output a JavaScript value: #include "jerryscript.h" static void -print_value (const jerry_value_t value) +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"); @@ -228,7 +639,7 @@ print_value (const jerry_value_t value) /* Float value */ else if (jerry_value_is_number (value)) { - printf ("number"); + printf ("number: %lf", jerry_get_number_value (value)); } /* String value */ else if (jerry_value_is_string (value)) @@ -249,10 +660,11 @@ print_value (const jerry_value_t value) } printf ("\n"); + jerry_release_value (value); } ``` -## Simple JavaScript shell +## Example 8: Simple JavaScript shell Now all building blocks, necessary to construct JavaScript shell, are ready. @@ -266,7 +678,9 @@ Shell operation can be described with the following loop: - print result of eval; - loop. -[doctest]: # (test="compile") +See the following `api-example-8-shell.c` file: + +[doctest]: # (test="link") ```c #include @@ -275,7 +689,67 @@ Shell operation can be described with the following loop: #include "jerryscript.h" #include "jerryscript-ext/handler.h" -void print_value (const jerry_value_t); +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)) + { + /* Determining required buffer size */ + jerry_size_t req_sz = jerry_get_string_size (value); + jerry_char_t str_buf_p[req_sz + 1]; + + jerry_string_to_char_buffer (value, str_buf_p, req_sz); + str_buf_p[req_sz] = '\0'; + + printf ("%s", (const char *) str_buf_p); + } + /* Object reference */ + else if (jerry_value_is_object (value)) + { + printf ("[JS object]"); + } + + printf ("\n"); + + jerry_release_value (value); +} int main (void) @@ -327,15 +801,9 @@ main (void) len, JERRY_PARSE_NO_OPTS); - /* If command evaluated successfully, print value, returned by eval */ - if (jerry_value_is_error (ret_val)) - { - /* Evaluated JS code thrown an exception - * and didn't handle it with try-catch-finally */ - printf ("Unhandled JS exception occurred: "); - } - + /* Print out the value */ print_value (ret_val); + jerry_release_value (ret_val); } @@ -346,11 +814,24 @@ main (void) } ``` -The application inputs commands and evaluates them, one after another. +To compile it one can use the following command: -## Step 6. Creating JS object in global context +(**Note** that the `libjerry-ext` was added **before** the `libjerry-port-default` entry for the `pkg-config` call. -In this example we demonstrate how to use native function and structures in JavaScript. +```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]: # () @@ -433,15 +914,33 @@ main (void) } ``` +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 +Hello, World ``` -## Step 7. Extending JS Objects with native functions +## Example 10. Extending JS Objects with native functions -Here we create a JS Object with `jerry_eval`, then extend it with a native function. This function shows how to get a property value from the object and how to manipulate it. +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]: # () @@ -455,9 +954,12 @@ Here we create a JS Object with `jerry_eval`, then extend it with a native funct 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_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); @@ -466,7 +968,7 @@ add_handler (const jerry_value_t func_value, /**< function object */ { /* Convert Jerry API values to double */ double x = jerry_get_number_value (x_val); - double d = jerry_get_number_value (*args_p); + double d = jerry_get_number_value (args_p[0]); /* Add the parameter to 'x' */ jerry_value_t res_val = jerry_create_number (x + d); @@ -543,14 +1045,26 @@ main (void) } ``` -The application will generate the following output: +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 ``` -## Step 8. Changing the seed of pseudorandom generated numbers +## 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. @@ -594,4 +1108,4 @@ main (void) ## Further steps -For further API description, please visit [API Reference page](https://pando-project.github.io/jerryscript/api-reference/) on [JerryScript home page](https://pando-project.github.io/jerryscript/). +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/). diff --git a/04.INTERNALS.md b/04.INTERNALS.md index 5f365d52f..7d2a46637 100644 --- a/04.INTERNALS.md +++ b/04.INTERNALS.md @@ -33,7 +33,7 @@ Expression parser is responsible for parsing JavaScript expressions. It is imple JavaScript statements are parsed by this component. It uses the [Expression parser](#expression-parser) to parse the constituent expressions. The implementation of Statement parser is located in `./jerry-core/parser/js/js-parser-statm.c`. -Function `parser_parse_source` carries out the parsing and compiling of the input EcmaScript source code. When a function appears in the source `parser_parse_source` calls `parser_parse_function` which is responsible for processing the source code of functions recursively including argument parsing and context handling. After the parsing, function `parser_post_processing` dumps the created opcodes and returns an `ecma_compiled_code_t*` that points to the compiled bytecode sequence. +Function `parser_parse_source` carries out the parsing and compiling of the input ECMAScript source code. When a function appears in the source `parser_parse_source` calls `parser_parse_function` which is responsible for processing the source code of functions recursively including argument parsing and context handling. After the parsing, function `parser_post_processing` dumps the created opcodes and returns an `ecma_compiled_code_t*` that points to the compiled bytecode sequence. The interactions between the major components shown on the following figure. @@ -43,19 +43,19 @@ The interactions between the major components shown on the following figure. This section describes the compact byte-code (CBC) representation. The key focus is reducing memory consumption of the byte-code representation without sacrificing considerable performance. Other byte-code representations often focus on performance only so inventing this representation is an original research. -CBC is a CISC like instruction set which assigns shorter instructions for frequent operations. Many instructions represent multiple atomic tasks which reduces the byte code size. This technique is basically a data compression method. +CBC is a CISC like instruction set which assigns shorter instructions for frequent operations. Many instructions represent multiple atomic tasks which reduces the bytecode size. This technique is basically a data compression method. ## Compiled Code Format -The memory layout of the compiled byte code is the following. +The memory layout of the compiled bytecode is the following. ![CBC layout]({{ site.github.url }}/img/CBC_layout.png){: class="thumbnail center-block img-responsive" } The header is a `cbc_compiled_code` structure with several fields. These fields contain the key properties of the compiled code. -The literals part is an array of ecma values. These values can contain any EcmaScript value types, e.g. strings, numbers, function and regexp templates. The number of literals is stored in the `literal_end` field of the header. +The literals part is an array of ecma values. These values can contain any ECMAScript value types, e.g. strings, numbers, functions and regexp templates. The number of literals is stored in the `literal_end` field of the header. -CBC instruction list is a sequence of byte code instructions which represents the compiled code. +CBC instruction list is a sequence of bytecode instructions which represents the compiled code. ## Byte-code Format @@ -65,7 +65,7 @@ The memory layout of a byte-code is the following: Each byte-code starts with an opcode. The opcode is one byte long for frequent and two byte long for rare instructions. The first byte of the rare instructions is always zero (`CBC_EXT_OPCODE`), and the second byte represents the extended opcode. The name of common and rare instructions start with `CBC_` and `CBC_EXT_` prefix respectively. -The maximum number of opcodes is 511, since 255 common (zero value excluded) and 256 rare instructions can be defined. Currently around 230 frequent and 120 rare instructions are available. +The maximum number of opcodes is 511, since 255 common (zero value excluded) and 256 rare instructions can be defined. Currently around 215 frequent and 70 rare instructions are available. There are three types of bytecode arguments in CBC: @@ -73,7 +73,7 @@ There are three types of bytecode arguments in CBC: * __literal argument__: An integer index which is greater or equal than zero and less than the `literal_end` field of the header. For further information see next section Literals (next). - * __relative branch__: An 1-3 byte long offset. The branch argument might also represent the end of an instruction range. For example the branch argument of `CBC_EXT_WITH_CREATE_CONTEXT` shows the end of a `with` statement. More precisely the position after the last instruction. + * __relative branch__: An 1-3 byte long offset. The branch argument might also represent the end of an instruction range. For example the branch argument of `CBC_EXT_WITH_CREATE_CONTEXT` shows the end of a `with` statement. More precisely the position after the last instruction in the with clause. Argument combinations are limited to the following seven forms: @@ -147,11 +147,11 @@ Byte-codes of this category serve for placing objects onto the stack. As there a
-| byte-code | description | -| CBC_PUSH_LITERAL | Pushes the value of the given literal argument. | -| CBC_PUSH_TWO_LITERALS | Pushes the value of the given two literal arguments. | -| CBC_PUSH_UNDEFINED | Pushes an undefined value. | -| CBC_PUSH_TRUE | Pushes a logical true. | +| byte-code | description | +| CBC_PUSH_LITERAL | Pushes the value of the given literal argument. | +| CBC_PUSH_TWO_LITERALS | Pushes the values of the given two literal arguments. | +| CBC_PUSH_UNDEFINED | Pushes an undefined value. | +| CBC_PUSH_TRUE | Pushes a logical true. | | CBC_PUSH_PROP_LITERAL | Pushes a property whose base object is popped from the stack, and the property name is passed as a literal argument. |
@@ -202,7 +202,7 @@ Branch byte-codes are used to perform conditional and unconditional jumps in the | CBC_JUMP_BACKWARD | Jumps backward by the 1 byte long relative offset argument. | | CBC_JUMP_BACKWARD_2 | Jumps backward by the 2 byte long relative offset argument. | | CBC_JUMP_BACKWARD_3 | Jumps backward by the 3 byte long relative offset argument. | -| CBC_BRANCH_IF_TRUE_FORWARD | Jumps if the value on the top of the stack is true by the 1 byte long relative offset argument. | +| CBC_BRANCH_IF_TRUE_FORWARD | Jumps forward if the value on the top of the stack is true by the 1 byte long relative offset argument. | @@ -225,12 +225,14 @@ ECMA component of the engine is responsible for the following notions: ## Data Representation -The major structure for data representation is `ECMA_value`. The lower two bits of this structure encode value tag, which determines the type of the value: +The major structure for data representation is `ECMA_value`. The lower three bits of this structure encode value tag, which determines the type of the value: * simple * number * string * object +* symbol +* error ![ECMA value representation]({{ site.github.url }}/img/ecma_value.png){: class="thumbnail center-block img-responsive" } @@ -259,7 +261,7 @@ system. These "uncompressed pointers" increases the memory consumption by around There are two possible representation of numbers according to standard IEEE 754: The default is 8-byte (double), -but the engine supports the 4-byte (single precision) representation by setting CONFIG_ECMA_NUMBER_TYPE as well. +but the engine supports the 4-byte (single precision) representation by setting JERRY_NUMBER_TYPE_FLOAT64 to 0 as well. ![Number]({{ site.github.url }}/img/number.png){: class="thumbnail center-block img-responsive" } @@ -281,7 +283,6 @@ The objects are represented as following structure: * Reference counter - number of hard (non-property) references * Next object pointer for the garbage collector - * GC's visited flag * type (function object, lexical environment, etc.) ### Properties of Objects @@ -329,7 +330,7 @@ Collections are array-like data structures, which are optimized to save memory. ### Exception Handling -In order to implement a sense of exception handling, the return values of JerryScript functions are able to indicate their faulty or "exceptional" operation. The return values are actually ECMA values (see section [Data Representation](#data-representation)) in which the error bit is set if an erroneous operation is occurred. +In order to implement a sense of exception handling, the return values of JerryScript functions are able to indicate their faulty or "exceptional" operation. The return values are ECMA values (see section [Data Representation](#data-representation)) and if an erroneous operation occurred the ECMA_VALUE_ERROR simple value is returned. ### Value Management and Ownership diff --git a/05.PORT-API.md b/05.PORT-API.md index 4468da9e5..0b42befe4 100644 --- a/05.PORT-API.md +++ b/05.PORT-API.md @@ -75,8 +75,8 @@ typedef enum * vfprintf(logfile), or both, depending on log level. * * Note: - * This port function is called by jerry-core when JERRY_ENABLE_LOGGING is - * defined. It is also common practice though to use this function in + * 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, ...); @@ -95,7 +95,8 @@ void jerry_port_print_char (char c); ### ES2015 Module system helper functions -The import statement requires two specific functions for opening and closing files (the modules) port specific. +The module system requires two specific functions for opening and closing files. +It also requires a platform specific way of normalizing file paths. ```c /** @@ -118,6 +119,23 @@ 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 */ ``` ## Date @@ -139,7 +157,7 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */ * * Note: * This port function is called by jerry-core when - * CONFIG_DISABLE_DATE_BUILTIN is _not_ defined. Otherwise this function is + * 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 @@ -161,7 +179,7 @@ double jerry_port_get_local_time_zone_adjustment (double unix_ms, bool is_utc); * * Note: * This port function is called by jerry-core when - * CONFIG_DISABLE_DATE_BUILTIN is _not_ defined. It is also common practice + * 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. * @@ -183,7 +201,7 @@ simultaneously. * * Note: * This port function is called by jerry-core when - * JERRY_ENABLE_EXTERNAL_CONTEXT is defined. Otherwise this function is not + * JERRY_EXTERNAL_CONTEXT is enabled. Otherwise this function is not * used. * * @return the pointer to the engine context. @@ -198,8 +216,8 @@ struct jerry_context_t *jerry_port_get_current_context (void); * Makes the process sleep for a given time. * * Note: - * This port function is called by jerry-core when JERRY_DEBUGGER is - * defined. Otherwise this function is not used. + * 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. */ @@ -345,7 +363,7 @@ jerry_port_get_current_context (void) #include #endif /* HAVE_TIME_H */ -#ifdef JERRY_DEBUGGER +#if defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) void jerry_port_sleep (uint32_t sleep_time) { #ifdef HAVE_TIME_H @@ -359,5 +377,5 @@ void jerry_port_sleep (uint32_t sleep_time) #endif /* HAVE_TIME_H */ (void) sleep_time; } /* jerry_port_sleep */ -#endif /* JERRY_DEBUGGER */ +#endif /* defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) */ ``` diff --git a/10.EXT-REFERENCE-HANDLER.md b/10.EXT-REFERENCE-HANDLER.md index efee4c5e9..d46961cc5 100644 --- a/10.EXT-REFERENCE-HANDLER.md +++ b/10.EXT-REFERENCE-HANDLER.md @@ -8,6 +8,421 @@ permalink: /ext-reference-handler/ * toc {:toc} +# Common methods to handle properties + +The `jerryscript-ext/handler.h` header defines a set of convenience methods +which makes the property access a bit straightforward. + +## jerryx_set_property_str + +**Summary** + +Set a property on a target object with a given name. + +*Note*: +- The property name must be a zero terminated UTF-8 string. +- There should be no '\0' (NULL) character in the name excluding the string terminator. +- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it + is no longer needed. + + +**Prototype** + +```c +jerry_value_t +jerryx_set_property_str (const jerry_value_t target_object, + const char *name, + const jerry_value_t value); +``` + +- `target_object` - the object where the property should be set +- `name` - name of the property +- `value` - property value to be set +- return value + - JS true value, if success + - thrown error, if there was a problem setting the property + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" +#include "jerryscript-ext/handler.h" + +int +main (int argc, char **argv) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t global = jerry_get_global_object (); + + jerry_value_t value = jerry_create_number (3.3); + jerry_value_t result = jerryx_set_property_str (global, "value", value); + if (jerry_value_is_error (result)) + { + /* The error type/reason can be extracted via the `jerry_get_value_from_error` method */ + printf ("Error during property configuration\r\n"); + } + + jerry_release_value (result); + jerry_release_value (value); + jerry_release_value (global); + jerry_cleanup(); + + return 0; +} +``` + +## jerryx_get_property_str + +**Summary** + +Get the value of a property from the specified object with the given name. + +*Notes*: +- The property name must be a zero terminated UTF-8 string. +- There should be no '\0' (NULL) character in the name excluding the string terminator. +- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it + is no longer needed. + + +**Prototype** + +``` +jerry_value_t +jerryx_get_property_str (const jerry_value_t target_object, + const char *name); +``` + +- `target_object` - object on which the property name is accessed +- `name` - property name as an UTF-8 `char*` +- return value + - value of property, if success + - thrown error, if there was a problem accessing the property + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" +#include "jerryscript-ext/handler.h" + +int +main (int argc, char **argv) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t global = jerry_get_global_object (); + + jerry_value_t math_object = jerryx_get_property_str (global, "Math"); + + /* use math_object */ + + jerry_release_value (math_object); + jerry_release_value (global); + jerry_cleanup(); + + return 0; +} +``` + +## jerryx_has_property_str + +**Summary** + +Check if a property exists on an object. + +*Notes*: +- The operation performed is the same as what the `jerry_has_property` method. +- The property name must be a zero terminated UTF-8 string. +- There should be no '\0' (NULL) character in the name excluding the string terminator. + + +**Prototype** + +``` +bool +jerryx_has_property_str (const jerry_value_t target_object, + const char *name); +``` + +- `target_object` - object on which the property name is accessed +- `name` - property name as an UTF-8 `char*` +- return value + - true, if the given property name exsits on the object + - false, if there is no such property name or there was an error accessing the property + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" +#include "jerryscript-ext/handler.h" + +int +main (int argc, char **argv) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t global = jerry_get_global_object (); + + bool have_math = jerryx_has_property_str (global, "Math"); + + jerry_release_value (global); + jerry_cleanup(); + + return have_math ? 0 : 1; +} +``` + +# Utility to register multiple properties in bulk + +In some cases it is useful to register multiple properties for a given object +for this the following utility structures and methods are provided. + +## jerryx_property_entry + +**Summary** + +Structure to define an array of properties with `name` and `value` fields which +can be registered to a target object. + +The engine must be initialied before specifying the `jerry_value_t` in the struct. + + +**Prototype** + +```c +typedef struct { + const char *name; + jerry_value_t value; +} jerryx_function_list_entry; +``` + +**See also** + +- [jerryx_set_properties](#jerryx_set_properties) + + +## jerryx_register_result + +**Summary** + +Structure returned as the result of the [jerryx_set_properties](#jerryx_set_properties) operation. +The `result` field will either be a JavaScript undefined value or an error object. +In every case the `registered` field is used to indicated the number of +successfully registered methods. + +This must be passed for the [jerryx_release_property_entry](#jerryx_release_property_entry) method +after the property registration. + +If any error occured during the property registration the `result` field of the structure +must be manually released after processing the error value. + +**Prototype** + +```c +typedef struct { + jerry_value_t result; + uint32_t registered; +} jerryx_register_result; +``` + +**See also** + +- [jerryx_set_properties](#jerryx_set_properties) +- [jerryx_release_property_entry](#jerryx_release_property_entry) + + +## jerryx_set_properties + +**Summary** + +Set multiple properties on a target object. + +The properties are an array of (name, jerry_value_t) pairs and +this list must end with a (NULL, 0) entry. + +Important notes: +* Each property value in the input array is released after a successful property registration. +* The method [jerryx_release_property_entry](#jerryx_release_property_entry) must be called if there is any failed registration + to release the values in the entries array. + It is safe to call this cleanup method in every case not just in case of failure. +* If the error value is reported via the result it must be freed manually. + +**Prototype** + +```c +jerryx_register_result +jerryx_set_properties (const jerry_value_t target_object, + const jerryx_property_entry entries[]); +``` + +- `target_object` - object on which the entries will be set. +- `entries` - array of (name, jerry_value_t) pairs. +- return a [jerryx_register_result](#jerryx_register_result). + - if everything is ok, the struct's `result` field is set to a JS undefined value. + - otherwise the `result` field is an error object indicating the problem. + - in every case the `registered` field contains the number of successfully registered properties. + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" +#include "jerryscript-ext/handler.h" + +static jerry_value_t +handler (const jerry_value_t function_obj, + const jerry_value_t this_val, + const jerry_value_t args_p[], + const jerry_length_t args_cnt) +{ + printf ("native handler called!\n"); + + return jerry_create_boolean (true); +} + +int +main (int argc, char **argv) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerryx_property_entry methods[] = + { + { "demo", jerry_create_external_function (handler) }, + { NULL, 0 }, + }; + + jerry_value_t global = jerry_get_global_object (); + jerryx_register_result reg = jerryx_set_properties (global, methods); + /* if `reg.result` is undefined all methods are registered */ + if (jerry_value_is_error (reg.result)) + { + printf ("Only registered %d properties\r\n", reg.registered); + /* clean up not registered property values */ + jerryx_release_property_entry (methods, reg); + + /* clean up the error */ + jerry_release_value (reg.result); + } + + jerry_release_value (global); + + jerry_cleanup(); + + return 0; +} +``` + +**Convenience macros** + +To make property registration convenient, there are a set of macros to use +when setting a property entry: + +* `JERRYX_PROPERTY_NUMBER(NAME, NUMBER)` - creates a number entry. +* `JERRYX_PROPERTY_STRING(NAME, STR)` - creates an UTF-8 string entry. This string must be zero terminated. +* `JERRYX_PROPERTY_STRING_SZ(NAME, STR, SIZE)` - creates an UTF-8 string entry using only `SIZE` bytes from the string. +* `JERRYX_PROPERTY_BOOLEAN(NAME, VALUE)` - creates a boolean entry. +* `JERRYX_PROPERTY_FUNCTION(NAME, NATIVE)` - creates a native C function entry. +* `JERRYX_PROPERTY_UNDEFINED(NAME)` - creates an undefined property entry. +* `JERRYX_PROPERTY_LIST_END()` - indicates the end of the property list. + +**Example usage of Convenience macros** + +[doctest]: # () + +```c +#include "jerryscript.h" +#include "jerryscript-ext/handler.h" + +static jerry_value_t +handler (const jerry_value_t function_obj, + const jerry_value_t this_val, + const jerry_value_t args_p[], + const jerry_length_t args_cnt) +{ + printf ("native handler called!\n"); + + return jerry_create_boolean (true); +} + +int +main (int argc, char **argv) +{ + jerry_init (JERRY_INIT_EMPTY); + + /** + * Create a array of properties to be registered. + * This must be done after initializing the engine as creating `jerry_value_t` + * elements are invalid before `jerry_init`. + */ + jerryx_property_entry methods[] = + { + JERRYX_PROPERTY_FUNCTION ("demo", handler), + JERRYX_PROPERTY_NUMBER ("test_num", 2.3), + JERRYX_PROPERTY_UNDEFINED ("this_is_undefined"), + JERRYX_PROPERTY_LIST_END(), + }; + + jerry_value_t global = jerry_get_global_object (); + jerryx_register_result reg = jerryx_set_properties (global, methods); + /* if `reg.result` is undefined all methods are registered */ + if (jerry_value_is_error (reg.result)) + { + printf ("Only registered %d properties\r\n", reg.registered); + /* clean up not registered property values */ + jerryx_release_property_entry (methods, reg); + + /* clean up the error */ + jerry_release_value (reg.result); + } + + jerry_release_value (global); + + jerry_cleanup(); + + return 0; +} +``` + + +**See also** + +- [jerryx_property_entry](#jerryx_property_entry) +- [jerryx_release_property_entry](#jerryx_release_property_entry) +- [jerryx_register_result](#jerryx_register_result) + +## jerryx_release_property_entry + +**Summary** + +Release all `jerry_value_t` in a `jerryx_property_entry` array based on a previous [jerryx_set_properties](#jerryx_set_properties) call +and also the error value (if any) in the `jerryx_register_result` structure. +In case of a successful registration it is safe to call this method. + +After the method call the `ęntries` array should not be used as all values are released. + +**Prototype** + +``` +void +jerryx_release_property_entry (const jerryx_property_entry entries[], + const jerryx_register_result register_result); +``` + +- `entires` - array of [jerryx_property_entry](#jerryx_property_entry). +- `register_result` - result of a previous [jerryx_set_properties](#jerryx_set_properties) call. + +**Example** + +For example usage see [jerryx_set_properties](#jerryx_set_properties). + + # Common external function handlers ## jerryx_handler_assert_fatal @@ -79,7 +494,7 @@ An alias to `jerryx_handler_assert_fatal`. **Summary** Expose garbage collector to scripts. If the first argument of the function -is logical true, it performs a high severity gc. Otherwise a low severity +is logical true, it performs a high pressure gc. Otherwise a low pressure gc is performed, which is also the default if no parameters passed. **Prototype** diff --git a/14.EXT-REFERENCE-HANDLE-SCOPE.md b/14.EXT-REFERENCE-HANDLE-SCOPE.md index 34977c0ac..6ebfc8bef 100644 --- a/14.EXT-REFERENCE-HANDLE-SCOPE.md +++ b/14.EXT-REFERENCE-HANDLE-SCOPE.md @@ -51,7 +51,7 @@ main (void) jerry_init (JERRY_INIT_EMPTY); test_handle_scope_val (); - jerry_gc (JERRY_GC_SEVERITY_LOW); + jerry_gc (JERRY_GC_PRESSURE_LOW); jerry_cleanup (); } /* main */ @@ -103,7 +103,7 @@ main (void) jerry_init (JERRY_INIT_EMPTY); test_handle_scope_val (); - jerry_gc (JERRY_GC_SEVERITY_LOW); + jerry_gc (JERRY_GC_PRESSURE_LOW); jerry_cleanup (); } /* main */ diff --git a/15.MODULE-SYSTEM.md b/15.MODULE-SYSTEM.md index a680626a0..1647436d5 100644 --- a/15.MODULE-SYSTEM.md +++ b/15.MODULE-SYSTEM.md @@ -10,35 +10,49 @@ permalink: /module-system/ # ES6 module support for JerryScript -The module system allows users to write import and export statements in scripts. Therefore the logic of the application could be separated in custom modules. +The module system allows users to write import and export statements in scripts, which can be used to separate the logic of the application into custom modules. The standard's relevant part can be found [here](https://www.ecma-international.org/ecma-262/6.0/#sec-modules). ## General -If the main script contains import statements, then Jerry opens and runs the appropriate scripts before the main script (as the standard says). The script's and the module's extension is `.js`, custom extensions are unnecessary. +If a script contains import statements, then JerryScript will open and evaluate the the referenced modules before the main script runs, resolving and creating bindings for the referenced identifiers in the process. +It is not necessary to use any specific filename extensions for modules, JerryScript will try to open the given file paths as they are, but will try to normalize them before doing so. The exact normalization process is dependant on the port implementation provided. It is the user's responsibility to verify that the given files are valid EcmaScript modules. main.js ```js -import { secret_number } from "./module.js" +import { exported_value } from "./module.js" -print (secret_number); +print (exported_value); ``` module.js ```js -var secret_number = 42; +var exported_value = 42; -export secret_number; +export exported_value; ``` ## Supported features -* import variable or function - * add alias name to the imported variable (function) -* export variable or function - * add alias name to the exported variable (function) +* exporting identifiers from the module's lexical environment + * specifying export names for the exported values +* importing exported identifiers from a module + * specifying local binding names for the imported values +* module namespace imports + * `import * as module from 'module.js` +* indirect export statements + * `export {variable} from 'module.js'` +* star export statements + * `export * from 'module.js'` +* importing a module for side-effects + * `import 'module.js'` +* default import and export statements + * `export default local_identifier` + * `import def from 'module.js'` +* anonymous default exports + * `export default function () {}` ### Example @@ -79,22 +93,20 @@ export function getFeatureDetails() { } ``` -## Unsupported features +### Module namespace import statements -* **snapshot** -* errors from the imported scripts -* redirection ( `export { a, b } from 'module.js'` ) -* default import and export - * `import b from 'module.js'` - * `export default b`, -* whole module import statements - * `import * from 'module.js` - * `import { * as module } from 'module.js` -* object freezing ( `Object.freeze (this)` ) +A module namespace object can be imported. In this case the local binding will contain an object holding the exported values of the module, including local exports and all indirect exports. Ambiguous exported names are exluded from the namespace object. -### Redirection +```js +import * as module from './module.js'; -An export statement can import variables from a custom module and export it directly from the current script. This statement is called redirection. In this case the `export { b } from 'module2.js'` works as the `b` was imported before then exported as a local variable. +print(">> Engine: " + module.engine); +print(">> Version: " + module.version); +``` + +### Indirect export statements + +An export statement can transitively export variables from another module, either via named indirect exports or a star export statement. In this case the resolving process will follow the chain until it reaches a module containing a local binding for that export name. If there are multiple modules which satisfy the export, that means the export is ambiguous, and will result in a SyntaxError. ```js import { a, b } from 'module.js' @@ -115,28 +127,42 @@ export var b = 40; ### Default imports and exports -TODO: This part is going to be written in the next part of the patch. - -### Import the whole module - -The whole module can be imported. In this case the `m` object would contain the exported parts of the module. If the import is not aliased, the `global object` would contain the exports. +Each module can optionally provide a single default export by using the `export default` statement. Default exports can either reference identifiers in the module's lexical environment, or be an anonymous default export, in which case they will only be accessible by an importing script. ```js -import { * as m } from "./module.js" +import defaultExport, { b as c } from 'module.js' -print (m.secret_number); -print (m.getPrettifiedNumber()); -print (m.api.version); +print (defaultExport); // 2 +print (c ()); // 42 ``` ```js // module.js -var secret_number = 42; -export secret_number; - -export function getPrettifiedNumber() { - return "*** " + secret_number + " ***"; +export default 2; +export function b () { + return 42; } - -export { ble as api } from "./ble.js"; ``` + +### Importing modules for side-effects + +Evaluate a module without importing anything. Any errors encountered in the module will be propagated. + +```js +import 'module.js' // > module.js +// "> module.js" is printed +b (); // (ReferenceError) b is not defined +``` + +```js +// module.js +export function b () { + print ("> module.js"); + return 42; +} +b (); +``` + +## Unsupported features + +* **snapshot** diff --git a/16.MIGRATION-GUIDE.md b/16.MIGRATION-GUIDE.md new file mode 100644 index 000000000..5a76334a0 --- /dev/null +++ b/16.MIGRATION-GUIDE.md @@ -0,0 +1,782 @@ +--- +layout: page +title: Migration Guide +category: documents +permalink: /migration-guide/ +--- + +* toc +{:toc} + +# Migration guide + +This guide intends to describe the major changes between the JerryScript 1.0 and 2.0 versions. +In addtion it is designed to provide a guide on how to modify the 1.0 version code to a +2.0 compliant code. + +During the development it was important to minimize the changes in the API functions and types. +Each API method removal or chang is described below providing a ***before*** and ***after*** +code example. +For more information on the current API methods please check the [API reference](02.API-REFERENCE.md) document. + +# Short list of removed/renamed headers, types, functions, and macros + +***Removed legacy headers*** + +- `jerry-internal.h` + +***Renamed headers*** + +- `jerry-api.h` to `jerryscript.h` +- `jerry-port.h` to `jerryscript-port.h` + +***Removed API types*** + +- `jerry_char_ptr_t` usage replaced with `jerry_char_t *` +- `jerry_object_free_callback_t` replaced by `jerry_object_native_free_callback_t` + +***Removed API methods*** + +- `jerry_get_memory_limits` +- `jerry_get_object_native_handle` replaced by `jerry_get_object_native_pointer` +- `jerry_set_object_native_handle` replaced by `jerry_set_object_native_pointer` +- `jerry_value_set_abort_flag` replaced by `jerry_create_abort_from_value` +- `jerry_value_has_abort_flag` replaced by `jerry_value_is_abort` +- `jerry_value_set_error_flag` replaced by `jerry_create_error_from_value` +- `jerry_value_has_error_flag` replaced by `jerry_value_is_error` +- `jerry_value_clear_error_flag` replaced by `jerry_get_value_from_error` +- `jerry_get_value_without_error_flag` replaced by `jerry_get_value_from_error` +- `jerry_parse_and_save_snapshot` replaced by `jerry_generate_snapshot` +- `jerry_parse_and_save_function_snapshot` replaced by `jerry_generate_function_snapshot` + + +***Removed unused configuration macros*** + +- `CONFIG_MEM_DATA_LIMIT_MINUS_HEAP_SIZE` +- `CONFIG_MEM_STACK_LIMIT` +- `CONFIG_VM_STACK_FRAME_INLINED_VALUES_NUMBER` +- `CONFIG_ECMA_GLOBAL_ENVIRONMENT_DECLARATIVE` +- All `CONFIG_..` macros have been renamed to use the `JERRY_` prefix format. + + +# Modified API functions + +## Error manipulating functions + +The most important changes in the API are releated to error handling and manipulation. + +### jerry_value_set_abort_flag + +This function was replaced with [`jerry_create_abort_from_value`](02.API-REFERENCE.md#jerry_create_abort_from_value). +Take note of the second argument of the new `jerry_create_abort_from_value` function which controls if the +first argument should be usable after the call or not. + +**Before** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_set_abort_flag (&value); + + jerry_release_value (value); +} +``` + +**After** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_t abort = jerry_create_abort_from_value (value, true); + // using the 'value' variable after release is invalid + + jerry_release_value (abort); +} +``` + +- OR + +```c +{ + jerry_value_t value; + ... // create or acquire value + + jerry_value_t abort = jerry_create_abort_from_value (value, false); + // both 'abort' and 'value' can be used and must be released when they are no longer needed + + jerry_release_value (abort); + jerry_release_value (value); +} +``` + +### jerry_value_has_abort_flag + +This function was renamed to [`jerry_value_is_abort`](02.API-REFERENCE.md#jerry_value_is_abort). + +**Before** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + if (jerry_value_has_abort_flag (value)) + { + // ... + } + + jerry_release_value (value); +} +``` + +**After** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + if (jerry_value_is_abort (value)) + { + // ... + } + + jerry_release_value (value); +} +``` + +### jerry_value_set_error_flag + +This function was replaced with [`jerry_create_error_from_value`](02.API-REFERENCE.md#jerry_create_error_from_value). +Take note of the second argument of the new `jerry_create_error_from_value` function which controls if the +first argument should be usable after the call or not. + +**Before** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_set_error_flag (&value); + + jerry_release_value (value); +} +``` + +**After** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_t error = jerry_create_error_from_value (value, true); + // using the 'value' variable after release is invalid + + jerry_release_value (error); +} +``` + +- OR + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_t error = jerry_create_error_from_value (value, false); + // both 'error' and 'value' can be used and must be released when they are no longer needed + + jerry_release_value (error); + jerry_release_value (value); +} +``` + +### jerry_value_has_error_flag + +This function was renamed to [`jerry_value_is_error`](02.API-REFERENCE.md#jerry_value_is_error). + +**Before** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + if (jerry_value_has_error_flag (value)) + { + // ... + } + + jerry_release_value (value); +} +``` + +**After** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + if (jerry_value_is_error (value)) + { + // ... + } + + jerry_release_value (value); +} +``` + +### jerry_value_clear_error_flag AND jerry_get_value_without_error_flag + +These functions were merged into [`jerry_get_value_from_error`](02.API-REFERENCE.md#jerry_get_value_from_error). +Please note the second argument of the new function which controls if the first argument passed should be released +or not. + +**Before** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_set_error_flag (&value); + jerry_value_clear_error_flag (&value); + // or + jerry_value_t real_value = jerry_get_value_without_error_flag (value); + + jerry_release_value (value); + jerry_release_value (real_value); +} +``` + +**After** + +```c +{ + jerry_value_t value; + // create or acquire value + // ... + + jerry_value_t error = jerry_create_error_from_value (value, true); + + jerry_value_t real_value = jerry_get_value_from_error (error, true); + + jerry_release_value (real_value); +} +``` + +## Other functions changed + +### jerry_register_magic_strings + +In case of the `jerry_register_magic_strings` function the change is that +the first argument's base type `jerry_char_ptr_t` was changed to `jerry_char_t*`. +For more details see: [`jerry_register_magic_strings`](02.API-REFERENCE.md#jerry_register_magic_strings). + +In the following code parts please take note of the type used for the `magic_string_items` array. + +**Before** + +```c +{ + // must be static, because 'jerry_register_magic_strings' does not copy + // the items must be sorted by size at first, then lexicographically + static const jerry_char_ptr_t magic_string_items[] = { + (const jerry_char_ptr_t) "magicstring1", + (const jerry_char_ptr_t) "magicstring2", + (const jerry_char_ptr_t) "magicstring3" + }; + uint32_t num_magic_string_items = (uint32_t) (sizeof (magic_string_items) / sizeof (jerry_char_ptr_t)); + + // must be static, because 'jerry_register_magic_strings' does not copy + static const jerry_length_t magic_string_lengths[] = { 12, 12, 12 }; + jerry_register_magic_strings (magic_string_items, num_magic_string_items, magic_string_lengths); +} +``` + +**After** + +```c +{ + // must be static, because 'jerry_register_magic_strings' does not copy + // the items must be sorted by size at first, then lexicographically + static const jerry_char_t *magic_string_items[] = { + (const jerry_char_t *) "magicstring1", + (const jerry_char_t *) "magicstring2", + (const jerry_char_t *) "magicstring3" + }; + uint32_t num_magic_string_items = (uint32_t) (sizeof (magic_string_items) / sizeof (jerry_char_t *)); + + // must be static, because 'jerry_register_magic_strings' does not copy + static const jerry_length_t magic_string_lengths[] = { 12, 12, 12 }; + jerry_register_magic_strings (magic_string_items, num_magic_string_items, magic_string_lengths); +} +``` + +## Snapshot generating API + +### jerry_parse_and_save_snapshot + +This function was replaced with [`jerry_generate_snapshot`](02.API-REFERENCE.md#jerry_generate_snapshot). +The function returns an error object if there was any problem during snapshot generation and +if there was no problem the return value is a number value containing the snapshot size in bytes. + +**Before** + +```c +{ + static uint32_t global_mode_snapshot_buffer[256]; + const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();"; + + size_t global_mode_snapshot_size = + jerry_parse_and_save_snapshot (code_to_snapshot_p, + strlen ((const char *) code_to_snapshot_p), + true, + false, + global_mode_snapshot_buffer, + sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + // use "global_mode_snapshot_buffer" +} +``` + +**After** + +```c +{ + static uint32_t global_mode_snapshot_buffer[256]; + const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();"; + + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + code_to_snapshot_p, + strlen ((const char *) code_to_snapshot_p), + global_mode_snapshot_buffer, + sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + if (jerry_value_is_error (generate_result)) + { + // There was a problem during snapshot generation, for example there is a SyntaxError. + // Use the "generate_result" to check the error. + } + else + { + size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); + // use "global_mode_snapshot_buffer" + } + jerry_release_value (generate_result); +} +``` + +### jerry_parse_and_save_function_snapshot + +This function was replaced with [`jerry_generate_function_snapshot`](02.API-REFERENCE.md#jerry_parse_and_save_function_snapshot). +The function returns an error object if there was any problem during snapshot generation and +if there was no problem the return value is a number value containing the snapshot size in bytes. + +**Before** + +```c +{ + static uint32_t func_snapshot_buffer[1024]; + + const jerry_char_t *args_p = (const jerry_char_t *) "a, b"; + const jerry_char_t *src_p = (const jerry_char_t *) "return a + b;"; + + size_t func_snapshot_size = + jerry_parse_and_save_function_snapshot (src_p, + strlen ((const char *) src_p), + args_p, + strlen ((const char *) args_p), + false, + func_snapshot_buffer, + sizeof (func_snapshot_buffer) / sizeof (uint32_t)); + // check "function_snapshot_size" and use "func_snapshot_buffer" +} +``` + +**After** + +```c +{ + static uint32_t func_snapshot_buffer[1024]; + + const jerry_char_t *args_p = (const jerry_char_t *) "a, b"; + const jerry_char_t *src_p = (const jerry_char_t *) "return a + b;"; + + jerry_value_t generate_result; + generate_result = jerry_generate_function_snapshot (NULL, + 0, + src_p, + strlen ((const char *) src_p), + args_p, + strlen ((const char *) args_p), + 0, + func_snapshot_buffer, + sizeof (func_snapshot_buffer) / sizeof (uint32_t)); + if (jerry_value_is_error (generate_result)) + { + // There was a problem during snapshot generation, for example there is a SyntaxError. + // Use the "generate_result" to check the error. + } + else + { + size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); + // use "func_snapshot_buffer" + } + + jerry_release_value (generate_result) +} +``` + +## Garbage collection + +### jerry_gc + +The [`jerry_gc`](02.API-REFERENCE.md#jerry_gc) function was modified to handle an argument which represents the pressure for the garbage collector. +For more information checkout the [`jerry_gc_mode_t`](02.API-REFERENCE.md#jerry_gc_mode_t) reference. + +**Before** + +```c +{ + jerry_gc (); +} +``` + +**After** + +```c +{ + jerry_gc (JERRY_GC_PRESSURE_LOW); +} +``` + +## jerry_eval + +The third argument of [`jerry_eval`](02.API-REFERENCE.md#jerry_eval) has been changed +from `bool` to [`jerry_parse_opts_t`](02.API-REFERENCE.md#jerry_parse_opts_t). + +**Before** + +```c +const jerry_char_t *str_to_eval = (const jerry_char_t *) "1 + 1"; +jerry_value_t ret_val = jerry_eval (str_to_eval, + strlen ((const char *) str_to_eval), + false); +``` + +**After** + +```c +const jerry_char_t *str_to_eval = (const jerry_char_t *) "1 + 1"; +jerry_value_t ret_val = jerry_eval (str_to_eval, + strlen ((const char *) str_to_eval), + JERRY_PARSE_NO_OPTS); +``` + +## Port API + +### jerry_port_get_time_zone + +The port API of handling timezones has been changed. The previous interface did not +allow timezones to be handled correctly, even if the host system was up to the task. +Check [the related issue](https://github.com/jerryscript-project/jerryscript/issues/1661) +for more details. + +The new port API function name is [jerry_port_get_local_time_zone_adjustment](05.PORT-API.md#date-1]. + +Below is the default implementations for both versions: + +**Before** + +```c +bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p) +{ + struct timeval tv; + struct timezone tz; + + /* gettimeofday may not fill tz, so zero-initializing */ + tz.tz_minuteswest = 0; + tz.tz_dsttime = 0; + + if (gettimeofday (&tv, &tz) != 0) + { + return false; + } + + tz_p->offset = tz.tz_minuteswest; + tz_p->daylight_saving_time = tz.tz_dsttime > 0 ? 1 : 0; + + return true; +} /* jerry_port_get_time_zone */ +``` + +**After** + +```c +double jerry_port_get_local_time_zone_adjustment (double unix_ms, + bool is_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 */ +``` + +## Native pointers + +The assignment of native pointers (previously called handles) have been changed +since v1.0. In the previous version only one native pointer could be assigned to +a `jerry_value_t`. Now it is allowed to register multiple native infos, which +can be accessed with the corresponding +[`jerry_object_native_info_t`](02.API-REFERENCE.md#jerry_object_native_info_t). +The old functions were removed and replaced by new ones. + +- `jerry_object_free_callback_t` callback type is replaced by `jerry_object_native_info_t` +- `jerry_get_object_native_handle` is replaced by [`jerry_get_object_native_pointer`](02.API-REFERENCE.md#jerry_get_object_native_pointer) +- `jerry_set_object_native_handle` is replaced by [`jerry_set_object_native_pointer`](02.API-REFERENCE.md#jerry_set_object_native_pointer) + +**Before** + +```c +struct +{ + int data; +} my_info; + +static void +handler_construct_freecb (uintptr_t native_p) +{ + // Invoked when the JS object is released and the + // native data should be freed. + + struct my_info *info = (struct my_info *) native_p; + free (info); +} + +void +demo (void) +{ + jerry_value_t this_val; + // create or acquire this_val + // ... + + struct my_info *info = (struct my_info *) malloc (sizeof (struct my_info)); + info->data = 11; + + // setting the native handle + jerry_set_object_native_handle (this_val, + (uintptr_t) info, + handler_construct_freecb); + // ... + // reading back the native handle + uintptr_t ptr = (uintptr_t) NULL; + bool is_ok = jerry_get_object_native_handle (this_val, &ptr); + if (is_ok) + { + struct my_info *obj_info = (struct my_info *) ptr; + // use "obj_info" + } +} +``` + + +**After** + +```c +struct +{ + int data; +} my_info; + +static void +handler_construct_freecb (void *native_p) +{ + // Invoked when the JS object is released and the + // native data should be freed. + + struct my_info *info = (struct my_info *) native_p; + free (info); +} + +static const jerry_object_native_info_t my_info_type_info = +{ + .free_cb = handler_construct_freecb +}; + +void +demo (void) +{ + jerry_value_t this_val; + // create or acquire this_val + // ... + + struct my_info *info = (struct my_info *) malloc (sizeof (struct my_info)); + info->data = 11; + + // setting the native handle + jerry_set_object_native_pointer (this_val, + info, + &my_info_type_info); + // ... + // reading back the native handle pointed by the "my_info_type_info" variable + void *ptr = NULL; + bool has_p = jerry_get_object_native_pointer (this_val, &ptr, &my_info_type_info); + if (has_p) + { + struct my_info *obj_info = (struct my_info *) ptr; + // use "obj_info" + } +} +``` + +# New API functions + +In this section the new API functions are listed. + +## Built-in objects + +***ArrayBuffer*** + +- [`jerry_create_arraybuffer`](02.API-REFERENCE.md#jerry_create_arraybuffer) +- [`jerry_create_arraybuffer_external`](02.API-REFERENCE.md#jerry_create_arraybuffer_external) +- [`jerry_get_arraybuffer_pointer`](02.API-REFERENCE.md#jerry_get_arraybuffer_pointer) + +***DataView*** + +- [`jerry_create_dataview`](02.API-REFERENCE.md#jerry_create_dataview) +- [`jerry_value_is_dataview`](02.API-REFERENCE.md#jerry_value_is_dataview) +- [`jerry_get_dataview_buffer`](02.API-REFERENCE.md#jerry_get_dataview_buffer) + +***JSON*** + +- [`jerry_json_parse`](02.API-REFERENCE.md#jerry_json_parse) +- [`jerry_json_stringify`](02.API-REFERENCE.md#jerry_json_stringify) + +***Number*** + +- [`jerry_create_number_infinity`](02.API-REFERENCE.md#jerry_create_number_infinity) +- [`jerry_create_number_nan`](02.API-REFERENCE.md#jerry_create_number_nan) + +***Promise*** + +- [`jerry_run_all_enqueued_jobs`](02.API-REFERENCE.md#jerry_run_all_enqueued_jobs) +- [`jerry_create_promise`](02.API-REFERENCE.md#jerry_create_promise) +- [`jerry_resolve_or_reject_promise`](02.API-REFERENCE.md#jerry_resolve_or_reject_promise) +- [`jerry_value_is_promise`](02.API-REFERENCE.md#jerry_value_is_promise) + +***RegExp*** + +- [`jerry_create_regexp`](02.API-REFERENCE.md#jerry_create_regexp) +- [`jerry_create_regexp_sz`](02.API-REFERENCE.md#jerry_create_regexp_sz) + +***String*** + +- [`jerry_substring_to_utf8_char_buffer`](02.API-REFERENCE.md#jerry_substring_to_utf8_char_buffer) +- [`jerry_get_utf8_string_size`](02.API-REFERENCE.md#jerry_get_utf8_string_size) +- [`jerry_get_utf8_string_length`](02.API-REFERENCE.md#jerry_get_utf8_string_length) +- [`jerry_create_string_from_utf8`](02.API-REFERENCE.md#jerry_create_string_from_utf8) +- [`jerry_create_string_sz_from_utf8`](02.API-REFERENCE.md#jerry_create_string_sz_from_utf8) + +***Symbol*** + +- [`jerry_create_symbol`](02.API-REFERENCE.md#jerry_create_symbol) +- [`jerry_get_symbol_descriptive_string`](02.API-REFERENCE.md#jerry_get_symbol_descriptive_string) +- [`jerry_value_is_symbol`](02.API-REFERENCE.md#jerry_value_is_symbol) + +***TypedArray*** + +- [`jerry_create_typedarray`](02.API-REFERENCE.md#jerry_create_typedarray) +- [`jerry_create_typedarray_for_arraybuffer`](02.API-REFERENCE.md#jerry_create_typedarray_for_arraybuffer) +- [`jerry_create_typedarray_for_arraybuffer_sz`](02.API-REFERENCE.md#jerry_create_typedarray_for_arraybuffer_sz) +- [`jerry_get_typedarray_type`](02.API-REFERENCE.md#jerry_get_typedarray_type) +- [`jerry_get_typedarray_length`](02.API-REFERENCE.md#jerry_get_typedarray_length) +- [`jerry_get_typedarray_buffer`](02.API-REFERENCE.md#jerry_get_typedarray_buffer) +- [`jerry_value_is_typedarray`](02.API-REFERENCE.md#jerry_value_is_typedarray) + + +## Instances and memory management + +***JerryScript instances*** + +- [`jerry_create_context`](02.API-REFERENCE.md#jerry_create_context) +- [`jerry_get_context_data`](02.API-REFERENCE.md#jerry_get_context_data) + +***Memory management*** + +- [`jerry_heap_alloc`](02.API-REFERENCE.md#jerry_heap_alloc) +- [`jerry_heap_free`](02.API-REFERENCE.md#jerry_heap_free) + + +## Operations with JavaScript values + +***Binary operations*** + +- [`jerry_binary_operation`](02.API-REFERENCE.md#jerry_binary_operation) + +***Error manipulating*** + +- [`jerry_get_error_type`](02.API-REFERENCE.md#jerry_get_error_type) +- [`jerry_get_backtrace`](02.API-REFERENCE.md#jerry_get_backtrace) + +***Native pointers*** + +- [`jerry_delete_object_native_pointer`](02.API-REFERENCE.md#jerry_delete_object_native_pointer) +- [`jerry_objects_foreach_by_native_info`](02.API-REFERENCE.md#jerry_objects_foreach_by_native_info) + +***Property*** + +- [`jerry_delete_property_by_index`](02.API-REFERENCE.md#jerry_delete_property_by_index) +- [`jerry_objects_foreach`](02.API-REFERENCE.md#jerry_objects_foreach) + + +## Debugger + +- [`jerry_debugger_is_connected`](07.DEBUGGER.md#jerry_debugger_is_connected) +- [`jerry_debugger_stop`](07.DEBUGGER.md#jerry_debugger_stop) +- [`jerry_debugger_continue`](07.DEBUGGER.md#jerry_debugger_continue) +- [`jerry_debugger_stop_at_breakpoint`](07.DEBUGGER.md#jerry_debugger_stop_at_breakpoint) +- [`jerry_debugger_wait_for_client_source`](07.DEBUGGER.md#jerry_debugger_wait_for_client_source) +- [`jerry_debugger_send_output`](07.DEBUGGER.md#jerry_debugger_send_output) +- [`jerry_debugger_send_log`](07.DEBUGGER.md#jerry_debugger_send_log) + + +## Other + +- [`jerry_is_feature_enabled`](02.API-REFERENCE.md#jerry_is_feature_enabled) +- [`jerry_parse_and_save_literals`](02.API-REFERENCE.md#jerry_parse_and_save_literals) +- [`jerry_set_vm_exec_stop_callback`](02.API-REFERENCE.md#jerry_set_vm_exec_stop_callback) + + +## Port API functions + +- [`jerry_port_normalize_path`](05.PORT-API.md#jerry_port_normalize_path) +- [`jerry_port_read_source`](05.PORT-API.md#jerry_port_read_source) +- [`jerry_port_release_source`](05.PORT-API.md#jerry_port_release_source) +- [`jerry_port_print_char`](05.PORT-API.md#jerry_port_print_char) +- [`jerry_port_get_current_context`](05.PORT-API.md#jerry_port_get_current_context) +- [`jerry_port_fatal`](05.PORT-API.md#jerry_port_fatal) +- [`jerry_port_sleep`](05.PORT-API.md#jerry_port_sleep) diff --git a/img/ecma_object.png b/img/ecma_object.png index b0d45450d..1913dfc89 100644 Binary files a/img/ecma_object.png and b/img/ecma_object.png differ diff --git a/img/ecma_value.png b/img/ecma_value.png index 589424302..9e54853e0 100644 Binary files a/img/ecma_value.png and b/img/ecma_value.png differ