Implement the core of Proxy object (#3562)

- Internal routines of the of the proxy object are unimplemented
 - For-in enumerate with proxy target is currently not supported

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2020-02-28 14:41:59 +01:00
committed by GitHub
parent 9b393ee2ea
commit 4e136c8973
57 changed files with 3017 additions and 397 deletions
+128 -21
View File
@@ -35,6 +35,7 @@
#include "ecma-objects-general.h"
#include "ecma-regexp-object.h"
#include "ecma-promise-object.h"
#include "ecma-proxy-object.h"
#include "ecma-symbol-object.h"
#include "ecma-typedarray-object.h"
#include "opcodes.h"
@@ -803,6 +804,25 @@ jerry_value_is_promise (const jerry_value_t value) /**< api value */
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
} /* jerry_value_is_promise */
/**
* Check if the specified value is a proxy object.
*
* @return true - if the specified value is a proxy object,
* false - otherwise
*/
bool
jerry_value_is_proxy (const jerry_value_t value) /**< api value */
{
jerry_assert_api_available ();
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
return (ecma_is_value_object (value)
&& ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (value)));
#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
JERRY_UNUSED (value);
return false;
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
} /* jerry_value_is_proxy */
/**
* Check if the specified value is string.
*
@@ -966,6 +986,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
|| feature == JERRY_FEATURE_DATAVIEW
#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
|| feature == JERRY_FEATURE_PROXY
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
#if ENABLED (JERRY_BUILTIN_DATE)
|| feature == JERRY_FEATURE_DATE
#endif /* ENABLED (JERRY_BUILTIN_DATE) */
@@ -1585,6 +1608,34 @@ jerry_create_promise (void)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
} /* jerry_create_promise */
/**
* Create a new Proxy object with the given target and handler
*
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return value of the created Proxy object
*/
jerry_value_t
jerry_create_proxy (const jerry_value_t target, /**< target argument */
const jerry_value_t handler) /**< handler argument */
{
jerry_assert_api_available ();
if (ecma_is_value_error_reference (target)
|| ecma_is_value_error_reference (handler))
{
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
}
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
ecma_object_t *proxy_p = ecma_proxy_create (target, handler);
return jerry_return (proxy_p == NULL ? ECMA_VALUE_ERROR : ecma_make_object_value (proxy_p));
#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Proxy is not supported.")));
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
} /* jerry_create_proxy */
/**
* Create string from a valid UTF-8 string
*
@@ -1986,8 +2037,8 @@ jerry_substring_to_utf8_char_buffer (const jerry_value_t value, /**< input strin
/**
* Checks whether the object or it's prototype objects have the given property.
*
* @return true - if the property exists
* false - otherwise
* @return raised error - if the operation fail
* true/false API value - depend on whether the property exists
*/
jerry_value_t
jerry_has_property (const jerry_value_t obj_val, /**< object value */
@@ -2001,17 +2052,15 @@ jerry_has_property (const jerry_value_t obj_val, /**< object value */
return ECMA_VALUE_FALSE;
}
bool has_property = ecma_op_object_has_property (ecma_get_object_from_value (obj_val),
ecma_get_prop_name_from_value (prop_name_val));
return ecma_make_boolean_value (has_property);
return ecma_op_object_has_property (ecma_get_object_from_value (obj_val),
ecma_get_prop_name_from_value (prop_name_val));
} /* jerry_has_property */
/**
* Checks whether the object has the given property.
*
* @return true - if the property exists
* false - otherwise
* @return ECMA_VALUE_ERROR - if the operation raises error
* ECMA_VALUE_{TRUE, FALSE} - based on whether the property exists
*/
jerry_value_t
jerry_has_own_property (const jerry_value_t obj_val, /**< object value */
@@ -2025,10 +2074,26 @@ jerry_has_own_property (const jerry_value_t obj_val, /**< object value */
return ECMA_VALUE_FALSE;
}
bool has_property = ecma_op_object_has_own_property (ecma_get_object_from_value (obj_val),
ecma_get_prop_name_from_value (prop_name_val));
ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name_val);
return ecma_make_boolean_value (has_property);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_OBJECT_IS_PROXY (obj_p))
{
ecma_property_descriptor_t prop_desc;
ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc);
if (ecma_is_value_true (status))
{
ecma_free_property_descriptor (&prop_desc);
}
return jerry_return (status);
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
return ecma_make_boolean_value (ecma_op_ordinary_object_has_own_property (obj_p, prop_name_p));
} /* jerry_has_own_property */
/**
@@ -2092,6 +2157,15 @@ jerry_delete_property (const jerry_value_t obj_val, /**< object value */
ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val),
ecma_get_prop_name_from_value (prop_name_val),
false);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_IS_VALUE_ERROR (ret_value))
{
// TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
jcontext_release_exception ();
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
return ecma_is_value_true (ret_value);
} /* jerry_delete_property */
@@ -2118,6 +2192,14 @@ jerry_delete_property_by_index (const jerry_value_t obj_val, /**< object value *
false);
ecma_deref_ecma_string (str_idx_p);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_IS_VALUE_ERROR (ret_value))
{
// TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
jcontext_release_exception ();
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
return ecma_is_value_true (ret_value);
} /* jerry_delete_property_by_index */
@@ -2560,9 +2642,19 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val
ecma_property_descriptor_t prop_desc;
if (!ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val),
ecma_get_prop_name_from_value (prop_name_val),
&prop_desc))
ecma_value_t status = ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val),
ecma_get_prop_name_from_value (prop_name_val),
&prop_desc);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_IS_VALUE_ERROR (status))
{
// TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
jcontext_release_exception ();
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
if (!ecma_is_value_true (status))
{
return false;
}
@@ -2803,6 +2895,13 @@ jerry_get_prototype (const jerry_value_t obj_val) /**< object value */
ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_OBJECT_IS_PROXY (obj_p))
{
return jerry_return (ecma_proxy_object_get_prototype_of (obj_p));
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
if (obj_p->u2.prototype_cp == JMEM_CP_NULL)
{
return ECMA_VALUE_NULL;
@@ -2834,16 +2933,14 @@ jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
}
ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
if (ecma_is_value_null (proto_obj_val))
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_OBJECT_IS_PROXY (obj_p))
{
obj_p->u2.prototype_cp = JMEM_CP_NULL;
}
else
{
ECMA_SET_NON_NULL_POINTER (obj_p->u2.prototype_cp, ecma_get_object_from_value (proto_obj_val));
return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto_obj_val));
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
return ECMA_VALUE_TRUE;
return ecma_op_ordinary_object_set_prototype_of (obj_p, proto_obj_val);
} /* jerry_set_prototype */
/**
@@ -3073,6 +3170,16 @@ jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_collection_t *names_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE_PROTOTYPE);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (names_p == NULL)
{
// TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
jcontext_release_exception ();
return false;
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
ecma_value_t *buffer_p = names_p->buffer_p;
ecma_value_t property_value = ECMA_VALUE_EMPTY;