Implement handle scope API in jerry-ext (#2753)

JerryScript-DCO-1.0-Signed-off-by: legendecas legendecas@gmail.com
This commit is contained in:
legendecas
2019-03-27 21:49:59 +08:00
committed by Zoltan Herczeg
parent 772ab277ea
commit 5b29bf6288
13 changed files with 1510 additions and 0 deletions
+1
View File
@@ -37,6 +37,7 @@ file(GLOB SOURCE_EXT
arg/*.c
common/*.c
debugger/*.c
handle-scope/*.c
handler/*.c
module/*.c)
@@ -0,0 +1,224 @@
/* 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.
*/
#include <stdlib.h>
#include "handle-scope-internal.h"
static jerryx_handle_scope_t jerryx_handle_scope_root =
{
.prelist_handle_count = 0,
.handle_ptr = NULL,
};
static jerryx_handle_scope_t *jerryx_handle_scope_current = &jerryx_handle_scope_root;
static jerryx_handle_scope_pool_t jerryx_handle_scope_pool =
{
.count = 0,
.start = NULL,
};
#define JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST \
jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1
#define JERRYX_HANDLE_SCOPE_PRELIST_IDX(scope) (scope - jerryx_handle_scope_pool.prelist)
/**
* Get current handle scope top of stack.
*/
inline jerryx_handle_scope_t *
jerryx_handle_scope_get_current (void)
{
return jerryx_handle_scope_current;
} /* jerryx_handle_scope_get_current */
/**
* Get root handle scope.
*/
inline jerryx_handle_scope_t *
jerryx_handle_scope_get_root (void)
{
return &jerryx_handle_scope_root;
} /* jerryx_handle_scope_get_root */
/**
* Determines if given handle scope is located in pre-allocated list.
*
* @param scope - the one to be determined.
*/
static inline bool
jerryx_handle_scope_is_in_prelist (jerryx_handle_scope_t *scope)
{
return (jerryx_handle_scope_pool.prelist <= scope)
&& (scope <= (jerryx_handle_scope_pool.prelist + JERRYX_SCOPE_PRELIST_SIZE - 1));
} /** jerryx_handle_scope_is_in_prelist */
/**
* Get the parent of given handle scope.
* If given handle scope is in prelist, the parent must be in prelist too;
* if given is the first item of heap chain list, the parent must be the last one of prelist;
* the parent must be in chain list otherwise.
*
* @param scope - the one to be permformed on.
* @returns - the parent of the given scope.
*/
jerryx_handle_scope_t *
jerryx_handle_scope_get_parent (jerryx_handle_scope_t *scope)
{
if (scope == &jerryx_handle_scope_root)
{
return NULL;
}
if (!jerryx_handle_scope_is_in_prelist (scope))
{
jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope;
if (dy_scope == jerryx_handle_scope_pool.start)
{
return JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST;
}
jerryx_handle_scope_dynamic_t *parent = dy_scope->parent;
return (jerryx_handle_scope_t *) parent;
}
if (scope == jerryx_handle_scope_pool.prelist)
{
return &jerryx_handle_scope_root;
}
return jerryx_handle_scope_pool.prelist + JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope) - 1;
} /** jerryx_handle_scope_get_parent */
/**
* Get the child of given handle scope.
* If the given handle scope is in heap chain list, its child must be in heap chain list too;
* if the given handle scope is the last one of prelist, its child must be the first item of chain list;
* the children are in prelist otherwise.
*
* @param scope - the one to be permformed on.
* @returns the child of the given scope.
*/
jerryx_handle_scope_t *
jerryx_handle_scope_get_child (jerryx_handle_scope_t *scope)
{
if (scope == &jerryx_handle_scope_root)
{
if (jerryx_handle_scope_pool.count > 0)
{
return jerryx_handle_scope_pool.prelist;
}
return NULL;
}
if (!jerryx_handle_scope_is_in_prelist (scope))
{
jerryx_handle_scope_dynamic_t *child = ((jerryx_handle_scope_dynamic_t *) scope)->child;
return (jerryx_handle_scope_t *) child;
}
if (scope == JERRYX_HANDLE_SCOPE_POOL_PRELIST_LAST)
{
return (jerryx_handle_scope_t *) jerryx_handle_scope_pool.start;
}
long idx = JERRYX_HANDLE_SCOPE_PRELIST_IDX (scope);
if (idx < 0)
{
return NULL;
}
if ((unsigned long) idx >= jerryx_handle_scope_pool.count - 1)
{
return NULL;
}
return jerryx_handle_scope_pool.prelist + idx + 1;
} /** jerryx_handle_scope_get_child */
/**
* Claims a handle scope either from prelist or allocating a new memory block,
* and increment pool's scope count by 1, and set current scope to the newly claimed one.
* If there are still available spaces in prelist, claims a block in prelist;
* otherwise allocates a new memory block from heap and sets its fields to default values,
* and link it to previously dynamically allocated scope, or link it to pool's start pointer.
*
* @returns the newly claimed handle scope pointer.
*/
jerryx_handle_scope_t *
jerryx_handle_scope_alloc (void)
{
jerryx_handle_scope_t *scope;
if (jerryx_handle_scope_pool.count < JERRYX_SCOPE_PRELIST_SIZE)
{
scope = jerryx_handle_scope_pool.prelist + jerryx_handle_scope_pool.count;
}
else
{
jerryx_handle_scope_dynamic_t *dy_scope = malloc (sizeof (jerryx_handle_scope_dynamic_t));
JERRYX_HANDLE_SCOPE_ASSERT (dy_scope != NULL);
dy_scope->child = NULL;
if (jerryx_handle_scope_pool.count != JERRYX_SCOPE_PRELIST_SIZE)
{
jerryx_handle_scope_dynamic_t *dy_current = (jerryx_handle_scope_dynamic_t *) jerryx_handle_scope_current;
dy_scope->parent = dy_current;
dy_current->child = dy_scope;
}
else
{
jerryx_handle_scope_pool.start = dy_scope;
dy_scope->parent = NULL;
}
scope = (jerryx_handle_scope_t *) dy_scope;
}
scope->prelist_handle_count = 0;
scope->escaped = false;
scope->handle_ptr = NULL;
jerryx_handle_scope_current = scope;
++jerryx_handle_scope_pool.count;
return (jerryx_handle_scope_t *) scope;
} /** jerryx_handle_scope_alloc */
/**
* Deannounce a previously claimed handle scope, return it to pool
* or free the allocated memory block.
*
* @param scope - the one to be freed.
*/
void
jerryx_handle_scope_free (jerryx_handle_scope_t *scope)
{
if (scope == &jerryx_handle_scope_root)
{
return;
}
--jerryx_handle_scope_pool.count;
if (scope == jerryx_handle_scope_current)
{
jerryx_handle_scope_current = jerryx_handle_scope_get_parent (scope);
}
if (!jerryx_handle_scope_is_in_prelist (scope))
{
jerryx_handle_scope_dynamic_t *dy_scope = (jerryx_handle_scope_dynamic_t *) scope;
if (dy_scope == jerryx_handle_scope_pool.start)
{
jerryx_handle_scope_pool.start = dy_scope->child;
}
else if (dy_scope->parent != NULL)
{
dy_scope->parent->child = dy_scope->child;
}
free (dy_scope);
return;
}
/**
* Nothing to do with scopes in prelist
*/
} /** jerryx_handle_scope_free */
@@ -0,0 +1,89 @@
/* 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_HANDLE_SCOPE_INTERNAL_H
#define JERRYX_HANDLE_SCOPE_INTERNAL_H
#include "jerryscript.h"
#include "jerryscript-port.h"
#include "jerryscript-ext/handle-scope.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#define JERRYX_HANDLE_SCOPE_ASSERT(x) \
do \
{ \
if (!(x)) \
{ \
jerry_port_log (JERRY_LOG_LEVEL_ERROR, \
"JerryXHandleScope: Assertion '%s' failed at %s(%s):%lu.\n", \
#x, \
__FILE__, \
__func__, \
(unsigned long) __LINE__); \
jerry_port_fatal (ERR_FAILED_INTERNAL_ASSERTION); \
} \
} while (0)
/** MARK: - handle-scope-allocator.c */
typedef struct jerryx_handle_scope_pool_s jerryx_handle_scope_pool_t;
/**
* A linear allocating memory pool for type jerryx_handle_scope_t,
* in which allocated item shall be released in reversed order of allocation
*/
struct jerryx_handle_scope_pool_s
{
jerryx_handle_scope_t prelist[JERRYX_SCOPE_PRELIST_SIZE]; /**< inlined handle scopes in the pool */
size_t count; /**< number of handle scopes in the pool */
jerryx_handle_scope_dynamic_t *start; /**< start address of dynamically allocated handle scope list */
};
jerryx_handle_scope_t *
jerryx_handle_scope_get_parent (jerryx_handle_scope_t *scope);
jerryx_handle_scope_t *
jerryx_handle_scope_get_child (jerryx_handle_scope_t *scope);
jerryx_handle_scope_t *
jerryx_handle_scope_alloc (void);
void
jerryx_handle_scope_free (jerryx_handle_scope_t *scope);
/** MARK: - END handle-scope-allocator.c */
/** MARK: - handle-scope.c */
void
jerryx_handle_scope_release_handles (jerryx_handle_scope scope);
jerry_value_t
jerryx_hand_scope_escape_handle_from_prelist (jerryx_handle_scope scope, size_t idx);
jerry_value_t
jerryx_handle_scope_add_handle_to (jerryx_handle_t *handle, jerryx_handle_scope scope);
jerryx_handle_scope_status
jerryx_escape_handle_internal (jerryx_escapable_handle_scope scope,
jerry_value_t escapee,
jerry_value_t *result,
bool should_promote);
/** MARK: - END handle-scope.c */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRYX_HANDLE_SCOPE_INTERNAL_H */
+361
View File
@@ -0,0 +1,361 @@
/* 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.
*/
#include <stdlib.h>
#include "handle-scope-internal.h"
/**
* Opens a new handle scope and attach it to current global scope as a child scope.
*
* @param result - [out value] opened scope.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_open_handle_scope (jerryx_handle_scope *result)
{
*result = jerryx_handle_scope_alloc ();
return jerryx_handle_scope_ok;
} /** jerryx_open_handle_scope */
/**
* Release all jerry values attached to given scope
*
* @param scope - the scope of handles to be released.
*/
void
jerryx_handle_scope_release_handles (jerryx_handle_scope scope)
{
size_t prelist_handle_count = scope->prelist_handle_count;
if (prelist_handle_count == JERRYX_HANDLE_PRELIST_SIZE && scope->handle_ptr != NULL)
{
jerryx_handle_t *a_handle = scope->handle_ptr;
while (a_handle != NULL)
{
jerry_release_value (a_handle->jval);
jerryx_handle_t *sibling = a_handle->sibling;
free (a_handle);
a_handle = sibling;
}
scope->handle_ptr = NULL;
prelist_handle_count = JERRYX_HANDLE_PRELIST_SIZE;
}
for (size_t idx = 0; idx < prelist_handle_count; idx++)
{
jerry_release_value (scope->handle_prelist[idx]);
}
scope->prelist_handle_count = 0;
} /** jerryx_handle_scope_release_handles */
/**
* Close the scope and its child scopes and release all jerry values that
* resides in the scopes.
* Scopes must be closed in the reverse order from which they were created.
*
* @param scope - the scope closed.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_close_handle_scope (jerryx_handle_scope scope)
{
/**
* Release all handles related to given scope and its child scopes
*/
jerryx_handle_scope a_scope = scope;
do
{
jerryx_handle_scope_release_handles (a_scope);
jerryx_handle_scope child = jerryx_handle_scope_get_child (a_scope);
jerryx_handle_scope_free (a_scope);
a_scope = child;
}
while (a_scope != NULL);
return jerryx_handle_scope_ok;
} /** jerryx_close_handle_scope */
/**
* Opens a new handle scope from which one object can be promoted to the outer scope
* and attach it to current global scope as a child scope.
*
* @param result - [out value] opened escapable handle scope.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_open_escapable_handle_scope (jerryx_handle_scope *result)
{
return jerryx_open_handle_scope (result);
} /** jerryx_open_escapable_handle_scope */
/**
* Close the scope and its child scopes and release all jerry values that
* resides in the scopes.
* Scopes must be closed in the reverse order from which they were created.
*
* @param scope - the one to be closed.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_close_escapable_handle_scope (jerryx_handle_scope scope)
{
return jerryx_close_handle_scope (scope);
} /** jerryx_close_escapable_handle_scope */
/**
* Internal helper.
* Escape a jerry value from the scope, yet did not promote it to outer scope.
* An assertion of if parent exists shall be made before invoking this function.
*
* @param scope - scope of the handle added to.
* @param idx - expected index of the handle in the scope's prelist.
* @returns escaped jerry value id
*/
jerry_value_t
jerryx_hand_scope_escape_handle_from_prelist (jerryx_handle_scope scope, size_t idx)
{
jerry_value_t jval = scope->handle_prelist[idx];
if (scope->prelist_handle_count == JERRYX_HANDLE_PRELIST_SIZE && scope->handle_ptr != NULL)
{
jerryx_handle_t *handle = scope->handle_ptr;
scope->handle_ptr = handle->sibling;
scope->handle_prelist[idx] = handle->jval;
free (handle);
return jval;
}
if (idx < JERRYX_HANDLE_PRELIST_SIZE - 1)
{
scope->handle_prelist[idx] = scope->handle_prelist[scope->prelist_handle_count - 1];
}
return jval;
} /** jerryx_hand_scope_escape_handle_from_prelist */
/**
* Internal helper.
* Escape a jerry value from the given escapable handle scope.
*
* @param scope - the expected scope to be escaped from.
* @param escapee - the jerry value to be escaped.
* @param result - [out value] escaped jerry value result.
* @param should_promote - true if the escaped value should be added to parent
* scope after escaped from the given handle scope.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_escape_handle_internal (jerryx_escapable_handle_scope scope,
jerry_value_t escapee,
jerry_value_t *result,
bool should_promote)
{
if (scope->escaped)
{
return jerryx_escape_called_twice;
}
jerryx_handle_scope parent = jerryx_handle_scope_get_parent (scope);
if (parent == NULL)
{
return jerryx_handle_scope_mismatch;
}
bool found = false;
{
size_t found_idx = 0;
size_t prelist_count = scope->prelist_handle_count;
/**
* Search prelist in a reversed order since last added handle
* is possible the one to be escaped
*/
for (size_t idx_plus_1 = prelist_count; idx_plus_1 > 0; --idx_plus_1)
{
if (escapee == scope->handle_prelist[idx_plus_1 - 1])
{
found = true;
found_idx = idx_plus_1 - 1;
break;
}
}
if (found)
{
*result = jerryx_hand_scope_escape_handle_from_prelist (scope, found_idx);
--scope->prelist_handle_count;
if (should_promote)
{
scope->escaped = true;
/**
* Escape handle to parent scope
*/
jerryx_create_handle_in_scope (*result, jerryx_handle_scope_get_parent (scope));
}
return jerryx_handle_scope_ok;
}
};
if (scope->prelist_handle_count <= JERRYX_HANDLE_PRELIST_SIZE && scope->handle_ptr == NULL)
{
return jerryx_handle_scope_mismatch;
}
/**
* Handle chain list is already in an reversed order,
* search through it as it is
*/
jerryx_handle_t *handle = scope->handle_ptr;
jerryx_handle_t *memo_handle = NULL;
jerryx_handle_t *found_handle = NULL;
while (!found)
{
if (handle == NULL)
{
return jerryx_handle_scope_mismatch;
}
if (handle->jval != escapee)
{
memo_handle = handle;
handle = handle->sibling;
continue;
}
/**
* Remove found handle from current scope's handle chain
*/
found = true;
found_handle = handle;
if (memo_handle == NULL)
{
// found handle is the first handle in heap
scope->handle_ptr = found_handle->sibling;
}
else
{
memo_handle->sibling = found_handle->sibling;
}
}
if (should_promote)
{
/**
* Escape handle to parent scope
*/
*result = jerryx_handle_scope_add_handle_to (found_handle, parent);
}
if (should_promote)
{
scope->escaped = true;
}
return jerryx_handle_scope_ok;
} /** jerryx_escape_handle_internal */
/**
* Promotes the handle to the JavaScript object so that it is valid for the lifetime of
* the outer scope. It can only be called once per scope. If it is called more than
* once an error will be returned.
*
* @param scope - the expected scope to be escaped from.
* @param escapee - the jerry value to be escaped.
* @param result - [out value] escaped jerry value result.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_escape_handle (jerryx_escapable_handle_scope scope,
jerry_value_t escapee,
jerry_value_t *result)
{
return jerryx_escape_handle_internal (scope, escapee, result, true);
} /** jerryx_escape_handle */
/**
* Escape a handle from scope yet do not promote it to the outer scope.
* Leave the handle's life time management up to user.
*
* @param scope - the expected scope to be removed from.
* @param escapee - the jerry value to be removed.
* @param result - [out value] removed jerry value result.
* @return status code, jerryx_handle_scope_ok if success.
*/
jerryx_handle_scope_status
jerryx_remove_handle (jerryx_escapable_handle_scope scope,
jerry_value_t escapee,
jerry_value_t *result)
{
return jerryx_escape_handle_internal (scope, escapee, result, false);
} /** jerryx_remove_handle */
/**
* Try to reuse given handle if possible while adding to the scope.
*
* @param handle - the one to be added to the scope.
* @param scope - the scope of handle to be added to.
* @returns the jerry value id wrapped by given handle.
*/
jerry_value_t
jerryx_handle_scope_add_handle_to (jerryx_handle_t *handle, jerryx_handle_scope scope)
{
size_t prelist_handle_count = scope->prelist_handle_count;
if (prelist_handle_count < JERRYX_HANDLE_PRELIST_SIZE)
{
++scope->prelist_handle_count;
jerry_value_t jval = handle->jval;
free (handle);
scope->handle_prelist[prelist_handle_count] = jval;
return jval;
}
handle->sibling = scope->handle_ptr;
scope->handle_ptr = handle;
return handle->jval;
} /** jerryx_handle_scope_add_handle_to */
/**
* Add given jerry value to the scope.
*
* @param jval - jerry value to be added to scope.
* @param scope - the scope of the jerry value been expected to be added to.
* @return jerry value that added to scope.
*/
jerry_value_t
jerryx_create_handle_in_scope (jerry_value_t jval, jerryx_handle_scope scope)
{
size_t prelist_handle_count = scope->prelist_handle_count;
if (prelist_handle_count < JERRYX_HANDLE_PRELIST_SIZE)
{
scope->handle_prelist[prelist_handle_count] = jval;
++scope->prelist_handle_count;
return jval;
}
jerryx_handle_t *handle = malloc (sizeof (jerryx_handle_t));
JERRYX_HANDLE_SCOPE_ASSERT (handle != NULL);
handle->jval = jval;
handle->sibling = scope->handle_ptr;
scope->handle_ptr = handle;
return jval;
} /** jerryx_create_handle_in_scope */
/**
* Add given jerry value to current top scope.
*
* @param jval - jerry value to be added to scope.
* @return jerry value that added to scope.
*/
jerry_value_t
jerryx_create_handle (jerry_value_t jval)
{
return jerryx_create_handle_in_scope (jval, jerryx_handle_scope_get_current ());
} /** jerryx_create_handle */
@@ -0,0 +1,135 @@
/* 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_HANDLE_SCOPE_H
#define JERRYX_HANDLE_SCOPE_H
#include "jerryscript.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef JERRYX_HANDLE_PRELIST_SIZE
#define JERRYX_HANDLE_PRELIST_SIZE 20
#endif
#ifndef JERRYX_SCOPE_PRELIST_SIZE
#define JERRYX_SCOPE_PRELIST_SIZE 20
#endif
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
STATIC_ASSERT (JERRYX_SCOPE_PRELIST_SIZE < 32, JERRYX_SCOPE_PRELIST_SIZE_must_be_less_than_size_of_uint8_t);
#undef STATIC_ASSERT
typedef struct jerryx_handle_t jerryx_handle_t;
/**
* Dynamically allocated handle in the scopes.
* Scopes has it's own size-limited linear storage of handles. Still there
* might be not enough space left for new handles, dynamically allocated
* `jerryx_handle_t` could ease the pre-allocated linear memory burden.
*/
struct jerryx_handle_t
{
jerry_value_t jval; /**< jerry value of the handle bound to */
jerryx_handle_t *sibling; /**< next sibling the the handle */
};
#define JERRYX_HANDLE_SCOPE_FIELDS \
jerry_value_t handle_prelist[JERRYX_HANDLE_PRELIST_SIZE]; \
uint8_t prelist_handle_count; \
bool escaped; \
jerryx_handle_t *handle_ptr
typedef struct jerryx_handle_scope_s jerryx_handle_scope_t;
typedef jerryx_handle_scope_t *jerryx_handle_scope;
typedef jerryx_handle_scope_t *jerryx_escapable_handle_scope;
/**
* Inlined simple handle scope type.
*/
struct jerryx_handle_scope_s
{
JERRYX_HANDLE_SCOPE_FIELDS; /**< common handle scope fields */
};
typedef struct jerryx_handle_scope_dynamic_s jerryx_handle_scope_dynamic_t;
/**
* Dynamically allocated handle scope type.
*/
struct jerryx_handle_scope_dynamic_s
{
JERRYX_HANDLE_SCOPE_FIELDS; /**< common handle scope fields */
jerryx_handle_scope_dynamic_t *child; /**< child dynamically allocated handle scope */
jerryx_handle_scope_dynamic_t *parent; /**< parent dynamically allocated handle scope */
};
#undef JERRYX_HANDLE_SCOPE_FIELDS
typedef enum
{
jerryx_handle_scope_ok = 0,
jerryx_escape_called_twice,
jerryx_handle_scope_mismatch,
} jerryx_handle_scope_status;
jerryx_handle_scope_status
jerryx_open_handle_scope (jerryx_handle_scope *result);
jerryx_handle_scope_status
jerryx_close_handle_scope (jerryx_handle_scope scope);
jerryx_handle_scope_status
jerryx_open_escapable_handle_scope (jerryx_handle_scope *result);
jerryx_handle_scope_status
jerryx_close_escapable_handle_scope (jerryx_handle_scope scope);
jerryx_handle_scope_status
jerryx_escape_handle (jerryx_escapable_handle_scope scope,
jerry_value_t escapee,
jerry_value_t *result);
/**
* Completely escape a handle from handle scope,
* leave life time management totally up to user.
*/
jerryx_handle_scope_status
jerryx_remove_handle (jerryx_escapable_handle_scope scope,
jerry_value_t escapee,
jerry_value_t *result);
jerry_value_t
jerryx_create_handle (jerry_value_t jval);
jerry_value_t
jerryx_create_handle_in_scope (jerry_value_t jval, jerryx_handle_scope scope);
/** MARK: - handle-scope-allocator.c */
jerryx_handle_scope_t *
jerryx_handle_scope_get_current (void);
jerryx_handle_scope_t *
jerryx_handle_scope_get_root (void);
/** MARK: - END handle-scope-allocator.c */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRYX_HANDLE_SCOPE_H */