## Reference counting in JerryScript In JerryScript all `jerry_value_t` values are independent references to internal objects. Values returned by JerryScript API functions are always live references and must be released by `jerry_release_value`. ```c jerry_value_t global = jerry_get_global_object (); /* The value stored in the 'global' variable contains a live * reference to the global object. The system also keeps its * own live reference to the global object. These two references * are independent, and both must be destroyed before the global * object can be freed. */ jerry_release_value (global); /* Without jerry_release_value() the global object will not * be freed even by jerry_cleanup(). After the reference * is released it becomes a dead reference and cannot be * used anymore. */ ``` Multiple references might refer to the same internal object even though their `jerry_value_t` representation might be different. ```c jerry_value_t pi_ref1 = jerry_create_number (3.14); jerry_value_t pi_ref2 = jerry_acquire_value (pi_ref1); /* Both pi_ref1 and pi_ref2 refer to the same 3.14 value * although they might not be equal in C (pi_ref1 != pi_ref2). */ /* Both references must be released. */ jerry_release_value (pi_ref1); jerry_release_value (pi_ref2); ``` Releasing the same `jerry_value_t` twice to release two live references is not allowed and it might cause crashes. Hence the following code is an **INCORRECT WAY** of releasing the 3.14 value. ```c jerry_release_value (pi_ref1); jerry_release_value (pi_ref1); ``` JerryScript API functions returning with a `jerry_value_t` always return with a new live reference. Passing a `jerry_value_t` to an API function never releases its reference (unless explicitly stated in the documentation). The next example shows this behaviour through property getting and setting. ```c jerry_value_t prop_value = jerry_get_property (...); /* The prop_value must be released later because both the base * object and the prop_value have an independent reference to * the same JavaScript value. When the operation fails, the * prop_value contains a live reference to an error object. * This reference must be released as well. */ if (jerry_value_is_error (prop_value)) { /* Errors can be handled here. */ } else { /* The application has a live reference to the property * value even if the base object is freed by the garbage * collector. */ } /* The prop_value must be released. */ jerry_release_value (prop_value); /* Property setting is the same. */ jerry_value_t new_prop_value = jerry_create_number (2.718); jerry_value_t result = jerry_set_property (..., new_prop_value); /* If the property set is successful, a new reference is created * for the value referenced by new_prop_value. The new_prop_value * reference must be released regardless of whether the operation * is successful. */ /* The new_prop_value can be passed to other JerryScript API * functions before the jerry_release_value () call. */ jerry_release_value (new_prop_value); /* The reference stored in the 'result' variable is live whether * the operation is successful or not, and must also be freed. */ if (jerry_value_is_error (result)) { /* Errors can be handled here. */ } else { /* A reference to a true primitive value is returned. */ } jerry_release_value (result); ``` The simplest form of setting a property without error checking is the following: ```c /* There are no 'ifs' in this snippet. */ jerry_release_value (jerry_set_property (..., new_prop_value)); jerry_release_value (new_prop_value); ``` The reference returned by a `jerry_external_handler_t` callback transfers the ownership of the live reference. Otherwise the referenced object could be freed by the garbage collector. ```c jerry_value_t my_external_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 { /* Do not release function_obj, this_val, and args_p because * these references are automatically released after the handler * is returned. This approach reduces code size which is useful * on embedded systems. However you can create other references * to them by calling jerry_acquire_value () if needed. */ /* Since the ownership of the reference is transferred to the * caller the following snippet is valid. */ /* If the value to be returned is needed for other purposes the * jerry_acquire_value () can be used to create new references. */ return jerry_create_string (...); } ``` Duplicating a `jerry_value_t` in C does not create another live reference. ```c jerry_value_t undef = jerry_create_undefined (); jerry_value_t undef2 = undef; /* Releasing either undef or undef2 is valid but not both. * After the release both references become dead (invalid). */ jerry_release_value (undef2); /* Dead references can be reassigned again. */ undef = jerry_create_boolean (true); ``` References can be duplicated in C as long as only one of them is freed. ```c jerry_value_t a = jerry_create_boolean (true); jerry_value_t b = a; jerry_value_t c = a; /* A new reference is assigned to 'a'. */ a = jerry_create_boolean (false); [...] jerry_release_value (a); /* The 'a' (boolean false) reference becomes dead (invalid). */ jerry_release_value (c); /* Both 'b' and 'c' (boolean true) references become dead. */ /* Since all references are released, no memory leak occurs. */ ```