1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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 "dfx_assist.h"
17 #include "ace_log.h"
18 #include "jerryscript-core.h"
19 #include "presets/console_log_impl.h"
20 
21 namespace OHOS {
22 namespace ACELite {
DumpErrorCode(const jerry_value_t errorValue)23 void DfxAssist::DumpErrorCode(const jerry_value_t errorValue)
24 {
25     const uint16_t errorMsgMaxLength = 128;
26     if (!jerry_is_feature_enabled(JERRY_FEATURE_ERROR_MESSAGES)) {
27         return;
28     }
29 
30     jerry_value_t errValue = jerry_get_value_from_error(errorValue, false);
31     jerry_value_t errStrVal = jerry_value_to_string(errValue);
32     jerry_release_value(errValue);
33 
34     if (jerry_value_is_error(errStrVal)) {
35         /* Avoid recursive error throws. */
36         HILOG_ERROR(HILOG_MODULE_ACE, "[Error value to string failed]");
37         jerry_release_value(errStrVal);
38         return;
39     }
40 
41     jerry_size_t errStrSize = jerry_get_utf8_string_size(errStrVal);
42     if (errStrSize >= errorMsgMaxLength) {
43         HILOG_ERROR(HILOG_MODULE_ACE, "[Error message too long]");
44         jerry_release_value(errStrVal);
45         return;
46     }
47 
48     jerry_char_t *errStrBuffer = static_cast<jerry_char_t *>(ace_malloc(sizeof(jerry_char_t) * (errStrSize + 1)));
49     if (errStrBuffer == nullptr) {
50         HILOG_ERROR(HILOG_MODULE_ACE, "malloc memory failed!");
51         jerry_release_value(errStrVal);
52         return;
53     }
54     jerry_size_t stringEnd = jerry_string_to_utf8_char_buffer(errStrVal, errStrBuffer, errStrSize);
55     errStrBuffer[stringEnd] = '\0';
56     // output to platform trace
57     HILOG_ERROR(HILOG_MODULE_ACE, " [JS Error]: %{public}s", reinterpret_cast<char *>(errStrBuffer));
58     // output to user console
59     LogString(LogLevel::LOG_LEVEL_ERR, "[JS Exception]: ");
60     LogString(LogLevel::LOG_LEVEL_ERR, reinterpret_cast<char *>(errStrBuffer));
61     // output line separator to trigger trace output
62     LogString(LogLevel::LOG_LEVEL_ERR, "\n");
63     ace_free(errStrBuffer);
64     errStrBuffer = nullptr;
65     jerry_release_value(errStrVal);
66 }
67 
DumpErrorMessage(const jerry_value_t errorValue)68 void DfxAssist::DumpErrorMessage(const jerry_value_t errorValue)
69 {
70     const uint16_t stackMsgMaxLength = 256;
71     const uint8_t arrMaxLength = 32;
72     jerry_value_t stackStr = jerry_create_string(reinterpret_cast<const jerry_char_t *>("stack"));
73     jerry_value_t errorVal = jerry_get_value_from_error(errorValue, false);
74 
75     jerry_value_t backtraceVal = jerry_get_property(errorVal, stackStr);
76     jerry_release_value(stackStr);
77     jerry_release_value(errorVal);
78 
79     if (jerry_value_is_error(backtraceVal) || !(jerry_value_is_array(backtraceVal))) {
80         jerry_release_value(backtraceVal);
81         return;
82     }
83 
84     uint32_t length = jerry_get_array_length(backtraceVal);
85     if (length == 0) {
86         jerry_release_value(backtraceVal);
87         return;
88     }
89     if (length > arrMaxLength) {
90         length = arrMaxLength;
91     }
92 
93     jerry_char_t *errStrBuffer = static_cast<jerry_char_t *>(ace_malloc(sizeof(jerry_char_t) * (stackMsgMaxLength)));
94     if (errStrBuffer == nullptr) {
95         HILOG_ERROR(HILOG_MODULE_ACE, "malloc memory failed!");
96         jerry_release_value(backtraceVal);
97         return;
98     }
99     HILOG_ERROR(HILOG_MODULE_ACE, "[Exception backtrace]:");
100     for (uint32_t i = 0; i < length; i++) {
101         jerry_value_t itemVal = jerry_get_property_by_index(backtraceVal, i);
102         jerry_size_t strSize = 0;
103         if (!jerry_value_is_error(itemVal) && jerry_value_is_string(itemVal)) {
104             strSize = jerry_get_utf8_string_size(itemVal);
105         }
106 
107         if (strSize >= stackMsgMaxLength) {
108             HILOG_ERROR(HILOG_MODULE_ACE, "%{public}hhu: [Backtrace string too long]", i);
109         } else {
110             jerry_size_t stringEnd = jerry_string_to_utf8_char_buffer(itemVal, errStrBuffer, strSize);
111             errStrBuffer[stringEnd] = '\0';
112             HILOG_ERROR(HILOG_MODULE_ACE, "%{public}u: %{public}s", i, reinterpret_cast<char *>(errStrBuffer));
113         }
114         jerry_release_value(itemVal);
115     }
116     ace_free(errStrBuffer);
117     errStrBuffer = nullptr;
118     jerry_release_value(backtraceVal);
119 }
120 } // namespace ACELite
121 } // namespace OHOS
122