Improve arguments object (#4145)
- Enhancement: Arguments object properties are now lazy instantiated - Bugfix: Mapped arguments object instantiated properties cannot be lcached - Bugfix: Mapped arguments should be constructed even if 0 formal parameters or arguments are provided - Update: remove 'caller' property of unmapped arguments object JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
@@ -0,0 +1,507 @@
|
||||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-arguments-object.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "jrt.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmaargumentsobject ECMA arguments object related routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Arguments object creation operation.
|
||||
*
|
||||
* See also: ECMA-262 v5, 10.6
|
||||
*/
|
||||
void
|
||||
ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */
|
||||
ecma_object_t *lex_env_p, /**< lexical environment the Arguments
|
||||
* object is created for */
|
||||
vm_frame_ctx_shared_args_t *shared_p) /**< shared context data */
|
||||
{
|
||||
const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p;
|
||||
uint16_t formal_params_number;
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
formal_params_number = ((cbc_uint16_arguments_t *) bytecode_data_p)->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
formal_params_number = ((cbc_uint8_arguments_t *) bytecode_data_p)->argument_end;
|
||||
}
|
||||
|
||||
uint32_t object_size = sizeof (ecma_unmapped_arguments_t);
|
||||
uint32_t saved_arg_count = JERRY_MAX (shared_p->arg_list_len, formal_params_number);
|
||||
uint8_t flags = ECMA_ARGUMENTS_OBJECT_NO_FLAGS;
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
flags = ECMA_ARGUMENTS_OBJECT_MAPPED;
|
||||
object_size = sizeof (ecma_mapped_arguments_t);
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||
{
|
||||
flags |= ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
}
|
||||
|
||||
ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE),
|
||||
object_size + (saved_arg_count * sizeof (ecma_value_t)),
|
||||
ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
|
||||
|
||||
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p;
|
||||
|
||||
arguments_p->header.u.pseudo_array.type = ECMA_PSEUDO_ARRAY_ARGUMENTS;
|
||||
arguments_p->header.u.pseudo_array.extra_info = flags;
|
||||
arguments_p->header.u.pseudo_array.u1.formal_params_number = formal_params_number;
|
||||
arguments_p->header.u.pseudo_array.u2.arguments_number = 0;
|
||||
arguments_p->callee = ecma_make_object_value (func_obj_p);
|
||||
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) obj_p) + object_size);
|
||||
|
||||
for (uint32_t i = 0; i < shared_p->arg_list_len; i++)
|
||||
{
|
||||
argv_p[i] = ecma_copy_value_if_not_object (shared_p->arg_list_p[i]);
|
||||
}
|
||||
|
||||
for (uint32_t i = shared_p->arg_list_len; i < saved_arg_count; i++)
|
||||
{
|
||||
argv_p[i] = ECMA_VALUE_INITIALIZED;
|
||||
}
|
||||
|
||||
arguments_p->header.u.pseudo_array.u2.arguments_number = shared_p->arg_list_len;
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) obj_p;
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->lex_env, lex_env_p);
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE)
|
||||
{
|
||||
mapped_arguments_p->u.byte_code_p = (ecma_compiled_code_t *) bytecode_data_p;
|
||||
}
|
||||
else
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
{
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->u.byte_code, bytecode_data_p);
|
||||
}
|
||||
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
||||
|
||||
ecma_value_t *formal_parameter_start_p;
|
||||
formal_parameter_start_p = ecma_compiled_code_resolve_arguments_start ((ecma_compiled_code_t *) bytecode_data_p);
|
||||
|
||||
for (uint32_t i = 0; i < formal_params_number; i++)
|
||||
{
|
||||
/* For legacy (non-strict) argument definition the trailing duplicated arguments cannot be lazy instantiated
|
||||
E.g: function f (a,a,a,a) {} */
|
||||
if (JERRY_UNLIKELY (ecma_is_value_empty (formal_parameter_start_p[i])))
|
||||
{
|
||||
ecma_property_value_t *prop_value_p;
|
||||
ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i);
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
prop_name_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
|
||||
prop_value_p->value = argv_p[i];
|
||||
argv_p[i] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t prop_flags = ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) ? ECMA_PROPERTY_FIXED
|
||||
: ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
prop_value_p = ecma_create_named_data_property (lex_env_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS),
|
||||
prop_flags,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_object_value (obj_p);
|
||||
ecma_deref_object (obj_p);
|
||||
} /* ecma_op_create_arguments_object */
|
||||
|
||||
/**
|
||||
* [[DefineOwnProperty]] ecma Arguments object's operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||
* ECMA-262 v5, 10.6
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
const ecma_property_descriptor_t *property_desc_p) /**< property
|
||||
* descriptor */
|
||||
{
|
||||
/* 3. */
|
||||
ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p,
|
||||
property_name_p,
|
||||
property_desc_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value)
|
||||
|| !(((ecma_extended_object_t *) object_p)->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p;
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index >= mapped_arguments_p->unmapped.header.u.pseudo_array.u1.formal_params_number)
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
|
||||
|
||||
if (!ecma_is_value_empty (argv_p[index]))
|
||||
{
|
||||
if (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
|
||||
{
|
||||
ecma_free_value_if_not_object (argv_p[index]);
|
||||
argv_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
|
||||
|
||||
ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p,
|
||||
name_p,
|
||||
property_desc_p->value,
|
||||
true);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
}
|
||||
|
||||
if ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
|
||||
&& !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE))
|
||||
{
|
||||
ecma_free_value_if_not_object (argv_p[index]);
|
||||
argv_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_arguments_object_define_own_property */
|
||||
|
||||
/**
|
||||
* [[Delete]] ecma Arguments object's operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||
* ECMA-262 v5, 10.6
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_arguments_object_delete (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
bool is_throw) /**< flag that controls failure handling */
|
||||
{
|
||||
/* 3. */
|
||||
ecma_value_t ret_value = ecma_op_general_object_delete (object_p, property_name_p, is_throw);
|
||||
|
||||
if (!ecma_is_value_true (ret_value)
|
||||
|| !(((ecma_extended_object_t *) object_p)->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p;
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index < mapped_arguments_p->unmapped.header.u.pseudo_array.u1.formal_params_number)
|
||||
{
|
||||
ecma_free_value_if_not_object (argv_p[index]);
|
||||
argv_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_arguments_object_delete */
|
||||
|
||||
/**
|
||||
* Try to lazy instantiate the given property of a mapped/unmapped arguments object
|
||||
*
|
||||
* @return pointer property, if one was instantiated,
|
||||
* NULL - otherwise.
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *property_name_p) /**< property's name */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
|
||||
JERRY_ASSERT (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
|
||||
|
||||
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p;
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
|
||||
ecma_property_value_t *prop_value_p;
|
||||
ecma_property_t *prop_p = NULL;
|
||||
uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number;
|
||||
uint8_t flags = arguments_p->header.u.pseudo_array.extra_info;
|
||||
|
||||
if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1);
|
||||
}
|
||||
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX)
|
||||
{
|
||||
if (index >= arguments_number
|
||||
|| ecma_is_value_empty (argv_p[index])
|
||||
|| argv_p[index] == ECMA_VALUE_INITIALIZED)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
&prop_p);
|
||||
|
||||
/* Passing the reference */
|
||||
prop_value_p->value = argv_p[index];
|
||||
|
||||
/* Pevent reinitialization */
|
||||
if ((flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
&& index < arguments_p->header.u.pseudo_array.u1.formal_params_number)
|
||||
{
|
||||
argv_p[index] = ECMA_VALUE_INITIALIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
return prop_p;
|
||||
}
|
||||
|
||||
if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH)
|
||||
&& !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED))
|
||||
{
|
||||
arguments_p->header.u.pseudo_array.extra_info |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED;
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
&prop_p);
|
||||
|
||||
prop_value_p->value = ecma_make_uint32_value (arguments_number);
|
||||
}
|
||||
|
||||
if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE)
|
||||
&& !(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED))
|
||||
{
|
||||
arguments_p->header.u.pseudo_array.extra_info |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED;
|
||||
|
||||
if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
prop_value_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
&prop_p);
|
||||
|
||||
prop_value_p->value = arguments_p->callee;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
|
||||
|
||||
prop_value_p = ecma_create_named_accessor_property (object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE),
|
||||
thrower_p,
|
||||
thrower_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
&prop_p);
|
||||
}
|
||||
return prop_p;
|
||||
}
|
||||
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLER)
|
||||
&& !(arguments_p->header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED))
|
||||
{
|
||||
if (arguments_p->header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
arguments_p->header.u.pseudo_array.extra_info |= ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED;
|
||||
|
||||
ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
|
||||
|
||||
prop_value_p = ecma_create_named_accessor_property (object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_CALLER),
|
||||
thrower_p,
|
||||
thrower_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
&prop_p);
|
||||
return prop_p;
|
||||
}
|
||||
#else /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR);
|
||||
|
||||
if (property_name_p == symbol_p
|
||||
&& !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED))
|
||||
{
|
||||
arguments_p->header.u.pseudo_array.extra_info |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED;
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (object_p,
|
||||
symbol_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
&prop_p);
|
||||
|
||||
prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT),
|
||||
LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (prop_value_p->value));
|
||||
ecma_deref_object (ecma_get_object_from_value (prop_value_p->value));
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (symbol_p);
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
return prop_p;
|
||||
} /* ecma_op_arguments_object_try_to_lazy_instantiate_property */
|
||||
|
||||
/**
|
||||
* List names of an arguments object's lazy instantiated properties
|
||||
*/
|
||||
void
|
||||
ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< arguments object */
|
||||
ecma_collection_t *prop_names_p, /**< prop name collection */
|
||||
ecma_property_counter_t *prop_counter_p) /**< prop counter */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
|
||||
JERRY_ASSERT (((ecma_extended_object_t *) obj_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
|
||||
|
||||
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p;
|
||||
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
|
||||
uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number;
|
||||
uint8_t flags = arguments_p->header.u.pseudo_array.extra_info;
|
||||
|
||||
if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1);
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < arguments_number; index++)
|
||||
{
|
||||
if (!ecma_is_value_empty (argv_p[index]))
|
||||
{
|
||||
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
|
||||
ecma_collection_push_back (prop_names_p, ecma_make_string_value (index_string_p));
|
||||
prop_counter_p->array_index_named_props++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED))
|
||||
{
|
||||
ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
|
||||
prop_counter_p->string_named_props++;
|
||||
}
|
||||
|
||||
if (!(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED))
|
||||
{
|
||||
ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLEE));
|
||||
prop_counter_p->string_named_props++;
|
||||
}
|
||||
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
if (!(flags & (ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED | ECMA_ARGUMENTS_OBJECT_MAPPED)))
|
||||
{
|
||||
ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER));
|
||||
prop_counter_p->string_named_props++;
|
||||
}
|
||||
#else /* ENABLED (JERRY_ESNEXT) */
|
||||
if (!(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED))
|
||||
{
|
||||
ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR);
|
||||
ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (symbol_p));
|
||||
prop_counter_p->symbol_named_props++;
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
} /* ecma_op_arguments_object_list_lazy_property_names */
|
||||
|
||||
/**
|
||||
* Get the formal parameter name corresponding to the given property index
|
||||
*
|
||||
* @return pointer to the formal parameter name
|
||||
*/
|
||||
ecma_string_t *
|
||||
ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, /**< mapped arguments
|
||||
* object */
|
||||
uint32_t index) /**< formal parameter index */
|
||||
{
|
||||
JERRY_ASSERT (mapped_arguments_p->unmapped.header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED);
|
||||
JERRY_ASSERT (index < mapped_arguments_p->unmapped.header.u.pseudo_array.u1.formal_params_number);
|
||||
|
||||
ecma_compiled_code_t *byte_code_p;
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (mapped_arguments_p->unmapped.header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE)
|
||||
{
|
||||
byte_code_p = mapped_arguments_p->u.byte_code_p;
|
||||
}
|
||||
else
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
{
|
||||
byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code);
|
||||
}
|
||||
|
||||
ecma_value_t *formal_param_names_p = ecma_compiled_code_resolve_arguments_start (byte_code_p);
|
||||
|
||||
return ecma_get_string_from_value (formal_param_names_p[index]);
|
||||
} /* ecma_op_arguments_object_get_formal_parameter */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
+15
-3
@@ -13,8 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_OBJECTS_ARGUMENTS_H
|
||||
#define ECMA_OBJECTS_ARGUMENTS_H
|
||||
#ifndef ECMA_ARGUMENTS_OBJECT_H
|
||||
#define ECMA_ARGUMENTS_OBJECT_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
@@ -30,4 +30,16 @@ ecma_value_t
|
||||
ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p,
|
||||
const ecma_property_descriptor_t *property_desc_p);
|
||||
|
||||
#endif /* !ECMA_OBJECTS_ARGUMENTS_H */
|
||||
ecma_property_t *
|
||||
ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p,
|
||||
ecma_string_t *property_name_p);
|
||||
|
||||
void
|
||||
ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p,
|
||||
ecma_collection_t *prop_names_p,
|
||||
ecma_property_counter_t *prop_counter_p);
|
||||
|
||||
ecma_string_t *
|
||||
ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p,
|
||||
uint32_t index);
|
||||
#endif /* !ECMA_ARGUMENTS_OBJECT_H */
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "ecma-objects-arguments.h"
|
||||
#include "ecma-arguments-object.h"
|
||||
#include "ecma-proxy-object.h"
|
||||
#include "ecma-symbol-object.h"
|
||||
#include "jcontext.h"
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-arguments.h"
|
||||
#include "ecma-objects-general.h"
|
||||
|
||||
#include "jrt.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmafunctionobject ECMA Function object related routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Arguments object creation operation.
|
||||
*
|
||||
* See also: ECMA-262 v5, 10.6
|
||||
*/
|
||||
void
|
||||
ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */
|
||||
ecma_object_t *lex_env_p, /**< lexical environment the Arguments
|
||||
object is created for */
|
||||
vm_frame_ctx_shared_args_t *shared_p) /**< shared context dta */
|
||||
{
|
||||
const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p;
|
||||
bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0;
|
||||
|
||||
uint32_t formal_params_number;
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
|
||||
formal_params_number = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
|
||||
formal_params_number = args_p->argument_end;
|
||||
}
|
||||
|
||||
ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
|
||||
ecma_object_t *obj_p;
|
||||
uint32_t arguments_number = shared_p->arg_list_len;
|
||||
|
||||
if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
&& arguments_number > 0
|
||||
&& formal_params_number > 0)
|
||||
{
|
||||
size_t formal_params_size = formal_params_number * sizeof (ecma_value_t);
|
||||
|
||||
obj_p = ecma_create_object (prototype_p,
|
||||
sizeof (ecma_extended_object_t) + formal_params_size,
|
||||
ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_ARGUMENTS;
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.pseudo_array.u2.lex_env_cp, lex_env_p);
|
||||
|
||||
ext_object_p->u.pseudo_array.u1.length = (uint16_t) formal_params_number;
|
||||
|
||||
ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_data_p;
|
||||
byte_p += ((size_t) bytecode_data_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
byte_p -= formal_params_size;
|
||||
|
||||
memcpy (arg_literal_p, byte_p, formal_params_size);
|
||||
|
||||
for (uint32_t i = 0; i < formal_params_number; i++)
|
||||
{
|
||||
if (arg_literal_p[i] != ECMA_VALUE_EMPTY)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[i]);
|
||||
ecma_ref_ecma_string (name_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
obj_p = ecma_create_object (prototype_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_ARGUMENTS_UL;
|
||||
}
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
/* 11.a, 11.b */
|
||||
for (uint32_t index = 0;
|
||||
index < arguments_number;
|
||||
index++)
|
||||
{
|
||||
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
index_string_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
const ecma_value_t *arguments_list_p = shared_p->arg_list_p;
|
||||
prop_value_p->value = ecma_copy_value_if_not_object (arguments_list_p[index]);
|
||||
|
||||
ecma_deref_ecma_string (index_string_p);
|
||||
}
|
||||
|
||||
/* 7. */
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_uint32_value (arguments_number);
|
||||
|
||||
ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/* ECMAScript v6, 9.4.4.6.7, 9.4.4.7.22 */
|
||||
ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR);
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
symbol_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
ecma_deref_ecma_string (symbol_p);
|
||||
prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT),
|
||||
LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (prop_value_p->value));
|
||||
ecma_deref_object (ecma_get_object_from_value (prop_value_p->value));
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* 13. */
|
||||
if (!is_strict)
|
||||
{
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE),
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_object_value (func_obj_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
|
||||
|
||||
/* 14. */
|
||||
prop_desc = ecma_make_empty_property_descriptor ();
|
||||
{
|
||||
prop_desc.flags = (ECMA_PROP_IS_GET_DEFINED
|
||||
| ECMA_PROP_IS_SET_DEFINED
|
||||
| ECMA_PROP_IS_ENUMERABLE_DEFINED
|
||||
| ECMA_PROP_IS_CONFIGURABLE_DEFINED);
|
||||
}
|
||||
prop_desc.set_p = thrower_p;
|
||||
prop_desc.get_p = thrower_p;
|
||||
|
||||
ecma_value_t completion = ecma_op_object_define_own_property (obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE),
|
||||
&prop_desc);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
|
||||
completion = ecma_op_object_define_own_property (obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_CALLER),
|
||||
&prop_desc);
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
}
|
||||
|
||||
ecma_string_t *arguments_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS);
|
||||
|
||||
if (is_strict)
|
||||
{
|
||||
ecma_op_create_immutable_binding (lex_env_p,
|
||||
arguments_string_p,
|
||||
ecma_make_object_value (obj_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_value_t completion = ecma_op_create_mutable_binding (lex_env_p,
|
||||
arguments_string_p,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
|
||||
completion = ecma_op_set_mutable_binding (lex_env_p,
|
||||
arguments_string_p,
|
||||
ecma_make_object_value (obj_p),
|
||||
false);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
}
|
||||
|
||||
ecma_deref_object (obj_p);
|
||||
} /* ecma_op_create_arguments_object */
|
||||
|
||||
/**
|
||||
* [[DefineOwnProperty]] ecma Arguments object's operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||
* ECMA-262 v5, 10.6
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
const ecma_property_descriptor_t *property_desc_p) /**< property
|
||||
* descriptor */
|
||||
{
|
||||
/* 3. */
|
||||
ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p,
|
||||
property_name_p,
|
||||
property_desc_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index == ECMA_STRING_NOT_ARRAY_INDEX)
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (index >= ext_object_p->u.pseudo_array.u1.length)
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
|
||||
if (arg_literal_p[index] == ECMA_VALUE_EMPTY)
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[index]);
|
||||
|
||||
if (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
arg_literal_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
|
||||
{
|
||||
/* emulating execution of function described by MakeArgSetter */
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
||||
|
||||
ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p,
|
||||
name_p,
|
||||
property_desc_p->value,
|
||||
true);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
}
|
||||
|
||||
if ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
|
||||
&& !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
arg_literal_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_arguments_object_define_own_property */
|
||||
|
||||
/**
|
||||
* [[Delete]] ecma Arguments object's operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||
* ECMA-262 v5, 10.6
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_arguments_object_delete (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
bool is_throw) /**< flag that controls failure handling */
|
||||
{
|
||||
/* 3. */
|
||||
ecma_value_t ret_value = ecma_op_general_object_delete (object_p, property_name_p, is_throw);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (ret_value));
|
||||
|
||||
if (ecma_is_value_true (ret_value))
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (index < ext_object_p->u.pseudo_array.u1.length)
|
||||
{
|
||||
ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
|
||||
if (arg_literal_p[index] != ECMA_VALUE_EMPTY)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[index]);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
arg_literal_p[index] = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = ECMA_VALUE_TRUE;
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_arguments_object_delete */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -22,8 +22,9 @@
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "ecma-string-object.h"
|
||||
#include "ecma-objects-arguments.h"
|
||||
#include "ecma-arguments-object.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-proxy-object.h"
|
||||
@@ -80,7 +81,6 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
JERRY_ASSERT (property_name_p != NULL);
|
||||
JERRY_ASSERT (options == ECMA_PROPERTY_GET_NO_OPTIONS
|
||||
|| options == ECMA_PROPERTY_GET_HAS_OWN_PROP
|
||||
|| property_ref_p != NULL);
|
||||
|
||||
ecma_object_type_t type = ecma_get_object_type (object_p);
|
||||
@@ -256,46 +256,67 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
else
|
||||
{
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
switch (type)
|
||||
{
|
||||
if (options & ECMA_PROPERTY_GET_VALUE)
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
{
|
||||
/* Get length virtual property. */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
|
||||
uint32_t len;
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
if (options & ECMA_PROPERTY_GET_VALUE)
|
||||
{
|
||||
/* Get length virtual property. */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
|
||||
property_ref_p->virtual_value = ecma_make_uint32_value (len);
|
||||
uint32_t len;
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
|
||||
property_ref_p->virtual_value = ecma_make_uint32_value (len);
|
||||
}
|
||||
|
||||
return ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||
{
|
||||
if (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
{
|
||||
property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
return ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
|
||||
if (property_p == NULL)
|
||||
@@ -304,36 +325,47 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
}
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_PSEUDO_ARRAY
|
||||
&& (options & ECMA_PROPERTY_GET_HAS_OWN_PROP))
|
||||
&& ((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS
|
||||
&& (((ecma_extended_object_t *) object_p)->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED))
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index < ext_object_p->u.pseudo_array.u1.formal_params_number)
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX
|
||||
&& index < ext_object_p->u.pseudo_array.u1.length)
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
|
||||
|
||||
if (!ecma_is_value_empty (argv_p[index]))
|
||||
{
|
||||
ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
|
||||
if (arg_Literal_p[index] != ECMA_VALUE_EMPTY)
|
||||
#if ENABLED (JERRY_LCACHE)
|
||||
/* Mapped arguments initialized properties MUST not be lcached */
|
||||
if (ecma_is_property_lcached (property_p))
|
||||
{
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]);
|
||||
jmem_cpointer_t prop_name_cp;
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
|
||||
ecma_named_data_property_assign_value (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
binding_value);
|
||||
ecma_free_value (binding_value);
|
||||
if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (property_name_p)))
|
||||
{
|
||||
prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (property_name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ECMA_SET_NON_NULL_POINTER (prop_name_cp, property_name_p);
|
||||
}
|
||||
ecma_lcache_invalidate (object_p, prop_name_cp, property_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_LCACHE) */
|
||||
ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
|
||||
|
||||
ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, name_p, true);
|
||||
|
||||
ecma_named_data_property_assign_value (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
binding_value);
|
||||
ecma_free_value (binding_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,26 +512,23 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS
|
||||
&& ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX
|
||||
&& index < ext_object_p->u.pseudo_array.u1.length)
|
||||
if (index < ext_object_p->u.pseudo_array.u1.formal_params_number)
|
||||
{
|
||||
ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
|
||||
|
||||
if (arg_Literal_p[index] != ECMA_VALUE_EMPTY)
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
|
||||
|
||||
if (!ecma_is_value_empty (argv_p[index]))
|
||||
{
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]);
|
||||
ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
return ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
return ecma_op_get_binding_value (lex_env_p, name_p, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -572,41 +601,62 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
else
|
||||
{
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
switch (type)
|
||||
{
|
||||
/* Get length virtual property. */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
|
||||
uint32_t len;
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
{
|
||||
/* Get length virtual property. */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
|
||||
return ecma_make_uint32_value (len);
|
||||
}
|
||||
uint32_t len;
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
|
||||
return ecma_make_uint32_value (len);
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||
{
|
||||
if (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
{
|
||||
property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (property_p == NULL)
|
||||
@@ -1207,26 +1257,22 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS
|
||||
&& (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED))
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX
|
||||
&& index < ext_object_p->u.pseudo_array.u1.length)
|
||||
if (index < ext_object_p->u.pseudo_array.u1.formal_params_number)
|
||||
{
|
||||
ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
|
||||
|
||||
if (arg_Literal_p[index] != ECMA_VALUE_EMPTY)
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
|
||||
|
||||
if (!ecma_is_value_empty (argv_p[index]))
|
||||
{
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]);
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true);
|
||||
ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
|
||||
ecma_op_set_mutable_binding (lex_env_p, name_p, value, true);
|
||||
return ECMA_VALUE_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1282,27 +1328,6 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
if (type == ECMA_OBJECT_TYPE_CLASS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX)
|
||||
{
|
||||
ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
|
||||
ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);
|
||||
|
||||
if (index < ecma_string_get_length (prim_value_str_p))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_get_object_is_builtin (object_p))
|
||||
{
|
||||
if (type == ECMA_OBJECT_TYPE_FUNCTION && ecma_builtin_function_is_routine (object_p))
|
||||
@@ -1320,32 +1345,74 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
||||
property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
else
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */
|
||||
if ((ecma_string_is_length (property_name_p))
|
||||
&& (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp)))
|
||||
switch (type)
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
case ECMA_OBJECT_TYPE_CLASS:
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index != ECMA_STRING_NOT_ARRAY_INDEX)
|
||||
{
|
||||
ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value;
|
||||
ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p);
|
||||
|
||||
if (index < ecma_string_get_length (prim_value_str_p))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */
|
||||
if ((ecma_string_is_length (property_name_p))
|
||||
&& (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp)))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||
{
|
||||
if (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
{
|
||||
property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1440,7 +1507,8 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS
|
||||
&& ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
return ecma_builtin_helper_def_prop (object_p,
|
||||
property_name_p,
|
||||
@@ -2057,6 +2125,10 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */
|
||||
{
|
||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||
{
|
||||
if (((ecma_extended_object_t *) obj_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
|
||||
{
|
||||
ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p);
|
||||
}
|
||||
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
if (ecma_object_is_typedarray (obj_p))
|
||||
{
|
||||
@@ -3052,7 +3124,7 @@ ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, /**< the obje
|
||||
ecma_property_t property = ecma_op_object_get_own_property (object_p,
|
||||
property_name_p,
|
||||
NULL,
|
||||
ECMA_PROPERTY_GET_HAS_OWN_PROP);
|
||||
ECMA_PROPERTY_GET_NO_OPTIONS);
|
||||
|
||||
return property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
|
||||
} /* ecma_op_ordinary_object_has_own_property */
|
||||
|
||||
Reference in New Issue
Block a user