1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci/** 17425bb815Sopenharmony_ci * Implementation of ECMA GetValue and PutValue 18425bb815Sopenharmony_ci */ 19425bb815Sopenharmony_ci 20425bb815Sopenharmony_ci#include "ecma-builtins.h" 21425bb815Sopenharmony_ci#include "ecma-exceptions.h" 22425bb815Sopenharmony_ci#include "ecma-gc.h" 23425bb815Sopenharmony_ci#include "ecma-helpers.h" 24425bb815Sopenharmony_ci#include "ecma-lex-env.h" 25425bb815Sopenharmony_ci#include "ecma-objects.h" 26425bb815Sopenharmony_ci#include "ecma-function-object.h" 27425bb815Sopenharmony_ci#include "ecma-objects-general.h" 28425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h" 29425bb815Sopenharmony_ci#include "ecma-reference.h" 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 32425bb815Sopenharmony_ci * @{ 33425bb815Sopenharmony_ci * 34425bb815Sopenharmony_ci * \addtogroup lexicalenvironment Lexical environment 35425bb815Sopenharmony_ci * @{ 36425bb815Sopenharmony_ci */ 37425bb815Sopenharmony_ci 38425bb815Sopenharmony_ci/** 39425bb815Sopenharmony_ci * GetValue operation part 40425bb815Sopenharmony_ci * 41425bb815Sopenharmony_ci * See also: ECMA-262 v5, 8.7.1, sections 3 and 5 42425bb815Sopenharmony_ci * 43425bb815Sopenharmony_ci * @return ecma value 44425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 45425bb815Sopenharmony_ci */ 46425bb815Sopenharmony_ciecma_value_t 47425bb815Sopenharmony_ciecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ 48425bb815Sopenharmony_ci ecma_object_t **ref_base_lex_env_p, /**< [out] reference's base (lexical environment) */ 49425bb815Sopenharmony_ci ecma_string_t *name_p) /**< variable name */ 50425bb815Sopenharmony_ci{ 51425bb815Sopenharmony_ci JERRY_ASSERT (lex_env_p != NULL 52425bb815Sopenharmony_ci && ecma_is_lexical_environment (lex_env_p)); 53425bb815Sopenharmony_ci 54425bb815Sopenharmony_ci while (true) 55425bb815Sopenharmony_ci { 56425bb815Sopenharmony_ci switch (ecma_get_lex_env_type (lex_env_p)) 57425bb815Sopenharmony_ci { 58425bb815Sopenharmony_ci case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: 59425bb815Sopenharmony_ci { 60425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); 61425bb815Sopenharmony_ci 62425bb815Sopenharmony_ci if (property_p != NULL) 63425bb815Sopenharmony_ci { 64425bb815Sopenharmony_ci *ref_base_lex_env_p = lex_env_p; 65425bb815Sopenharmony_ci ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 66425bb815Sopenharmony_ci 67425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 68425bb815Sopenharmony_ci if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) 69425bb815Sopenharmony_ci { 70425bb815Sopenharmony_ci return ecma_raise_reference_error (ECMA_ERR_MSG ("Variables declared by let/const must be" 71425bb815Sopenharmony_ci " initialized before reading their value.")); 72425bb815Sopenharmony_ci } 73425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 74425bb815Sopenharmony_ci 75425bb815Sopenharmony_ci return ecma_fast_copy_value (property_value_p->value); 76425bb815Sopenharmony_ci } 77425bb815Sopenharmony_ci break; 78425bb815Sopenharmony_ci } 79425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 80425bb815Sopenharmony_ci case ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND: 81425bb815Sopenharmony_ci { 82425bb815Sopenharmony_ci break; 83425bb815Sopenharmony_ci } 84425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 85425bb815Sopenharmony_ci default: 86425bb815Sopenharmony_ci { 87425bb815Sopenharmony_ci JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); 88425bb815Sopenharmony_ci 89425bb815Sopenharmony_ci ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p); 90425bb815Sopenharmony_ci 91425bb815Sopenharmony_ci if (ecma_is_value_found (result)) 92425bb815Sopenharmony_ci { 93425bb815Sopenharmony_ci /* Note: the result may contains ECMA_VALUE_ERROR */ 94425bb815Sopenharmony_ci *ref_base_lex_env_p = lex_env_p; 95425bb815Sopenharmony_ci return result; 96425bb815Sopenharmony_ci } 97425bb815Sopenharmony_ci 98425bb815Sopenharmony_ci break; 99425bb815Sopenharmony_ci } 100425bb815Sopenharmony_ci } 101425bb815Sopenharmony_ci 102425bb815Sopenharmony_ci if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) 103425bb815Sopenharmony_ci { 104425bb815Sopenharmony_ci break; 105425bb815Sopenharmony_ci } 106425bb815Sopenharmony_ci 107425bb815Sopenharmony_ci lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); 108425bb815Sopenharmony_ci } 109425bb815Sopenharmony_ci 110425bb815Sopenharmony_ci *ref_base_lex_env_p = NULL; 111425bb815Sopenharmony_ci#if ENABLED (JERRY_ERROR_MESSAGES) 112425bb815Sopenharmony_ci return ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, 113425bb815Sopenharmony_ci "% is not defined", 114425bb815Sopenharmony_ci ecma_make_string_value (name_p)); 115425bb815Sopenharmony_ci#else /* ENABLED (JERRY_ERROR_MESSAGES) */ 116425bb815Sopenharmony_ci return ecma_raise_reference_error (NULL); 117425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ERROR_MESSAGES) */ 118425bb815Sopenharmony_ci 119425bb815Sopenharmony_ci} /* ecma_op_get_value_lex_env_base */ 120425bb815Sopenharmony_ci 121425bb815Sopenharmony_ci/** 122425bb815Sopenharmony_ci * GetValue operation part (object base). 123425bb815Sopenharmony_ci * 124425bb815Sopenharmony_ci * See also: ECMA-262 v5, 8.7.1, section 4 125425bb815Sopenharmony_ci * 126425bb815Sopenharmony_ci * @return ecma value 127425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 128425bb815Sopenharmony_ci */ 129425bb815Sopenharmony_ciecma_value_t 130425bb815Sopenharmony_ciecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ 131425bb815Sopenharmony_ci ecma_string_t *property_name_p) /**< property name */ 132425bb815Sopenharmony_ci{ 133425bb815Sopenharmony_ci ecma_object_t *obj_p; 134425bb815Sopenharmony_ci 135425bb815Sopenharmony_ci if (JERRY_UNLIKELY (ecma_is_value_object (base_value))) 136425bb815Sopenharmony_ci { 137425bb815Sopenharmony_ci obj_p = ecma_get_object_from_value (base_value); 138425bb815Sopenharmony_ci } 139425bb815Sopenharmony_ci else 140425bb815Sopenharmony_ci { 141425bb815Sopenharmony_ci ecma_builtin_id_t id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; 142425bb815Sopenharmony_ci 143425bb815Sopenharmony_ci if (JERRY_LIKELY (ecma_is_value_string (base_value))) 144425bb815Sopenharmony_ci { 145425bb815Sopenharmony_ci ecma_string_t *string_p = ecma_get_string_from_value (base_value); 146425bb815Sopenharmony_ci 147425bb815Sopenharmony_ci if (ecma_string_is_length (property_name_p)) 148425bb815Sopenharmony_ci { 149425bb815Sopenharmony_ci return ecma_make_uint32_value (ecma_string_get_length (string_p)); 150425bb815Sopenharmony_ci } 151425bb815Sopenharmony_ci 152425bb815Sopenharmony_ci uint32_t index = ecma_string_get_array_index (property_name_p); 153425bb815Sopenharmony_ci 154425bb815Sopenharmony_ci if (index != ECMA_STRING_NOT_ARRAY_INDEX 155425bb815Sopenharmony_ci && index < ecma_string_get_length (string_p)) 156425bb815Sopenharmony_ci { 157425bb815Sopenharmony_ci ecma_char_t char_at_idx = ecma_string_get_char_at_pos (string_p, index); 158425bb815Sopenharmony_ci return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx)); 159425bb815Sopenharmony_ci } 160425bb815Sopenharmony_ci 161425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_STRING) 162425bb815Sopenharmony_ci id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; 163425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_STRING) */ 164425bb815Sopenharmony_ci } 165425bb815Sopenharmony_ci else if (ecma_is_value_number (base_value)) 166425bb815Sopenharmony_ci { 167425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_NUMBER) 168425bb815Sopenharmony_ci id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; 169425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_NUMBER) */ 170425bb815Sopenharmony_ci } 171425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 172425bb815Sopenharmony_ci else if (ecma_is_value_symbol (base_value)) 173425bb815Sopenharmony_ci { 174425bb815Sopenharmony_ci id = ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE; 175425bb815Sopenharmony_ci } 176425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 177425bb815Sopenharmony_ci else 178425bb815Sopenharmony_ci { 179425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_boolean (base_value)); 180425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_BOOLEAN) 181425bb815Sopenharmony_ci id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; 182425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */ 183425bb815Sopenharmony_ci } 184425bb815Sopenharmony_ci 185425bb815Sopenharmony_ci obj_p = ecma_builtin_get (id); 186425bb815Sopenharmony_ci } 187425bb815Sopenharmony_ci 188425bb815Sopenharmony_ci return ecma_op_object_get_with_receiver (obj_p, property_name_p, base_value); 189425bb815Sopenharmony_ci} /* ecma_op_get_value_object_base */ 190425bb815Sopenharmony_ci 191425bb815Sopenharmony_ci/** 192425bb815Sopenharmony_ci * PutValue operation part 193425bb815Sopenharmony_ci * 194425bb815Sopenharmony_ci * See also: ECMA-262 v5, 8.7.2, sections 3 and 5 195425bb815Sopenharmony_ci * 196425bb815Sopenharmony_ci * @return ecma value 197425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 198425bb815Sopenharmony_ci */ 199425bb815Sopenharmony_ciecma_value_t 200425bb815Sopenharmony_ciecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ 201425bb815Sopenharmony_ci ecma_string_t *name_p, /**< variable name */ 202425bb815Sopenharmony_ci bool is_strict, /**< flag indicating strict mode */ 203425bb815Sopenharmony_ci ecma_value_t value) /**< ECMA-value */ 204425bb815Sopenharmony_ci{ 205425bb815Sopenharmony_ci JERRY_ASSERT (lex_env_p != NULL 206425bb815Sopenharmony_ci && ecma_is_lexical_environment (lex_env_p)); 207425bb815Sopenharmony_ci 208425bb815Sopenharmony_ci while (true) 209425bb815Sopenharmony_ci { 210425bb815Sopenharmony_ci switch (ecma_get_lex_env_type (lex_env_p)) 211425bb815Sopenharmony_ci { 212425bb815Sopenharmony_ci case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: 213425bb815Sopenharmony_ci { 214425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); 215425bb815Sopenharmony_ci 216425bb815Sopenharmony_ci if (property_p != NULL) 217425bb815Sopenharmony_ci { 218425bb815Sopenharmony_ci if (ecma_is_property_writable (*property_p)) 219425bb815Sopenharmony_ci { 220425bb815Sopenharmony_ci ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 221425bb815Sopenharmony_ci 222425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 223425bb815Sopenharmony_ci if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) 224425bb815Sopenharmony_ci { 225425bb815Sopenharmony_ci return ecma_raise_reference_error (ECMA_ERR_MSG ("Variables declared by let/const must be" 226425bb815Sopenharmony_ci " initialized before writing their value.")); 227425bb815Sopenharmony_ci } 228425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 229425bb815Sopenharmony_ci 230425bb815Sopenharmony_ci ecma_named_data_property_assign_value (lex_env_p, property_value_p, value); 231425bb815Sopenharmony_ci } 232425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 233425bb815Sopenharmony_ci else if (ecma_is_property_enumerable (*property_p)) 234425bb815Sopenharmony_ci { 235425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Constant bindings cannot be reassigned.")); 236425bb815Sopenharmony_ci } 237425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 238425bb815Sopenharmony_ci else if (is_strict) 239425bb815Sopenharmony_ci { 240425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set.")); 241425bb815Sopenharmony_ci } 242425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 243425bb815Sopenharmony_ci } 244425bb815Sopenharmony_ci break; 245425bb815Sopenharmony_ci } 246425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 247425bb815Sopenharmony_ci case ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND: 248425bb815Sopenharmony_ci { 249425bb815Sopenharmony_ci break; 250425bb815Sopenharmony_ci } 251425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 252425bb815Sopenharmony_ci default: 253425bb815Sopenharmony_ci { 254425bb815Sopenharmony_ci JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); 255425bb815Sopenharmony_ci 256425bb815Sopenharmony_ci ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); 257425bb815Sopenharmony_ci 258425bb815Sopenharmony_ci ecma_value_t has_property = ecma_op_object_has_property (binding_obj_p, name_p); 259425bb815Sopenharmony_ci 260425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY) 261425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (has_property)) 262425bb815Sopenharmony_ci { 263425bb815Sopenharmony_ci return has_property; 264425bb815Sopenharmony_ci } 265425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */ 266425bb815Sopenharmony_ci 267425bb815Sopenharmony_ci if (ecma_is_value_true (has_property)) 268425bb815Sopenharmony_ci { 269425bb815Sopenharmony_ci ecma_value_t completion = ecma_op_object_put (binding_obj_p, 270425bb815Sopenharmony_ci name_p, 271425bb815Sopenharmony_ci value, 272425bb815Sopenharmony_ci is_strict); 273425bb815Sopenharmony_ci 274425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (completion)) 275425bb815Sopenharmony_ci { 276425bb815Sopenharmony_ci return completion; 277425bb815Sopenharmony_ci } 278425bb815Sopenharmony_ci 279425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_boolean (completion)); 280425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 281425bb815Sopenharmony_ci } 282425bb815Sopenharmony_ci 283425bb815Sopenharmony_ci break; 284425bb815Sopenharmony_ci } 285425bb815Sopenharmony_ci } 286425bb815Sopenharmony_ci 287425bb815Sopenharmony_ci if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) 288425bb815Sopenharmony_ci { 289425bb815Sopenharmony_ci break; 290425bb815Sopenharmony_ci } 291425bb815Sopenharmony_ci 292425bb815Sopenharmony_ci lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); 293425bb815Sopenharmony_ci } 294425bb815Sopenharmony_ci 295425bb815Sopenharmony_ci if (is_strict) 296425bb815Sopenharmony_ci { 297425bb815Sopenharmony_ci#if ENABLED (JERRY_ERROR_MESSAGES) 298425bb815Sopenharmony_ci return ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, 299425bb815Sopenharmony_ci "% is not defined", 300425bb815Sopenharmony_ci ecma_make_string_value (name_p)); 301425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ERROR_MESSAGES) */ 302425bb815Sopenharmony_ci return ecma_raise_reference_error (NULL); 303425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ERROR_MESSAGES) */ 304425bb815Sopenharmony_ci } 305425bb815Sopenharmony_ci 306425bb815Sopenharmony_ci ecma_value_t completion = ecma_op_object_put (ecma_builtin_get_global (), 307425bb815Sopenharmony_ci name_p, 308425bb815Sopenharmony_ci value, 309425bb815Sopenharmony_ci false); 310425bb815Sopenharmony_ci 311425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_boolean (completion)); 312425bb815Sopenharmony_ci 313425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 314425bb815Sopenharmony_ci} /* ecma_op_put_value_lex_env_base */ 315425bb815Sopenharmony_ci 316425bb815Sopenharmony_ci/** 317425bb815Sopenharmony_ci * @} 318425bb815Sopenharmony_ci * @} 319425bb815Sopenharmony_ci */ 320