vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
             uint32_t parse_opts) /**< ecma_parse_opts_t option bits */
{
  ecma_value_t this_binding;
  ecma_object_t *lex_env_p;

  /* ECMA-262 v5, 10.4.2 */
  if (parse_opts & ECMA_PARSE_DIRECT_EVAL)
  {
    this_binding = ecma_copy_value (JERRY_CONTEXT (vm_top_context_p)->this_binding);
    lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;

#if JERRY_DEBUGGER
    uint32_t chain_index = parse_opts >> ECMA_PARSE_CHAIN_INDEX_SHIFT;
    parse_opts &= (1 << ECMA_PARSE_CHAIN_INDEX_SHIFT) - 1;

    while (chain_index != 0)
    {
      if (JERRY_UNLIKELY (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL))
      {
        ecma_bytecode_deref (bytecode_data_p);
        ecma_free_value (this_binding);
        return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid scope chain index for eval"));
      }

      lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);

      if ((ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
          || (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE))
      {
        chain_index--;
      }
    }
#endif /* JERRY_DEBUGGER */
  }
  else
  {
#if JERRY_BUILTIN_REALMS
    ecma_object_t *global_obj_p = (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p);
    this_binding = ((ecma_global_object_t *) global_obj_p)->this_binding;
    ecma_ref_object (ecma_get_object_from_value (this_binding));
#else /* !JERRY_BUILTIN_REALMS */
    ecma_object_t *global_obj_p = ecma_builtin_get_global ();
    ecma_ref_object (global_obj_p);
    this_binding = ecma_make_object_value (global_obj_p);
#endif /* JERRY_BUILTIN_REALMS */
    lex_env_p = ecma_get_global_scope (global_obj_p);
  }

  ecma_ref_object (lex_env_p);

  if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0)
  {
    ecma_object_t *strict_lex_env_p = ecma_create_decl_lex_env (lex_env_p);

    ecma_deref_object (lex_env_p);
    lex_env_p = strict_lex_env_p;
  }

  if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED) != 0)
  {
    ecma_object_t *lex_block_p = ecma_create_decl_lex_env (lex_env_p);
    lex_block_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK;

    ecma_deref_object (lex_env_p);
    lex_env_p = lex_block_p;
  }

  vm_frame_ctx_shared_t shared;
  shared.bytecode_header_p = bytecode_data_p;
  shared.function_object_p = NULL;
  shared.status_flags = (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_FRAME_CTX_SHARED_DIRECT_EVAL : 0;

  ecma_value_t completion_value = vm_run (&shared, this_binding, lex_env_p);

  ecma_deref_object (lex_env_p);
  ecma_free_value (this_binding);

#if JERRY_SNAPSHOT_EXEC
  if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
  {
    ecma_bytecode_deref (bytecode_data_p);
  }
#else /* !JERRY_SNAPSHOT_EXEC */
  ecma_bytecode_deref (bytecode_data_p);
#endif /* JERRY_SNAPSHOT_EXEC */

  return completion_value;
} /* vm_run_eval */


Fix for-in collection cleanup on abrupt 'has' result (#4807)

This patch fixes #4747

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik robert.fancsik@h-lab.eu

vm_init_exec (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
  vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p;
  const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p;

  frame_ctx_p->prev_context_p = JERRY_CONTEXT (vm_top_context_p);
  frame_ctx_p->context_depth = 0;
  frame_ctx_p->status_flags = (uint8_t) ((shared_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL)
                                         | (bytecode_header_p->status_flags & VM_FRAME_CTX_IS_STRICT));

  uint16_t argument_end, register_end;
  ecma_value_t *literal_p;

  if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
  {
    cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;

    argument_end = args_p->argument_end;
    register_end = args_p->register_end;

    literal_p = (ecma_value_t *) (args_p + 1);
    literal_p -= register_end;
    frame_ctx_p->literal_start_p = literal_p;
    literal_p += args_p->literal_end;
  }
  else
  {
    cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;

    argument_end = args_p->argument_end;
    register_end = args_p->register_end;

    literal_p = (ecma_value_t *) (args_p + 1);
    literal_p -= register_end;
    frame_ctx_p->literal_start_p = literal_p;
    literal_p += args_p->literal_end;
  }

  frame_ctx_p->byte_code_p = (uint8_t *) literal_p;
  frame_ctx_p->byte_code_start_p = (uint8_t *) literal_p;
  frame_ctx_p->stack_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end;

  uint32_t arg_list_len = 0;

  if (argument_end > 0)
  {
    JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST);

    const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p;
    arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len;

    if (arg_list_len > argument_end)
    {
      arg_list_len = argument_end;
    }

    for (uint32_t i = 0; i < arg_list_len; i++)
    {
      VM_GET_REGISTER (frame_ctx_p, i) = ecma_fast_copy_value (arg_list_p[i]);
    }
  }

  /* The arg_list_len contains the end of the copied arguments.
   * Fill everything else with undefined. */
  if (register_end > arg_list_len)
  {
    ecma_value_t *stack_p = VM_GET_REGISTERS (frame_ctx_p) + arg_list_len;

    for (uint32_t i = arg_list_len; i < register_end; i++)
    {
      *stack_p++ = ECMA_VALUE_UNDEFINED;
    }
  }

  JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL;
  JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p;
} /* vm_init_exec */


vm_run_module (ecma_module_t *module_p) /**< module to be executed */
{
  const ecma_value_t module_init_result = ecma_module_initialize (module_p);

  if (ECMA_IS_VALUE_ERROR (module_init_result))
  {
    return module_init_result;
  }

  vm_frame_ctx_shared_t shared;
  shared.bytecode_header_p = module_p->u.compiled_code_p;
  shared.function_object_p = &module_p->header.object;
  shared.status_flags = 0;

  return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p);
} /* vm_run_module */


vm_get_class_function (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
  JERRY_ASSERT (frame_ctx_p != NULL);

  if (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC)
  {
    return frame_ctx_p->shared_p->function_object_p;
  }

  ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p);

  JERRY_ASSERT (environment_record_p != NULL);
  return ecma_get_object_from_value (environment_record_p->function_object);
} /* vm_get_class_function */


opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
  const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 1;
  uint8_t opcode = byte_code_p[-1];
  unsigned int arguments_list_len;

  if (opcode >= CBC_NEW0)
  {
    arguments_list_len = (unsigned int) (opcode - CBC_NEW0);
  }
  else
  {
    arguments_list_len = *byte_code_p++;
  }

  ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len;
  ecma_value_t constructor_value = stack_top_p[-1];
  ecma_value_t completion_value;

  const char *constructor_message_p = ecma_check_constructor (constructor_value);
  if (constructor_message_p != ECMA_IS_VALID_CONSTRUCTOR)
  {
    completion_value = ecma_raise_type_error (constructor_message_p);
  }
  else
  {
    ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value);

    completion_value = ecma_op_function_construct (constructor_obj_p,
                                                   constructor_obj_p,
                                                   stack_top_p,
                                                   arguments_list_len);
  }

  /* Free registers. */
  for (uint32_t i = 0; i < arguments_list_len; i++)
  {
    ecma_fast_free_value (stack_top_p[i]);
  }

  if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value)))
  {
#if JERRY_DEBUGGER
    JERRY_CONTEXT (debugger_exception_byte_code_p) = frame_ctx_p->byte_code_p;
#endif /* JERRY_DEBUGGER */
    frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p;
  }
  else
  {
    ecma_free_value (stack_top_p[-1]);
    frame_ctx_p->byte_code_p = byte_code_p;
    stack_top_p[-1] = completion_value;
  }

  frame_ctx_p->stack_top_p = stack_top_p;
} /* opfunc_construct */