diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index cf8f58ced..0a20f72e2 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -45,8 +45,6 @@ */ #define OP_UNIMPLEMENTED_LIST(op) \ - op (with) \ - op (end_with) \ static char __unused unimplemented_list_end #define DEFINE_UNIMPLEMENTED_OP(op) \ @@ -1402,6 +1400,68 @@ opfunc_this (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_this */ +/** + * 'With' opcode handler. + * + * See also: ECMA-262 v5, 12.10 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_with (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t expr_var_idx = opdata.data.with.expr; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (expr_value, + get_variable_value (int_data, + expr_var_idx, + false), + ret_value); + ECMA_TRY_CATCH (obj_expr_value, + ecma_op_to_object (expr_value.value), + ret_value); + + ecma_object_t *obj_p = ECMA_GET_POINTER (obj_expr_value.value.value); + + ecma_object_t *old_env_p = int_data->lex_env_p; + ecma_object_t *new_env_p = ecma_create_object_lex_env (old_env_p, + obj_p, + true); + int_data->lex_env_p = new_env_p; + + ecma_completion_value_t evaluation_completion = run_int_loop (int_data); + + if (evaluation_completion.type == ECMA_COMPLETION_TYPE_META) + { + opcode_t meta_opcode = read_opcode (int_data->pos); + JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta); + JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH); + + int_data->pos++; + + ret_value = ecma_make_empty_completion_value (); + } + else + { + ret_value = evaluation_completion; + } + + int_data->lex_env_p = old_env_p; + + ecma_deref_object (new_env_p); + + ECMA_FINALIZE (obj_expr_value); + ECMA_FINALIZE (expr_value); + + return ret_value; +} /* opfunc_with */ + /** * Evaluate argument of typeof. * @@ -1682,6 +1742,7 @@ opfunc_meta (opcode_t opdata, /**< operation data */ switch (type) { case OPCODE_META_TYPE_VARG: + case OPCODE_META_TYPE_END_WITH: { return ecma_make_completion_value (ECMA_COMPLETION_TYPE_META, ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY), diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 62f0412ee..b2cf22ebe 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -56,7 +56,8 @@ typedef enum OPCODE_META_TYPE_VARG, /**< element (var_idx) of arguments' list */ OPCODE_META_TYPE_VARG_PROP_DATA, /**< name (lit_idx) and value (var_idx) for a data property descriptor */ OPCODE_META_TYPE_VARG_PROP_GETTER, /**< name (lit_idx) and getter (var_idx) for an accessor property descriptor */ - OPCODE_META_TYPE_VARG_PROP_SETTER /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */ + OPCODE_META_TYPE_VARG_PROP_SETTER, /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */ + OPCODE_META_TYPE_END_WITH /**< end of with statement */ } opcode_meta_type; typedef struct @@ -95,8 +96,7 @@ typedef struct 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) + p##_1 (a, with, expr) #define OP_ASSIGNMENTS(p, a) \ p##_3 (a, assignment, var_left, type_value_right, value_right) diff --git a/src/libecmaobjects/ecma-helpers.c b/src/libecmaobjects/ecma-helpers.c index 997ebb8eb..c2ec8d7cf 100644 --- a/src/libecmaobjects/ecma-helpers.c +++ b/src/libecmaobjects/ecma-helpers.c @@ -93,7 +93,8 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out ecma_object_t *binding_obj_p, /**< binding object */ bool provide_this) /**< provideThis flag */ { - JERRY_ASSERT(binding_obj_p != NULL); + JERRY_ASSERT(binding_obj_p != NULL + && !binding_obj_p->is_lexical_environment); ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); ecma_init_gc_info (new_lexical_environment_p); diff --git a/src/libecmaoperations/ecma-conversion.c b/src/libecmaoperations/ecma-conversion.c index 229d8df3e..23767e5a2 100644 --- a/src/libecmaoperations/ecma-conversion.c +++ b/src/libecmaoperations/ecma-conversion.c @@ -391,7 +391,24 @@ ecma_op_to_string (ecma_value_t value) /**< ecma-value */ ecma_completion_value_t ecma_op_to_object (ecma_value_t value) /**< ecma-value */ { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(value); + switch ((ecma_type_t)value.value_type) + { + case ECMA_TYPE_SIMPLE: + case ECMA_TYPE_NUMBER: + case ECMA_TYPE_STRING: + { + JERRY_UNIMPLEMENTED (); + } + + case ECMA_TYPE_OBJECT: + { + return ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, + ecma_copy_value (value, true), + ECMA_TARGET_ID_RESERVED); + } + } + + JERRY_UNREACHABLE (); } /* ecma_op_to_object */ /** diff --git a/src/libecmaoperations/ecma-exceptions.c b/src/libecmaoperations/ecma-exceptions.c index 2377f945c..7ca4802c3 100644 --- a/src/libecmaoperations/ecma-exceptions.c +++ b/src/libecmaoperations/ecma-exceptions.c @@ -36,6 +36,9 @@ ecma_object_t* ecma_new_standard_error (ecma_standard_error_t error_type) /**< native error type */ { + /* SyntaxError should be treated as an early error */ + JERRY_ASSERT (error_type != ECMA_ERROR_SYNTAX); + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(error_type); } /* ecma_new_standard_error */ diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index d22bd8115..878e0f925 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -2083,7 +2083,7 @@ parse_with_statement (void) skip_newlines (); parse_statement (); - DUMP_VOID_OPCODE (end_with); + DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_END_WITH, INVALID_VALUE, INVALID_VALUE); } /* switch_statement diff --git a/src/liboptimizer/pretty-printer.c b/src/liboptimizer/pretty-printer.c index 97b840e15..f5206c8e2 100644 --- a/src/liboptimizer/pretty-printer.c +++ b/src/liboptimizer/pretty-printer.c @@ -347,8 +347,7 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite) uint8_t opcode_num = opcode.op_idx; __printf ("%3d: %20s ", oc, opcode_names[opcode_num]); - if (opcode_num != NAME_TO_ID (nop) && opcode_num != NAME_TO_ID (ret) - && opcode_num != NAME_TO_ID (end_with)) + if (opcode_num != NAME_TO_ID (nop) && opcode_num != NAME_TO_ID (ret)) { for (i = 1; i < opcode_sizes[opcode_num]; i++) { @@ -415,7 +414,6 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite) CASE_EXIT (exitval, "exit", status_code) CASE_SINGLE_ADDRESS (retval, "return", ret_value) CASE_ZERO_ADDRESS (ret, "return") - CASE_ZERO_ADDRESS (end_with, "") CASE_ZERO_ADDRESS (nop, "") TODO (Refine to match new opcodes) CASE_VARG_1_LHS (array_decl, lhs, "=", "[", list, "]") diff --git a/tests/unit/common.h b/tests/unit/common.h index 38e0d1f56..70763d9ae 100644 --- a/tests/unit/common.h +++ b/tests/unit/common.h @@ -38,8 +38,7 @@ opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size) if (opcode_num1 != opcode_num2) return false; - if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret) - || opcode_num1 == NAME_TO_ID (end_with)) + if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret)) return true; for (j = 1; j < opcode_sizes[opcode_num1]; j++) @@ -50,4 +49,4 @@ opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size) return true; } -#endif // COMMON_H \ No newline at end of file +#endif // COMMON_H