/** * Resolve value corresponding to reference. * * @return value of the reference */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ ecma_string_t *name_p, /**< identifier's name */ bool is_strict) /**< strict mode */ { JERRY_ASSERT (lex_env_p != NULL); while (lex_env_p != NULL) { if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); if (property_p != NULL) { ecma_value_t prop_value = ecma_get_named_data_property_value (property_p); /* is the binding mutable? */ if (unlikely (!ecma_is_property_writable (property_p) && ecma_is_value_empty (prop_value))) { /* unitialized mutable binding */ if (is_strict) { return ecma_raise_reference_error (ECMA_ERR_MSG ("")); } else { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } return ecma_fast_copy_value (prop_value); } } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND || ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_property_t *property_p = ecma_op_object_get_property (binding_obj_p, name_p); if (property_p != NULL) { return ecma_op_object_get (binding_obj_p, name_p); } } lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } return ecma_raise_reference_error (ECMA_ERR_MSG ("")); } /* ecma_op_resolve_reference_value */
/** * GetBindingValue operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ bool is_strict) /**< argument S */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (name_p != NULL); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p); ecma_value_t prop_value = ecma_get_named_data_property_value (property_p); /* is the binding mutable? */ if (!ecma_is_property_writable (property_p) && ecma_is_value_empty (prop_value)) { /* unitialized immutable binding */ if (is_strict) { return ecma_raise_reference_error (""); } else { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } return ecma_copy_value (prop_value, true); } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); if (ecma_op_object_get_property (binding_obj_p, name_p) == NULL) { if (is_strict) { return ecma_raise_reference_error (""); } else { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } return ecma_op_object_get (binding_obj_p, name_p); } } /* ecma_op_get_binding_value */
/** * PutValue operation part (lexical environment base or unresolvable reference). * * See also: ECMA-262 v5, 8.7.2, sections 3 and 5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_put_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< reference's base (lexical environment) */ ecma_string_t *var_name_string_p, /**< variable name */ bool is_strict, /**< flag indicating strict mode */ ecma_value_t value) /**< ECMA-value */ { const bool is_unresolvable_reference = (ref_base_lex_env_p == NULL); // 3. if (unlikely (is_unresolvable_reference)) { // 3.a. if (is_strict) { return ecma_raise_reference_error (""); } else { // 3.b. ecma_object_t *global_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL); ecma_value_t completion = ecma_op_object_put (global_object_p, var_name_string_p, value, false); ecma_deref_object (global_object_p); JERRY_ASSERT (ecma_is_value_boolean (completion)); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); } } // 5. JERRY_ASSERT (ref_base_lex_env_p != NULL && ecma_is_lexical_environment (ref_base_lex_env_p)); // 5.a return ecma_op_set_mutable_binding (ref_base_lex_env_p, var_name_string_p, value, is_strict); } /* ecma_op_put_value_lex_env_base */
/** * GetValue operation part (lexical environment base or unresolvable reference). * * See also: ECMA-262 v5, 8.7.1, sections 3 and 5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_get_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< reference's base (lexical environment) */ ecma_string_t *var_name_string_p, /**< variable name */ bool is_strict) /**< flag indicating strict mode */ { const bool is_unresolvable_reference = (ref_base_lex_env_p == NULL); // 3. if (unlikely (is_unresolvable_reference)) { return ecma_raise_reference_error (""); } // 5. JERRY_ASSERT (ref_base_lex_env_p != NULL && ecma_is_lexical_environment (ref_base_lex_env_p)); // 5.a return ecma_op_get_binding_value (ref_base_lex_env_p, var_name_string_p, is_strict); } /* ecma_op_get_value_lex_env_base */
/** * GetBindingValue operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ bool is_strict) /**< argument S */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (name_p != NULL); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_value_t *prop_value_p = ecma_get_named_data_property (lex_env_p, name_p); return ecma_copy_value (prop_value_p->value); } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_value_t result = ecma_op_object_find (binding_obj_p, name_p); if (!ecma_is_value_found (result)) { if (is_strict) { result = ecma_raise_reference_error (ECMA_ERR_MSG ("Binding does not exist or is uninitialised.")); } else { result = ECMA_VALUE_UNDEFINED; } } return result; } } /* ecma_op_get_binding_value */
/** * Resolve value corresponding to reference. * * @return value of the reference */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ ecma_string_t *name_p) /**< identifier's name */ { JERRY_ASSERT (lex_env_p != NULL); while (lex_env_p != NULL) { ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p); if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); if (property_p != NULL) { return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); } } else if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND) { ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); #ifndef CONFIG_ECMA_LCACHE_DISABLE ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); if (property_p != NULL) { ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { return ecma_fast_copy_value (prop_value_p->value); } JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_value_p); if (getter_p == NULL) { return ECMA_VALUE_UNDEFINED; } ecma_value_t base_value = ecma_make_object_value (binding_obj_p); return ecma_op_function_call (getter_p, base_value, NULL, 0); } #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ ecma_value_t prop_value = ecma_op_object_find (binding_obj_p, name_p); if (ecma_is_value_found (prop_value)) { return prop_value; } } else { #if ENABLED (JERRY_ES2015_CLASS) JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND); #else /* !ENABLED (JERRY_ES2015_CLASS) */ JERRY_UNREACHABLE (); #endif /* ENABLED (JERRY_ES2015_CLASS) */ } lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } #ifdef JERRY_ENABLE_ERROR_MESSAGES ecma_value_t name_val = ecma_make_string_value (name_p); ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, "% is not defined", name_val); #else /* !JERRY_ENABLE_ERROR_MESSAGES */ ecma_value_t error_value = ecma_raise_reference_error (NULL); #endif /* JERRY_ENABLE_ERROR_MESSAGES */ return error_value; } /* ecma_op_resolve_reference_value */