1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecma-array-object.h" 17#include "ecma-helpers.h" 18#include "ecma-objects.h" 19#include "jcontext.h" 20#include "lit-char-helpers.h" 21#include "vm.h" 22 23/** 24 * Check whether currently executed code is strict mode code 25 * 26 * @return true - current code is executed in strict mode, 27 * false - otherwise 28 */ 29bool 30vm_is_strict_mode (void) 31{ 32 JERRY_ASSERT (JERRY_CONTEXT (vm_top_context_p) != NULL); 33 34 return JERRY_CONTEXT (vm_top_context_p)->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE; 35} /* vm_is_strict_mode */ 36 37/** 38 * Check whether currently performed call (on top of call-stack) is performed in form, 39 * meeting conditions of 'Direct Call to Eval' (see also: ECMA-262 v5, 15.1.2.1.1) 40 * 41 * Warning: 42 * the function should only be called from implementation 43 * of built-in 'eval' routine of Global object 44 * 45 * @return true - currently performed call is performed through 'eval' identifier, 46 * without 'this' argument, 47 * false - otherwise 48 */ 49inline bool JERRY_ATTR_ALWAYS_INLINE 50vm_is_direct_eval_form_call (void) 51{ 52 return (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0; 53} /* vm_is_direct_eval_form_call */ 54 55#if defined(JERRY_FUNCTION_BACKTRACE) && !defined(__APPLE__) 56static ecma_string_t* 57vm_get_function_name_string (vm_frame_ctx_t *context_p) 58{ 59 ecma_stringbuilder_t func_name_builder; 60 if (context_p->prev_context_p != NULL) { 61 vm_frame_ctx_t* prev_ctx_p = context_p->prev_context_p; 62 ecma_object_t* func_obj = ecma_get_object_from_value (prev_ctx_p->callee_value); 63 ecma_object_type_t func_obj_type = ecma_get_object_type (func_obj); 64 if (func_obj_type == ECMA_OBJECT_TYPE_FUNCTION 65 || func_obj_type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION 66 || func_obj_type == ECMA_OBJECT_TYPE_BOUND_FUNCTION) { 67 ecma_string_t* name_prop = ecma_get_magic_string (LIT_MAGIC_STRING_NAME); 68 ecma_value_t func_name_value = ecma_op_object_get (func_obj, name_prop); 69 if (func_name_value == ECMA_VALUE_UNDEFINED) { 70 func_name_builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) ("<unknown>"), 9); 71 } else { 72 func_name_builder = ecma_stringbuilder_create_from(ecma_get_string_from_value (func_name_value)); 73 } 74 ecma_deref_ecma_string (name_prop); 75 } else { 76 func_name_builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) ("<erroneous>"), 11); 77 } 78 } else { 79 func_name_builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) ("<GLOBAL>"), 8); 80 } 81 ecma_string_t* lbracket = ecma_new_ecma_string_from_utf8((const lit_utf8_byte_t *) ("("), 1); 82 ecma_string_t* rbracket = ecma_new_ecma_string_from_utf8((const lit_utf8_byte_t *) (")"), 1); 83 ecma_stringbuilder_append (&func_name_builder, lbracket); 84 ecma_stringbuilder_append (&func_name_builder, rbracket); 85 ecma_stringbuilder_append_byte (&func_name_builder, LIT_CHAR_COMMA); 86 ecma_stringbuilder_append_byte (&func_name_builder, LIT_CHAR_SP); 87 ecma_deref_ecma_string(rbracket); 88 ecma_deref_ecma_string(lbracket); 89 return ecma_stringbuilder_finalize (&func_name_builder); 90} 91#endif 92 93/** 94 * Get backtrace. The backtrace is an array of strings where 95 * each string contains the position of the corresponding frame. 96 * The array length is zero if the backtrace is not available. 97 * 98 * @return array ecma value 99 */ 100ecma_value_t 101vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */ 102{ 103#if ENABLED (JERRY_LINE_INFO) 104 ecma_value_t result_array = ecma_op_create_array_object (NULL, 0, false); 105 106 if (max_depth == 0) 107 { 108 max_depth = UINT32_MAX; 109 } 110 111 vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); 112 ecma_object_t *array_p = ecma_get_object_from_value (result_array); 113 JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); 114 uint32_t index = 0; 115 116 while (context_p != NULL) 117 { 118 ecma_string_t *str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); 119 120#if defined(JERRY_FUNCTION_BACKTRACE) && !defined(__APPLE__) 121 ecma_string_t* func_name = vm_get_function_name_string (context_p); 122 func_name = ecma_concat_ecma_strings (func_name, str_p); 123 124 ecma_fast_array_set_property (array_p, index, ecma_make_string_value (func_name)); 125 ecma_deref_ecma_string(str_p); 126 ecma_deref_ecma_string(func_name); 127#else 128 ecma_fast_array_set_property (array_p, index, ecma_make_string_value (str_p)); 129 ecma_deref_ecma_string (str_p); 130#endif 131 132 context_p = context_p->prev_context_p; 133 index++; 134 135 if (index >= max_depth) 136 { 137 break; 138 } 139 } 140 141 return result_array; 142#else /* !ENABLED (JERRY_LINE_INFO) */ 143 JERRY_UNUSED (max_depth); 144 145 return ecma_op_create_array_object (NULL, 0, false); 146#endif /* ENABLED (JERRY_LINE_INFO) */ 147} /* vm_get_backtrace */ 148