mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implement jerry_get_own_property API function (#4612)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
a95e3e37e1
commit
29b7c8f8ff
@ -6994,6 +6994,77 @@ jerry_get_property_by_index (const jerry_value_t obj_val,
|
||||
- [jerry_set_property](#jerry_set_property)
|
||||
- [jerry_set_property_by_index](#jerry_set_property_by_index)
|
||||
|
||||
## jerry_get_own_property
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the own property value of an object with the given name. The function tells
|
||||
whether the property is found, and the receiver object can be specified as well.
|
||||
The receiver is passed as the `this` argument for getters, and the receiver
|
||||
argument for Proxy `get` traps.
|
||||
|
||||
*Notes*:
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it is no longer needed.
|
||||
- The `found_p` argument is ignored if its value is NULL.
|
||||
- The target value of `found_p` argument is set to false when the arguments are invalid, e.g. `obj_val` is not an object.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_get_own_property (const jerry_value_t obj_val,
|
||||
const jerry_value_t prop_name_val,
|
||||
const jerry_value_t receiver_val,
|
||||
bool *found_p);
|
||||
```
|
||||
|
||||
- `obj_val` - object value
|
||||
- `prop_name_val` - property name
|
||||
- `receiver_val` - receiver object
|
||||
- `found_p` - [out] true, if the property is found or obj_val is a Proxy object, false otherwise
|
||||
- return value
|
||||
- value of property, if success
|
||||
- thrown error, otherwise
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "stdio.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 *) "Object");
|
||||
|
||||
bool found;
|
||||
jerry_value_t prop_value = jerry_get_own_property (global_object, prop_name, global_object, &found);
|
||||
|
||||
if (found)
|
||||
{
|
||||
printf ("Property is found!\n");
|
||||
}
|
||||
|
||||
/* use "prop_value" then release it. */
|
||||
|
||||
jerry_release_value (prop_value);
|
||||
jerry_release_value (prop_name);
|
||||
jerry_release_value (global_object);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_get_property](#jerry_get_property)
|
||||
- [jerry_get_property_by_index](#jerry_get_property_by_index)
|
||||
|
||||
## jerry_get_internal_property
|
||||
|
||||
**Summary**
|
||||
|
||||
@ -3030,6 +3030,66 @@ jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */
|
||||
return jerry_return (ret_value);
|
||||
} /* jerry_get_property_by_index */
|
||||
|
||||
/**
|
||||
* Get the own property value of an object with the given name.
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return value of the property - if success
|
||||
* value marked with error flag - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_get_own_property (const jerry_value_t obj_val, /**< object value */
|
||||
const jerry_value_t prop_name_val, /**< property name (string value) */
|
||||
const jerry_value_t receiver_val, /**< receiver object value */
|
||||
bool *found_p) /**< [out] true, if the property is found
|
||||
* or obj_val is a Proxy object, false otherwise */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
if (found_p != NULL)
|
||||
{
|
||||
*found_p = false;
|
||||
}
|
||||
|
||||
if (!ecma_is_value_object (obj_val)
|
||||
|| !ecma_is_value_prop_name (prop_name_val)
|
||||
|| !ecma_is_value_object (receiver_val))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
|
||||
ecma_string_t *property_name_p = ecma_get_prop_name_from_value (prop_name_val);
|
||||
|
||||
#if JERRY_BUILTIN_PROXY
|
||||
if (ECMA_OBJECT_IS_PROXY (object_p))
|
||||
{
|
||||
if (found_p != NULL)
|
||||
{
|
||||
*found_p = true;
|
||||
}
|
||||
|
||||
return jerry_return (ecma_proxy_object_get (object_p, property_name_p, receiver_val));
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_PROXY */
|
||||
|
||||
ecma_value_t ret_value = ecma_op_object_find_own (receiver_val, object_p, property_name_p);
|
||||
|
||||
if (ecma_is_value_found (ret_value))
|
||||
{
|
||||
if (found_p != NULL)
|
||||
{
|
||||
*found_p = true;
|
||||
}
|
||||
|
||||
return jerry_return (ret_value);
|
||||
}
|
||||
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
} /* jerry_get_own_property */
|
||||
|
||||
/**
|
||||
* Get value of an internal property to the specified object with the given name.
|
||||
*
|
||||
|
||||
@ -687,6 +687,8 @@ bool jerry_delete_internal_property (const jerry_value_t obj_val, const jerry_va
|
||||
|
||||
jerry_value_t jerry_get_property (const jerry_value_t obj_val, const jerry_value_t prop_name_val);
|
||||
jerry_value_t jerry_get_property_by_index (const jerry_value_t obj_val, uint32_t index);
|
||||
jerry_value_t jerry_get_own_property (const jerry_value_t obj_val, const jerry_value_t prop_name_val,
|
||||
const jerry_value_t receiver_val, bool *found_p);
|
||||
jerry_value_t jerry_get_internal_property (const jerry_value_t obj_val, const jerry_value_t prop_name_val);
|
||||
jerry_value_t jerry_set_property (const jerry_value_t obj_val, const jerry_value_t prop_name_val,
|
||||
const jerry_value_t value_to_set);
|
||||
|
||||
@ -50,6 +50,7 @@ set(SOURCE_UNIT_TEST_MAIN_MODULES
|
||||
test-exec-stop.c
|
||||
test-external-string.c
|
||||
test-from-property-descriptor.c
|
||||
test-get-own-property.c
|
||||
test-has-property.c
|
||||
test-internal-properties.c
|
||||
test-jmem.c
|
||||
|
||||
212
tests/unit-core/test-get-own-property.c
Normal file
212
tests/unit-core/test-get-own-property.c
Normal file
@ -0,0 +1,212 @@
|
||||
/* 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 "jerryscript.h"
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
static jerry_value_t
|
||||
create_object (const char *source_p) /**< source script */
|
||||
{
|
||||
jerry_value_t result = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), 0);
|
||||
TEST_ASSERT (jerry_value_is_object (result));
|
||||
return result;
|
||||
} /* create_object */
|
||||
|
||||
static void
|
||||
compare_string (jerry_value_t value, /**< value to compare */
|
||||
const char *string_p) /**< expected value */
|
||||
{
|
||||
jerry_char_t string_buffer[64];
|
||||
|
||||
TEST_ASSERT (jerry_value_is_string (value));
|
||||
|
||||
size_t size = strlen (string_p);
|
||||
TEST_ASSERT (size <= sizeof (string_buffer));
|
||||
TEST_ASSERT (size == jerry_get_string_size (value));
|
||||
|
||||
jerry_string_to_char_buffer (value, string_buffer, (jerry_size_t) size);
|
||||
TEST_ASSERT (memcmp (string_p, string_buffer, size) == 0);
|
||||
} /* compare_string */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
TEST_INIT ();
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t pp_string = jerry_create_string ((const jerry_char_t *) "pp");
|
||||
jerry_value_t qq_string = jerry_create_string ((const jerry_char_t *) "qq");
|
||||
jerry_value_t rr_string = jerry_create_string ((const jerry_char_t *) "rr");
|
||||
|
||||
jerry_value_t object = create_object ("'use strict';\n"
|
||||
"({ pp:'A', get qq() { return 'B' } })");
|
||||
|
||||
jerry_value_t result = jerry_get_own_property (object, pp_string, object, NULL);
|
||||
compare_string (result, "A");
|
||||
jerry_release_value (result);
|
||||
|
||||
bool found = false;
|
||||
result = jerry_get_own_property (object, pp_string, object, &found);
|
||||
compare_string (result, "A");
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_get_own_property (object, qq_string, object, NULL);
|
||||
compare_string (result, "B");
|
||||
jerry_release_value (result);
|
||||
|
||||
found = false;
|
||||
result = jerry_get_own_property (object, qq_string, object, &found);
|
||||
compare_string (result, "B");
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_get_own_property (object, rr_string, object, NULL);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
found = true;
|
||||
result = jerry_get_own_property (object, rr_string, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
TEST_ASSERT (!found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (object);
|
||||
|
||||
object = create_object ("'use strict';\n"
|
||||
"Object.create({ pp:'Found!' })\n");
|
||||
|
||||
found = true;
|
||||
/* Does not check prototype. */
|
||||
result = jerry_get_own_property (object, pp_string, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
TEST_ASSERT (!found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (object);
|
||||
|
||||
object = create_object ("'use strict';\n"
|
||||
"var obj = Object.create({ get pp() { return this.qq } })\n"
|
||||
"Object.defineProperty(obj, 'qq', { value: 'Prop' })\n"
|
||||
"obj");
|
||||
jerry_value_t prototype = jerry_get_prototype (object);
|
||||
|
||||
TEST_ASSERT (jerry_value_is_object (prototype));
|
||||
found = false;
|
||||
result = jerry_get_own_property (prototype, pp_string, object, &found);
|
||||
compare_string (result, "Prop");
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (prototype);
|
||||
jerry_release_value (object);
|
||||
|
||||
/* Error cases. */
|
||||
jerry_value_t invalid_arg = jerry_create_null ();
|
||||
object = jerry_create_object ();
|
||||
|
||||
found = true;
|
||||
result = jerry_get_own_property (invalid_arg, pp_string, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
TEST_ASSERT (!found);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_get_own_property (object, pp_string, invalid_arg, NULL);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
found = true;
|
||||
result = jerry_get_own_property (object, invalid_arg, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
TEST_ASSERT (!found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (object);
|
||||
jerry_release_value (invalid_arg);
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_PROXY))
|
||||
{
|
||||
object = create_object ("'use strict';\n"
|
||||
"var proxy = new Proxy({}, {\n"
|
||||
" get: function(target, prop, receiver) {\n"
|
||||
" if (prop === 'qq') return\n"
|
||||
" return receiver[prop]\n"
|
||||
" }\n"
|
||||
"})\n"
|
||||
"var obj = Object.create(proxy)\n"
|
||||
"Object.defineProperty(obj, 'pp', { value: 'Prop' })\n"
|
||||
"obj");
|
||||
|
||||
prototype = jerry_get_prototype (object);
|
||||
found = false;
|
||||
result = jerry_get_own_property (prototype, pp_string, object, &found);
|
||||
compare_string (result, "Prop");
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
found = false;
|
||||
result = jerry_get_own_property (prototype, qq_string, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (prototype);
|
||||
jerry_release_value (object);
|
||||
|
||||
object = create_object ("'use strict';\n"
|
||||
"(new Proxy({}, {\n"
|
||||
" get: function(target, prop, receiver) {\n"
|
||||
" throw 'Error'\n"
|
||||
" }\n"
|
||||
"}))\n");
|
||||
|
||||
found = false;
|
||||
result = jerry_get_own_property (object, qq_string, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (object);
|
||||
}
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL))
|
||||
{
|
||||
object = create_object ("'use strict'\n"
|
||||
"var sym = Symbol();\n"
|
||||
"({ pp:sym, [sym]:'Prop' })");
|
||||
|
||||
found = false;
|
||||
jerry_value_t symbol = jerry_get_own_property (object, pp_string, object, &found);
|
||||
TEST_ASSERT (jerry_value_is_symbol (symbol));
|
||||
TEST_ASSERT (found);
|
||||
|
||||
found = false;
|
||||
result = jerry_get_own_property (object, symbol, object, &found);
|
||||
compare_string (result, "Prop");
|
||||
TEST_ASSERT (found);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (symbol);
|
||||
jerry_release_value (object);
|
||||
}
|
||||
|
||||
jerry_release_value (pp_string);
|
||||
jerry_release_value (qq_string);
|
||||
jerry_release_value (rr_string);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
} /* main */
|
||||
Loading…
x
Reference in New Issue
Block a user