diff --git a/docs/11.EXT-REFERENCE-AUTORELEASE.md b/docs/11.EXT-REFERENCE-AUTORELEASE.md new file mode 100644 index 000000000..8e3aa9ae3 --- /dev/null +++ b/docs/11.EXT-REFERENCE-AUTORELEASE.md @@ -0,0 +1,47 @@ +# Autorelease values + +## JERRYX_AR_VALUE_T + +**Summary** + +Macro for `const jerry_value_t` for which jerry_release_value() is +automatically called when the variable goes out of scope. + +*Note*: The macro depends on compiler support. For GCC and LLVM/clang, the macro is implemented +using the `__cleanup__` variable attribute. For other compilers, no support has been added yet. + +**Example** + +```c +#include "jerryscript.h" +#include "jerryscript-ext/autorelease.h" + +static void foo (bool enable) +{ + JERRYX_AR_VALUE_T bar = jerry_create_string (...); + + if (enable) + { + JERRYX_AR_VALUE_T baz = jerry_get_global_object (); + + ... + + /* + * jerry_release_value (baz) and jerry_release_value (bar) is called automatically before + * returning, because `baz` and `bar` go out of scope. + */ + return; + } + + /* + * jerry_release_value (bar) is called automatically when the function returns, + * because `bar` goes out of scope. + */ +} +``` + +**See also** + +- [jerry_value_t](../docs/02.API-REFERENCE.md#jerry_value_t) +- [jerry_acquire_value](../docs/02.API-REFERENCE.md#jerry_acquire_value) +- [jerry_release_value](../docs/02.API-REFERENCE.md#jerry_release_value) diff --git a/jerry-ext/include/jerryscript-ext/autorelease.h b/jerry-ext/include/jerryscript-ext/autorelease.h new file mode 100644 index 000000000..f7cf7dea1 --- /dev/null +++ b/jerry-ext/include/jerryscript-ext/autorelease.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYX_AUTORELEASE_H +#define JERRYX_AUTORELEASE_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "autorelease.impl.h" + +/* + * Macro for `const jerry_value_t` for which jerry_release_value () is + * automatically called when the variable goes out of scope. + * + * Example usage: + * static void foo (bool enable) + * { + * JERRYX_AR_VALUE_T bar = jerry_create_string (...); + * + * if (enable) { + * JERRYX_AR_VALUE_T baz = jerry_get_global_object (); + * + * // ... + * + * // jerry_release_value (baz) and jerry_release_value (bar) is called automatically before + * // returning, because `baz` and `bar` go out of scope. + * return; + * } + * + * // jerry_release_value (bar) is called automatically when the function returns, + * // because `bar` goes out of scope. + * } + */ +#define JERRYX_AR_VALUE_T __JERRYX_AR_VALUE_T_IMPL + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* !JERRYX_AUTORELEASE_H */ diff --git a/jerry-ext/include/jerryscript-ext/autorelease.impl.h b/jerry-ext/include/jerryscript-ext/autorelease.impl.h new file mode 100644 index 000000000..558b17095 --- /dev/null +++ b/jerry-ext/include/jerryscript-ext/autorelease.impl.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYX_AUTORELEASE_IMPL_H +#define JERRYX_AUTORELEASE_IMPL_H + +#include "jerryscript.h" + +#ifdef __GNUC__ +/* + * Calls jerry_release_value (*value). + * The GCC __cleanup__ function must take a pointer to the variable to clean up. + * + * @return void + */ +static inline void +jerryx_autorelease_cleanup (const jerry_value_t *value) /**< jerry value */ +{ + jerry_release_value (*value); +} /* jerryx_autorelease_cleanup */ + +#define __JERRYX_AR_VALUE_T_IMPL const jerry_value_t __attribute__ ((__cleanup__(jerryx_autorelease_cleanup))) +#else /* !__GNUC__ */ +/* TODO: for other compilers */ +#error "No autorelease implementation for your compiler!" +#endif /* __GNUC__ */ + +#endif /* !JERRYX_AUTORELEASE_IMPL_H */ diff --git a/tests/unit-ext/test-ext-autorelease.c b/tests/unit-ext/test-ext-autorelease.c new file mode 100644 index 000000000..c639e995a --- /dev/null +++ b/tests/unit-ext/test-ext-autorelease.c @@ -0,0 +1,64 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Unit test for jerry-ext/autorelease. + */ + +#include "jerryscript.h" +#include "jerryscript-ext/autorelease.h" +#include "test-common.h" + +static int native_free_cb_call_count; + +static void +native_free_cb (void *native_p) +{ + ++native_free_cb_call_count; + (void) native_p; +} /* native_free_cb */ + +static const jerry_object_native_info_t native_info = +{ + .free_cb = native_free_cb, +}; + +static jerry_value_t +create_object (void) +{ + jerry_value_t obj = jerry_create_object (); + jerry_set_object_native_pointer (obj, NULL, &native_info); + return obj; +} /* create_object */ + +static void +test_autorelease_val (void) +{ + JERRYX_AR_VALUE_T obj = create_object (); + (void) obj; +} /* test_autorelease_val */ + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + native_free_cb_call_count = 0; + test_autorelease_val (); + jerry_gc (); + TEST_ASSERT (native_free_cb_call_count == 1); + + jerry_cleanup (); +} /* main */ diff --git a/tools/update-webpage.sh b/tools/update-webpage.sh index ec140c673..80711adab 100755 --- a/tools/update-webpage.sh +++ b/tools/update-webpage.sh @@ -32,6 +32,7 @@ DEBUGGER_MD="07.DEBUGGER.md" CODING_STANDARDS_MD="08.CODING-STANDARDS.md" EXT_REFERENCE_ARG_MD="09.EXT-REFERENCE-ARG.md" EXT_REFERENCE_HANDLER_MD="10.EXT-REFERENCE-HANDLER.md" +EXT_REFERENCE_AUTORELEASE_MD="11.EXT-REFERENCE-AUTORELEASE.md" declare -A titles @@ -45,6 +46,7 @@ titles[$DEBUGGER_MD]="Debugger" titles[$CODING_STANDARDS_MD]="Coding Standards" titles[$EXT_REFERENCE_ARG_MD]="'Extension API: Argument Validation'" titles[$EXT_REFERENCE_HANDLER_MD]="'Extension API: External Function Handlers'" +titles[$EXT_REFERENCE_AUTORELEASE_MD]="'Extension API: Autorelease Values'" for docfile in $docs_dir/*.md; do docfile_base=`basename $docfile`