1 /*
2 * Copyright (c) 2023 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 #include "uncaught_exception_callback.h"
16
17 #include <string>
18
19 #include "js_env_logger.h"
20 #include "native_engine/native_engine.h"
21 #include "ui_content.h"
22
23 namespace OHOS {
24 namespace JsEnv {
GetNativeStrFromJsTaggedObj(napi_value obj,const char * key)25 std::string NapiUncaughtExceptionCallback::GetNativeStrFromJsTaggedObj(napi_value obj, const char* key)
26 {
27 if (obj == nullptr) {
28 JSENV_LOG_E("Failed to get value from key.");
29 return "";
30 }
31
32 napi_value valueStr = nullptr;
33 napi_get_named_property(env_, obj, key, &valueStr);
34 napi_valuetype valueType = napi_undefined;
35 napi_typeof(env_, valueStr, &valueType);
36 if (valueType != napi_string) {
37 JSENV_LOG_E("Failed to convert value from key.");
38 return "";
39 }
40
41 size_t valueStrBufLength = 0;
42 napi_get_value_string_utf8(env_, valueStr, nullptr, 0, &valueStrBufLength);
43 auto valueCStr = std::make_unique<char[]>(valueStrBufLength + 1);
44 size_t valueStrLength = 0;
45 napi_get_value_string_utf8(env_, valueStr, valueCStr.get(), valueStrBufLength + 1, &valueStrLength);
46 std::string ret(valueCStr.get(), valueStrLength);
47 JSENV_LOG_D("GetNativeStrFromJsTaggedObj Success.");
48 return ret;
49 }
50
operator ()(napi_value obj)51 void NapiUncaughtExceptionCallback::operator()(napi_value obj)
52 {
53 std::string errorMsg = GetNativeStrFromJsTaggedObj(obj, "message");
54 std::string errorName = GetNativeStrFromJsTaggedObj(obj, "name");
55 std::string errorStack = GetNativeStrFromJsTaggedObj(obj, "stack");
56 std::string summary = "Error name:" + errorName + "\n";
57 summary += "Error message:" + errorMsg + "\n";
58 const JsEnv::ErrorObject errorObj = {
59 .name = errorName,
60 .message = errorMsg,
61 .stack = errorStack
62 };
63 bool hasProperty = false;
64 napi_has_named_property(env_, obj, "code", &hasProperty);
65 if (hasProperty) {
66 std::string errorCode = GetNativeStrFromJsTaggedObj(obj, "code");
67 summary += "Error code:" + errorCode + "\n";
68 }
69 if (errorStack.empty()) {
70 JSENV_LOG_E("errorStack is empty");
71 return;
72 }
73 auto errorPos = SourceMap::GetErrorPos(errorStack);
74 std::string error;
75 if (obj != nullptr) {
76 napi_value fuc = nullptr;
77 napi_get_named_property(env_, obj, "errorfunc", &fuc);
78 napi_valuetype valueType = napi_undefined;
79 napi_typeof(env_, fuc, &valueType);
80 if (valueType == napi_function) {
81 error = reinterpret_cast<NativeEngine*>(env_)->GetSourceCodeInfo(fuc, errorPos);
82 }
83 }
84 if (sourceMapOperator_ == nullptr) {
85 JSENV_LOG_E("sourceMapOperator_ is empty");
86 return;
87 }
88 summary += error + "Stacktrace:\n" + sourceMapOperator_->TranslateBySourceMap(errorStack);
89 std::string str = Ace::UIContent::GetCurrentUIStackInfo();
90 if (!str.empty()) {
91 summary.append(str);
92 }
93 if (uncaughtTask_) {
94 uncaughtTask_(summary, errorObj);
95 }
96 }
97 } // namespace JsEnv
98 } // namespace OHOS
99