• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "frameworks/bridge/declarative_frontend/engine/v8/v8_utils.h"
17 
18 #include "base/log/log.h"
19 
20 #include "frameworks/bridge/declarative_frontend/engine/v8/v8_declarative_engine.h"
21 
22 namespace OHOS::Ace::Framework {
23 namespace V8Utils {
GetObjectKeys(v8::Local<v8::Object> obj)24 std::vector<std::string> GetObjectKeys(v8::Local<v8::Object> obj)
25 {
26     auto isolate = v8::Isolate::GetCurrent();
27     auto context = isolate->GetCurrentContext();
28     v8::Local<v8::Array> arr = obj->GetPropertyNames(context, v8::KeyCollectionMode::kIncludePrototypes,
29                                       v8::PropertyFilter::ALL_PROPERTIES, v8::IndexFilter::kSkipIndices)
30                                    .ToLocalChecked();
31 
32     std::vector<std::string> res;
33     for (uint32_t i = 0; i < arr->Length(); ++i) {
34         v8::Local<v8::Value> key = arr->Get(context, i).ToLocalChecked();
35         v8::String::Utf8Value s(isolate, key);
36         if (*s) {
37             res.push_back(*s);
38         }
39     }
40 
41     return res;
42 }
43 
JsStdDumpErrorAce(v8::Isolate * isolate,const v8::TryCatch * tryCatch)44 void JsStdDumpErrorAce(v8::Isolate* isolate, const v8::TryCatch* tryCatch)
45 {
46     v8::HandleScope handleScope(isolate);
47     auto context = isolate->GetCurrentContext();
48     auto stagingPage = static_cast<RefPtr<JsAcePage>*>(isolate->GetData(V8DeclarativeEngineInstance::STAGING_PAGE));
49 
50     // dump exception message
51     v8::String::Utf8Value exception(isolate, tryCatch->Exception());
52     LOGE("[DUMP] %{private}s", *exception);
53 
54     v8::Local<v8::Message> message = tryCatch->Message();
55     v8::Maybe<int> lineNumberLocal = message->GetLineNumber(context);
56     v8::MaybeLocal<v8::String> line = message->GetSourceLine(context);
57     int columnNumberStart = message->GetStartColumn();
58     int columnNumberEnd = message->GetEndColumn();
59 
60     int lineNumber = -1;
61     std::string source;
62     std::string column;
63     if (!lineNumberLocal.IsNothing()) {
64         lineNumber = lineNumberLocal.ToChecked();
65     }
66 
67     if (!line.IsEmpty()) {
68         v8::String::Utf8Value lineStrUtf8(isolate, line.ToLocalChecked());
69         source = *lineStrUtf8;
70         source += "\t\t";
71     }
72 
73     v8::String::Utf8Value script(isolate, message->GetScriptResourceName());
74     if (!(*script)) {
75         LOGE("%{private}s", source.c_str());
76         return;
77     }
78 
79     source += "(" + std::string(*script);
80     if (lineNumber != -1 && columnNumberStart != -1 && columnNumberEnd != -1) {
81         column.append(columnNumberStart, ' ');
82         column.append("^");
83         if ((columnNumberEnd - columnNumberStart) > 1) {
84             column.append(columnNumberEnd - columnNumberStart - 1, '~');
85         }
86         column.append("^");
87 
88         source += ":" + std::to_string(lineNumber) + ":" + std::to_string(columnNumberStart) + "-" +
89                   std::to_string(columnNumberEnd);
90     } else {
91         source += ")";
92     }
93 
94     LOGE("%s", source.c_str());
95     if (!line.IsEmpty()) {
96         LOGE("%s", column.c_str());
97     }
98 
99     RefPtr<RevSourceMap> pageMap;
100     RefPtr<RevSourceMap> appMap;
101     if (stagingPage && (*stagingPage)) {
102         pageMap = (*stagingPage)->GetPageMap();
103         appMap = (*stagingPage)->GetAppMap();
104     }
105 
106     if (!tryCatch->StackTrace(context).IsEmpty()) {
107         v8::String::Utf8Value stackTrace(isolate, tryCatch->StackTrace(context).ToLocalChecked());
108         if (pageMap || appMap) {
109             std::string tempStack = JsStdDumpSourceFile(*stackTrace, pageMap, appMap);
110             LOGE("%{public}s", tempStack.c_str());
111         } else {
112             LOGE("%{public}s", *stackTrace);
113         }
114     }
115 }
116 
ValueTypeAsString(v8::Local<v8::Value> val)117 std::string ValueTypeAsString(v8::Local<v8::Value> val)
118 {
119     auto isolate = v8::Isolate::GetCurrent();
120     v8::String::Utf8Value valType(isolate, val->TypeOf(isolate));
121     if (*valType) {
122         return *valType;
123     } else {
124         return "";
125     }
126 }
127 
JsStdDumpSourceFile(const std::string & stackTrace,const RefPtr<RevSourceMap> & pageMap,const RefPtr<RevSourceMap> & appMap)128 std::string JsStdDumpSourceFile(const std::string& stackTrace, const RefPtr<RevSourceMap>& pageMap,
129     const RefPtr<RevSourceMap>& appMap)
130 {
131 
132     const std::string suffix = ".js";
133     std::string ans = "";
134     std::string tempStack = stackTrace;
135     int32_t appFlag = tempStack.find("app.js");
136     bool isAppPage = appFlag > 0 && appMap;
137 
138     // find per line of stack
139     std::vector<std::string> res;
140     ExtractEachInfo(tempStack, res);
141 
142     // collect error info first
143     ans = ans + res[0] + "\n";
144     for (uint32_t i = 1; i < res.size(); i++) {
145         std::string temp = res[i];
146         std::string line = "";
147         std::string column = "";
148         GetPosInfo(temp, line, column);
149         if (line == "" || column == "") {
150             LOGI("the stack without line info");
151             break;
152         }
153 
154         const std::string sourceInfo = GetSourceInfo(line, column, pageMap, appMap, isAppPage);
155         if (sourceInfo == "") {
156             break;
157         }
158         temp = "at " + sourceInfo;
159         ans = ans + temp + "\n";
160     }
161     if (ans == "") {
162         return tempStack;
163     }
164     return ans;
165 }
166 
ExtractEachInfo(const std::string & tempStack,std::vector<std::string> & res)167 void ExtractEachInfo(const std::string& tempStack, std::vector<std::string>& res)
168 {
169     std::string tempStr = "";
170     for (uint32_t i = 0; i < tempStack.length(); i++) {
171         if (tempStack[i] == '\n') {
172             res.push_back(tempStr);
173             tempStr = "";
174         } else {
175             tempStr += tempStack[i];
176         }
177     }
178     res.push_back(tempStr);
179 }
180 
GetPosInfo(const std::string & temp,std::string & line,std::string & column)181 void GetPosInfo(const std::string& temp, std::string& line, std::string& column)
182 {
183     // 0 for colum, 1 for row
184     int32_t flag = 0;
185     // find line, column
186     for (int32_t i = temp.length() - 1; i > 0; i--) {
187         if (temp[i] == ':') {
188             flag += 1;
189             continue;
190         }
191         // some stack line may end with ")"
192         if (flag == 0) {
193             if (temp[i] >= '0' && temp[i] <= '9') {
194                 column = temp[i] + column;
195             }
196         } else if (flag == 1) {
197             line = temp[i] + line;
198         } else {
199             break;
200         }
201     }
202 }
203 
GetSourceInfo(const std::string & line,const std::string & column,const RefPtr<RevSourceMap> & pageMap,const RefPtr<RevSourceMap> & appMap,bool isAppPage)204 std::string GetSourceInfo(const std::string& line, const std::string& column, const RefPtr<RevSourceMap>& pageMap,
205     const RefPtr<RevSourceMap>& appMap, bool isAppPage)
206 {
207     std::string sourceInfo;
208     MappingInfo mapInfo;
209     if (isAppPage) {
210         mapInfo = appMap->Find(StringToInt(line), StringToInt(column));
211     } else {
212         mapInfo = pageMap->Find(StringToInt(line), StringToInt(column));
213     }
214     if (mapInfo.row == 0 || mapInfo.col == 0) {
215         return "";
216     }
217     sourceInfo = "(" + mapInfo.sources + ":" + std::to_string(mapInfo.row) + ":" + std::to_string(mapInfo.col) + ")";
218     return sourceInfo;
219 }
220 
221 } // namespace V8Utils
222 } // namespace OHOS::Ace::Framework
223