• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Analyzing JS Crash
2
3When an application crashes dues to a JS exception, it generates a JS crash log file. You can view the log to locate the error code and analyze the cause of the crash.
4
5This topic describes the JS Crash exception capture scenario, JS Crash fault analysis, and typical cases.
6
7## JS Crash Detection
8
9### JS Crash Log Specifications
10
11The following describes the fields in a process crash log.
12
13```
14Device info:XXX <- Device information
15Build info:XXX-XXXX X.X.X.XX(XXXXXXXX) <- Build information
16Fingerprint:ed1811f3f5ae13c7262b51aab73ddd01df95b2c64466a204e0d70e6461cf1697 <- Feature information
17Timestamp:XXXX-XX-XX XX:XX:XX.XXX <- Timestamp
18Module name:com.example.myapplication <- Module name
19Version:1.0.0 <- Version number
20VersionCode:1000000 <- Version code
21Pid:579 <- Process ID
22Uid:0 <- User ID
23Reason:TypeError <- Cause
24Error message:Cannot read property c of undefined <- Error message
25Cannot get SourceMap info, dump raw stack: <- The release package does not contain the **SourceMap** file, and the JavaScript stack fails to parse it.
26SourceCode:
27        var a = b.c;   <- Location of the problematic code
28                ^
29Stacktrace:
30    at onPageShow entry (entry/src/main/ets/pages/Index.ets:7:13)  <- Call stack of the error code
31           ^        ^                              ^
32         Function name Module bundle name The row and column numbers in the file
33```
34
35You can identify the cause of the crash, mostly application issues, based on Error message and Stacktrace in the logs.
36
37### JS Crash Exception Types
38
39JS crash exceptions are classified into the following types in the **Reason** field based on exception scenarios:
40
41 - **Error**: **Error** is the most basic type. Other error types are inherited from this type. The **Error** object consists of **message** and **name**, which indicate the error message and error name, respectively. Generally, exceptions of the **Error** type are thrown by developers.
42
43 - **TypeError**: As the most common error type at run-time, **TypeError** indicates a variable or parameter that is not of the expected type.
44
45 - **SyntaxError**: **SyntaxError** is also called parsing error. As the most common error type in all programming languages, **SyntaxError** indicates that the syntax does not comply with the syntax specifications of the programming language.
46
47 - **RangeError**: **RangeError** is thrown when a value exceeds the valid range. Common range errors include the following:
48    - The array length is negative or too long.
49    - The numeric parameter exceeds the predefined range.
50    - The number of function stack calls exceeds the maximum.
51
52 - **ReferenceError**: **ReferenceError** is thrown when a variable that does not exist is referenced. Each time a variable is created, the variable name and its value are stored in the key-value format. When a variable is referenced, the value will be located based on the key and returned. If the variable referenced cannot be to be found, **ReferenceError** is thrown.
53
54 - **URI Error**: **URI Error** is thrown when an invalid URI is found in **encodeURI()**, **decodeURI()**, **encodeURIComponent()**, **decodeURIComponent()**, **escape()**, or **unescape()**.
55
56## JS Crash Fault Analysis
57
58### Obtaining the Log
59
60The process crash log is a type of fault log managed together with the app freeze and JS application crash logs by the FaultLogger module. You can obtain process crash logs using any of the following methods:
61
62- Method 1: DevEco Studio
63
64    DevEco Studio collects process crash logs in **/data/log/faultlog/faultlogger/** and archives the logs in FaultLog. For details, see <!--RP1-->[Fault Log](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-fault-log-V5)<!--RP1End-->.
65
66- Method 2: hiAppEvent APIs
67
68    hiAppEvent provides APIs to subscribe to various fault logs. For details, see [Introduction to HiAppEvent](hiappevent-intro.md).
69
70<!--Del-->
71- Method 3: Shell
72
73    When a process crashes, you can find fault logs in **/data/log/faultlog/faultlogger/** on the device. The log files are named in the format of **jscrash-process name-process UID-time (milliseconds).log**. They contain information such as the device name, system version, and process crash call stack.
74
75    ![](figures/jscrash.png)
76<!--DelEnd-->
77
78### Analyzing Faults
79
80Generally, the cause of the fault can be found by locating the problematic code based on the exception scenario, error message, and call stack. The call stack is analyzed in the following cases:
81
82#### 1. StackTrace Scenarios
83
84In JS Crash fault logs, the **StackTrace** field provides the call stack information about the JS Crash exception. Common **StackTrace** information includes the following:
85
861. The stack top indicates the problematic code, as shown in the following example. You can click the link to locate the problematic code.
87    ```
88    Device info:xxx
89    Build info:xxx-xxx x.x.x.xxx(xxxx)
90    Fingerprint:ed1811f3f5ae13c7262b51aab73ddd01df95b2c64466a204e0d70e6461cf1697
91    Timestamp:xxxx-xx-xx xx:xx:xx.xxx
92    Module name:com.xxx.xxx
93    Version:1.0.0
94    VersionCode:1000000
95    PreInstalled:No
96    Foreground:Yes
97    Pid:31255
98    Uid:20020145
99    Reason:Error
100    Error name:Error
101    Error message:JSERROR
102    Sourcecode:
103                    throw new ErrOr("JSERROR");
104                          ^
105    Stacktrace:
106        at anonymous entry (entry/src/main/ets/pages/Index.ets:13:19)
107    ```
108
1092. If "Stack Cannot get SourceMap info, dump raw stack" is displayed in the call stack, as shown in the following example, the system fails to retrieve information from SourceMap and only displays the row number of the problematic code in the compiled code in an eTS stack. You can click the link to identify where the error occurred in the compiled code.
110    ```
111    Device info:xxx
112    Build info:xxx-xxx x.x.x.xxx(xxxx)
113    Fingerprint:a370fceb59011d96e41e97bda139b1851c911012ab8c386d1a2d63986d6d226d
114    Timestamp:xxxx-xx-xx xx:xx:xx.xxx
115    Module name:com.xxx.xxx
116    Version:1.0.0
117    VersionCode:1000000
118    PreInstalled:No
119    Foreground:Yes
120    Pid:39185
121    Uid:20020145
122    Reason:Error
123    Error name:Error
124    Error message:JSERROR
125    Stacktrace:
126    Cannot get SourceMap info, dump raw stack:
127        at anonymous entry (entry/src/main/ets/pages/Index.ts:49:49)
128    ```
129
1303. If "SourceMap is not initialized yet" is displayed in the call stack, as shown in the following example, SourceMap has not been initialized and the row number of the problematic code in the compiled code in an eTS stack is displayed. In this case, this log is added to notify developers. You can click the link to identify where the error occurred in the compiled code. The following is an example.
131    ```
132    Device info:xxx
133    Build info:xxx-xxx x.x.x.xxx(xxxx)
134    Fingerprint:377ef8529301363f373ce837d0bf83aacfc46112502143237e2f4026e86a0510
135    Timestamp:xxxx-xx-xx xx:xx:xx.xxx
136    Module name:com.xxx.xxx
137    Version:1.0.0
138    Versioncode:1000000
139    PreInstalled:No
140    Foreground:Yes
141    Pid:6042
142    Uid:20020145
143    Reason:Error
144    Error name:Error
145    Error message:JSERROR
146    Sourcecode:
147                throw new Error("JSERROR");
148                      ^
149    Stacktrace:
150    SourceMap is not initialized yet
151    at anonymous entry (entry/src/main/ets/pages/Index.ts:49:49)
152    ```
153
1544. The native stack is printed in the call stack, as shown in the following example. Generally, the **libark_jsruntime.so** dynamic library is at the top of the stack. This is because JS exceptions are thrown by the VM. Search for the error from the top down. Generally, the next frame of **libace_napi.z.so** is the location where an exception is thrown. The following is an example.
155    ```
156    Device info:xxx
157    Build info:xxx-xxx x.x.x.xxx(xxxx)
158    Fingerprint:89f2b64b24d642b0fc64e3a7cf68ca39fecaa580ff5736bb9d6706ea4cdf2c93
159    Timestamp:xxxx-xx-xx xx:xx:xx.xxx
160    Module name:com.xxx.xxx
161    Version:1.0.0
162    VersionCode:1000000
163    PreInstalled:No
164    Foreground:No
165    Pid:14325
166    Uid:20020145
167    Reason:ReferenceError
168    Error name:ReferenceError
169    Error message:Cannot find module 'com.xxx.xxx/entry/EntryAbility' , which is application Entry Point
170    Stacktrace:
171    SourceMap is not initialized yet
172    #01 pc 000000000028ba3b /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
173    #02 pc 00000000001452ff /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
174    #03 pC 0000000000144c9f /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
175    #04 pc 00000000001c617b /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
176    #05 pc 00000000004c3cb7 /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
177    #06 pc 00000000004c045f /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
178    #07 pc 000000000038034f /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
179    #08 pc 00000000004b2d9b /system/lib64/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
180    #09 pc 0000000000037e7f /system/lib64/platformsdk/libace_napi.z.so(10ceafd39b5354314d2fe3059b8f9e4f)
181    #10 pc 00000000000484cf /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014) <- Location where an exception is thrown
182    #11 pc 000000000004fce7 /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
183    #12 pc 000000000004e9fb /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
184    #13 pc 000000000004eb7b /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
185    #14 pc 000000000004f5c7 /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
186    #15 pc 00000000000303cf /system/lib64/platformsdk/libuiabilitykit_native.z.so(3203F4CCe84a43b519d0a731dfOdb1a3)
187    ```
188
189#### 2. Call Stack Analysis
190
191Perform call stack analysis as follows:
192
193- Case 1: A hyperlink is provided to go to the problematic code.
194
195  If the path or offset address in the stack trace information in the FaultLog points to a line of code of the current project, a hyperlink is provided. You can click the link in DevEco Studio to locate the code line.
196
197- Case 2: The hyperlink provided to go to the problematic code does not work.
198
199  If "Cannot get Source Map info, dump raw stack" is displayed, the JS stack fails to obtain the row and column numbers for the problematic code. In this case, clicking the provided hyperlink in DevEco Studio navigates you to an incorrect position or displays an error that indicates the position does not exist.
200
201  When an error occurs during the running of application code, the error stack information is printed. If the TS stack fails to obtain the row and column numbers for ArkTS code, the filename extension of the error stack is still "ets". You need to compile the intermediate product in the **build** directory to generate TS code and locate the problematic code in JS. For details, see [Stack Trace Analysis](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-release-app-stack-analysis-V5).
202
203
204## Case Study
205
206The following describes the most common error types, namely, **TypeError** and **Error**, that cause JS crashes.
207
208### TypeError Analysis
209
210As one of the most common errors that cause JS crashes, TypeError is thrown when the variable type is not the expected one. In other words, the variable is not verified before use. The error message is as follows:
211
212```
213Error name:TypeError
214Error message:Cannot read property xxx of undefined
215```
216
217#### Case 1: JS crash occasionally occurs when a gesture value is updated.
218
2191. Obtain the JS crash log:
220
221    ```
222    Generated by HiviewDFX@OpenHarmony
223    ================================================================
224    Device info:xxxx
225    Build info:xxxx
226    Fingerprint:9851196f9fed7fd818170303296ae7a5767c9ab11f38fd8b0072f0e32c42ea39
227    Timestamp:xxxx-xx-xx xx:xx:xx.xxx
228    Module name:com.xxx.xxx
229    Version:1.0.0.29
230    VersionCode:10000029
231    PreInstalled:Yes
232    Foreground:No
233    Pid:2780
234    Uid:20020018
235    Reason:TypeError
236    Error name:TypeError
237    Error message:Cannot read property needRenderTranslate of undefined
238    Stacktrace:
239    Cannot get SourceMap info, dump raw stack:
240        at updateGestureValue entry (phone/src/main/ets/SceneBoard/recent/scenepanel/recentpanel/RecentGesture.ts:51:51)
241        at onRecentGestureActionBegin entry (phone/src/main/ets/SceneBoard/scenemanager/SCBScenePanel.ts:5609:5609)
242        at anonymous entry (phone/src/main/ets/SceneBoard/scenemanager/SCBScenePanel.ts:555:555)
243        at anonymous entry (phone/src/main/ets/SceneBoard/recent/RecentEventView.ts:183:183)
244    ```
245
2462. Analyze log information.
247
248    According to the log information, **TypeError** is reported because the **needRenderTranslate** object is **undefined**. Then, obtain the error location based on the stack trace.
249If "Cannot get SourceMap info, dump raw stack" is displayed, the application is installed using a release package and the eTS row and column numbers cannot be converted from the JS stack. You can refer to [Stack Trace Analysis](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-release-app-stack-analysis-V5) to parse the row number.
250
2513. Locate the error code.
252
253    Based on the preceding JS stack and error variable analysis, the error code can be located as follows:
254
255    ```
256      // Update the gesture value.
257      public updateGestureValue(screenWidth: number, recentScale: number, sceneContainerSessionList: SCBSceneContainerSession[]) {
258        // Calculate the moving distance of the hand.
259        this.translationUpY = (this.multiCardsNum >= 1)? sceneContainerSessionList[this.multiCardsNum - 1].needRenderTranslate.translateY: 0; ---> Number of the error line
260        this.translationDownY = (this.multiCardsNum >= 2) ? sceneContainerSessionList[this.multiCardsNum - 2].needRenderTranslate.translateY : 0;
261        this.screenWidth = px2vp(screenWidth);
262        this.recentScale = recentScale;
263      }
264    ```
265
2664. Solution
267
268    According to the preceding analysis, the member variable **needRenderTranslate** of **sceneContainerSessionList** may be undefined. A protection needs to be added to avoid this type of problem. For example, you can add a '?' operator before the access object for protection.
269
270    ```
271    // Update the gesture value.
272    public updateGestureValue(screenWidth: number, recentScale: number, sceneContainerSessionList: SCBSceneContainerSession[]) {
273      // Calculate the moving distance of the hand.
274      this.translationUpY = (this.multiCardsNum >= 1) ?
275        sceneContainerSessionList[this.multiCardsNum - 1]?.needRenderTranslate.translateY : 0;
276      this.translationDownY = (this.multiCardsNum >= 2) ?
277        sceneContainerSessionList[this.multiCardsNum - 2]?.needRenderTranslate.translateY : 0;
278      this.screenWidth = px2vp(screenWidth);
279      this.recentScale = recentScale;
280    }
281    ```
282
2835. Suggestions
284
285    To solve this problem, we need to add necessary null checks in the coding phase to ensure security of object access. In many scenarios, the null check may only be a workaround. You need to check the object construction or value assignment logic based on service requirements.
286
287### Error Analysis
288
289Error problems are JS exceptions thrown by developers or JS libraries.
290
291There are two scenarios for this type of problem:
2921.	If the application encounters a fault that cannot be rectified, a JS exception is thrown to terminate the service and generate a fault log.
2932.	The service is terminated by an exception thrown by an API of the dependent JS library or module. In this case, you need to consider using try-catch to capture such exceptions.
294
295
296#### Case 1: Throw a custom JS exception to terminate an application.
297
298You can use the following code to throw a JS exception:
299
300```
301throw new Error("TEST JS ERROR")
302```
303
304Based on the fault logs collected by DevEco Studio FaultLog, you can locate the exception based on the JS exception stack.
305
306![](figures/jscrash_error_trigger.png)
307
308To solve this problem, locate the problematic code line based on the fault log and review the context.
309
310#### Case 2: Handle the JS crash caused by a JS exception thrown by a third-party API.
311
3121. Obtain the JS crash log. The key log information is as follows:
313    ```
314    Error name:Error
315    Error message:BussinessError 2501000: Operation failed.
316    Error code:2501000
317    Stacktrace:
318    Cannot get SourceMap info, dump raw stack:
319      at onStart entry (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/feature/systemstatus/linkspeedcomponent/src/main/ets/default/controller/NetSpeedController.ts:50:1)
320      at NetSpeedController entry (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/feature/systemstatus/linkspeedcomponent/src/main/ets/default/controller/NetSpeedController.ts:43:43)
321      at getInstance entry (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/staticcommon/basiccommon/src/main/ets/component/utils/SingletonHelper.ts:17:17)
322      at func_main_0 entry (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/feature/systemstatus/linkspeedcomponent/src/main/ets/default/controller/NetSpeedController.ts:325:325)
323    ```
324
3252. Analyze log information.
326
327    According to the log information, an **Error** exception is thrown by the code. Then, obtain the error location based on the stack trace.
328If "Cannot get SourceMap info, dump raw stack" is displayed, the application is installed using a release package and the eTS row and column numbers cannot be converted from the JS stack. You can refer to [Stack Trace Analysis](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-release-app-stack-analysis-V5) to parse the row number.
329
3303. Locate the error code.
331
332    Based on the preceding JS stack, you can locate the code in the **NetSpeedController.ts** file. The exception is thrown when **wifiManager.on()** is called.
333
334    ```
335    onStart(): void {
336      super.onStart();
337      log.showInfo('onStart');
338      ...
339      wifiManager.on('wifiConnectionChange', (data) => {
340        this.isConnected = data === 1 ? true : false;
341        this.handleUpdateState();
342      });
343      wifiManager.on('wifiStateChange', (data) => {
344        this.isWifiActive = data === 1 ? true : false;
345        this.handleUpdateState();
346      });
347      ...
348    }
349    ```
350
3514. Solution
352
353    According to the analysis of the source code, **wifiManager.on()** throws "BussinessError 2501000: Operation failed" occasionally. If this exception does not cause the application to crash, use try-catch to capture and process the exception. Modify the code as follows:
354
355    ```
356    onStart(): void {
357      super.onStart();
358      log.showInfo('onStart');
359      ...
360      try {
361        wifiManager.on('wifiConnectionChange', (data) => {
362          this.isConnected = data === 1 ? true : false;
363          this.handleUpdateState();
364        });
365      } catch (error) {
366        log.showError('wifiConnectionChange error');
367      }
368      try {
369        wifiManager.on('wifiStateChange', (data) => {
370          this.isWifiActive = data === 1 ? true : false;
371          this.handleUpdateState();
372        });
373      } catch (error) {
374        log.showError('wifiStateChange error');
375      }
376      ...
377    }
378    ```
379
3805. Suggestions
381
382    For such problems, we can use the JS exception mechanism in the coding phase to identify various exception scenarios. In addition, consider capturing the exceptions thrown by APIs to prevent unnecessary interrupts of the main services of the application.
383