Splitting 'delete' opcode to 'delete_var' and 'delete_prop'. Implementing corresponding opcode handlers.
This commit is contained in:
+119
-1
@@ -50,7 +50,6 @@
|
||||
op (prop_get_decl) \
|
||||
op (prop_set_decl) \
|
||||
op (obj_decl) \
|
||||
op (delete) \
|
||||
op (with) \
|
||||
op (end_with) \
|
||||
static char __unused unimplemented_list_end
|
||||
@@ -1367,6 +1366,125 @@ opfunc_typeof (opcode_t opdata, /**< operation data */
|
||||
return ret_value;
|
||||
} /* opfunc_typeof */
|
||||
|
||||
/**
|
||||
* 'delete' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.4.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_delete_var (opcode_t opdata, /**< operation data */
|
||||
int_data_t *int_data) /**< interpreter context */
|
||||
{
|
||||
const idx_t dst_var_idx = opdata.data.delete_var.lhs;
|
||||
const idx_t name_var_idx = opdata.data.delete_var.name;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (name_value, get_variable_value (int_data, name_var_idx, false), ret_value);
|
||||
JERRY_ASSERT (name_value.value.value_type == ECMA_TYPE_STRING);
|
||||
ecma_string_t *name_string_p = ECMA_GET_POINTER (name_value.value.value);
|
||||
|
||||
ecma_reference_t ref = ecma_op_get_identifier_reference (int_data->lex_env_p,
|
||||
name_string_p,
|
||||
int_data->is_strict);
|
||||
|
||||
if (ref.is_strict)
|
||||
{
|
||||
ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX));
|
||||
}
|
||||
else if (ecma_is_value_undefined (ref.base))
|
||||
{
|
||||
ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ref.base.value_type == ECMA_TYPE_OBJECT);
|
||||
ecma_object_t *bindings_p = ECMA_GET_POINTER (ref.base.value);
|
||||
JERRY_ASSERT (bindings_p->is_lexical_environment);
|
||||
|
||||
ecma_completion_value_t completion = ecma_op_delete_binding (bindings_p, ref.referenced_name_p);
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_var_idx, completion.value);
|
||||
}
|
||||
|
||||
ecma_free_reference (ref);
|
||||
|
||||
ECMA_FINALIZE (name_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_delete_var */
|
||||
|
||||
|
||||
/**
|
||||
* 'delete' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.4.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_delete_prop (opcode_t opdata, /**< operation data */
|
||||
int_data_t *int_data) /**< interpreter context */
|
||||
{
|
||||
const idx_t dst_var_idx = opdata.data.delete_prop.lhs;
|
||||
const idx_t base_var_idx = opdata.data.delete_prop.base;
|
||||
const idx_t name_var_idx = opdata.data.delete_prop.name;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (base_value, get_variable_value (int_data, base_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (name_value, get_variable_value (int_data, name_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (check_coercible_ret, ecma_op_check_object_coercible (base_value.value), ret_value);
|
||||
ECMA_TRY_CATCH (str_name_value, ecma_op_to_string (name_value.value), ret_value);
|
||||
|
||||
JERRY_ASSERT (name_value.value.value_type == ECMA_TYPE_STRING);
|
||||
ecma_string_t *name_string_p = ECMA_GET_POINTER (name_value.value.value);
|
||||
|
||||
if (ecma_is_value_undefined (base_value.value))
|
||||
{
|
||||
if (int_data->is_strict)
|
||||
{
|
||||
ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ECMA_TRY_CATCH (obj_value, ecma_op_to_object (base_value.value), ret_value);
|
||||
|
||||
JERRY_ASSERT (obj_value.value.value_type == ECMA_TYPE_OBJECT);
|
||||
ecma_object_t *obj_p = ECMA_GET_POINTER (obj_value.value.value);
|
||||
JERRY_ASSERT (!obj_p->is_lexical_environment);
|
||||
|
||||
ECMA_TRY_CATCH (delete_op_completion,
|
||||
ecma_op_object_delete (obj_p, name_string_p, int_data->is_strict),
|
||||
ret_value);
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_var_idx, delete_op_completion.value);
|
||||
|
||||
ECMA_FINALIZE (delete_op_completion);
|
||||
ECMA_FINALIZE (obj_value);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (str_name_value);
|
||||
ECMA_FINALIZE (check_coercible_ret);
|
||||
ECMA_FINALIZE (name_value);
|
||||
ECMA_FINALIZE (base_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_delete_prop */
|
||||
|
||||
/**
|
||||
* 'meta' opcode handler.
|
||||
*
|
||||
|
||||
@@ -92,7 +92,8 @@ typedef struct
|
||||
p##_3 (a, prop_set_decl, lhs, prop, arg) \
|
||||
p##_2 (a, obj_decl, lhs, list) \
|
||||
p##_1 (a, this, lhs) \
|
||||
p##_2 (a, delete, lhs, obj) \
|
||||
p##_2 (a, delete_var, lhs, name) \
|
||||
p##_3 (a, delete_prop, lhs, base, name) \
|
||||
p##_2 (a, typeof, lhs, obj) \
|
||||
p##_1 (a, with, expr) \
|
||||
p##_0 (a, end_with)
|
||||
|
||||
@@ -47,7 +47,8 @@ ecma_op_check_object_coercible (ecma_value_t value) /**< ecma-value */
|
||||
{
|
||||
case ECMA_TYPE_SIMPLE:
|
||||
{
|
||||
if (ecma_is_value_undefined (value))
|
||||
if (ecma_is_value_undefined (value)
|
||||
|| ecma_is_value_null (value))
|
||||
{
|
||||
return ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
|
||||
}
|
||||
|
||||
@@ -1331,7 +1331,12 @@ parse_unary_expression (void)
|
||||
{
|
||||
lhs = next_temp_name ();
|
||||
NEXT (expr, unary_expression);
|
||||
DUMP_OPCODE_2 (delete, lhs, expr);
|
||||
TODO (/* lhs = delete_var for delete, applied to expression, that is evaluating to Identifier;
|
||||
lhs = delete_prop for 'delete expr[expr]';
|
||||
lhs = true - otherwise; */);
|
||||
|
||||
// DUMP_OPCODE_2 (delete, lhs, expr);
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
return lhs;
|
||||
}
|
||||
if (is_keyword (KW_VOID))
|
||||
|
||||
@@ -427,7 +427,8 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
|
||||
CASE_VARG_0_NAME_LHS (prop_get_decl, lhs, "=", "get", prop, "[", "]")
|
||||
CASE_VARG_1_NAME_LHS (prop_set_decl, lhs, "=", "set", prop, "[", arg, "]")
|
||||
CASE_THIS (this, lhs, "=", "this")
|
||||
CASE_DOUBLE_ADDRESS (delete, lhs, "=", "delete", obj)
|
||||
CASE_DOUBLE_ADDRESS (delete_var, lhs, "=", "delete", name)
|
||||
CASE_TRIPLE_ADDRESS (delete_prop, lhs, "= delete", base, ".", name)
|
||||
CASE_DOUBLE_ADDRESS (typeof, lhs, "=", "typeof", obj)
|
||||
CASE_WITH (with, expr)
|
||||
CASE_VARG_0_NAME (var_decl, "var", variable_name, "", "")
|
||||
|
||||
Reference in New Issue
Block a user