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 "config.h"
17 #include "jerryscript.h"
18 #include "test-common.h"
19
20 static jerry_value_t
backtrace_handler(const jerry_value_t function_obj,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_count)21 backtrace_handler (const jerry_value_t function_obj, /**< function object */
22 const jerry_value_t this_val, /**< this value */
23 const jerry_value_t args_p[], /**< argument list */
24 const jerry_length_t args_count) /**< argument count */
25 {
26 JERRY_UNUSED (function_obj);
27 JERRY_UNUSED (this_val);
28
29 uint32_t max_depth = 0;
30
31 if (args_count > 0 && jerry_value_is_number (args_p[0]))
32 {
33 max_depth = (uint32_t) jerry_get_number_value (args_p[0]);
34 }
35
36 return jerry_get_backtrace (max_depth);
37 } /* backtrace_handler */
38
39 static jerry_value_t
run(const char * resource_name_p,const char * source_p)40 run (const char *resource_name_p, /**< resource name */
41 const char *source_p) /**< source code */
42 {
43 jerry_value_t code = jerry_parse ((const jerry_char_t *) resource_name_p,
44 strlen (resource_name_p),
45 (const jerry_char_t *) source_p,
46 strlen (source_p),
47 JERRY_PARSE_NO_OPTS);
48 TEST_ASSERT (!jerry_value_is_error (code));
49
50 jerry_value_t result = jerry_run (code);
51 jerry_release_value (code);
52
53 return result;
54 } /* run */
55
56 static void
compare(jerry_value_t array,uint32_t index,const char * str)57 compare (jerry_value_t array, /**< array */
58 uint32_t index, /**< item index */
59 const char *str) /**< string to compare */
60 {
61 jerry_char_t buf[64];
62
63 size_t len = strlen (str);
64
65 TEST_ASSERT (len < sizeof (buf));
66
67 jerry_value_t value = jerry_get_property_by_index (array, index);
68
69 TEST_ASSERT (!jerry_value_is_error (value)
70 && jerry_value_is_string (value));
71
72 TEST_ASSERT (jerry_get_string_size (value) == len);
73
74 jerry_size_t str_len = jerry_string_to_char_buffer (value, buf, (jerry_size_t) len);
75 TEST_ASSERT (str_len == len);
76
77 jerry_release_value (value);
78
79 TEST_ASSERT (memcmp (buf, str, len) == 0);
80 } /* compare */
81
82 static void
test_get_backtrace_api_call(void)83 test_get_backtrace_api_call (void)
84 {
85 jerry_init (JERRY_INIT_EMPTY);
86
87 jerry_value_t global = jerry_get_global_object ();
88
89 jerry_value_t func = jerry_create_external_function (backtrace_handler);
90 jerry_value_t name = jerry_create_string ((const jerry_char_t *) "backtrace");
91 jerry_value_t result = jerry_set_property (global, name, func);
92 TEST_ASSERT (!jerry_value_is_error (result));
93
94 jerry_release_value (result);
95 jerry_release_value (name);
96 jerry_release_value (func);
97
98 jerry_release_value (global);
99
100 const char *source = ("function f() {\n"
101 " return backtrace(0);\n"
102 "}\n"
103 "\n"
104 "function g() {\n"
105 " return f();\n"
106 "}\n"
107 "\n"
108 "function h() {\n"
109 " return g();\n"
110 "}\n"
111 "\n"
112 "h();\n");
113
114 jerry_value_t backtrace = run ("something.js", source);
115
116 TEST_ASSERT (!jerry_value_is_error (backtrace)
117 && jerry_value_is_array (backtrace));
118
119 TEST_ASSERT (jerry_get_array_length (backtrace) == 4);
120
121 compare (backtrace, 0, "something.js:2");
122 compare (backtrace, 1, "something.js:6");
123 compare (backtrace, 2, "something.js:10");
124 compare (backtrace, 3, "something.js:13");
125
126 jerry_release_value (backtrace);
127
128 /* Depth set to 2 this time. */
129
130 source = ("function f() {\n"
131 " return backtrace(2);\n"
132 "}\n"
133 "\n"
134 "function g() {\n"
135 " return f();\n"
136 "}\n"
137 "\n"
138 "function h() {\n"
139 " return g();\n"
140 "}\n"
141 "\n"
142 "h();\n");
143
144 backtrace = run ("something_else.js", source);
145
146 TEST_ASSERT (!jerry_value_is_error (backtrace)
147 && jerry_value_is_array (backtrace));
148
149 TEST_ASSERT (jerry_get_array_length (backtrace) == 2);
150
151 compare (backtrace, 0, "something_else.js:2");
152 compare (backtrace, 1, "something_else.js:6");
153
154 jerry_release_value (backtrace);
155
156 jerry_cleanup ();
157 } /* test_get_backtrace_api_call */
158
159 static void
test_exception_backtrace(void)160 test_exception_backtrace (void)
161 {
162 jerry_init (JERRY_INIT_EMPTY);
163
164 const char *source = ("function f() {\n"
165 " undef_reference;\n"
166 "}\n"
167 "\n"
168 "function g() {\n"
169 " return f();\n"
170 "}\n"
171 "\n"
172 "g();\n");
173
174 jerry_value_t error = run ("bad.js", source);
175
176 TEST_ASSERT (jerry_value_is_error (error));
177
178 error = jerry_get_value_from_error (error, true);
179
180 TEST_ASSERT (jerry_value_is_object (error));
181
182 jerry_value_t name = jerry_create_string ((const jerry_char_t *) "stack");
183 jerry_value_t backtrace = jerry_get_property (error, name);
184
185 jerry_release_value (name);
186 jerry_release_value (error);
187
188 TEST_ASSERT (!jerry_value_is_error (backtrace)
189 && jerry_value_is_array (backtrace));
190
191 TEST_ASSERT (jerry_get_array_length (backtrace) == 3);
192
193 compare (backtrace, 0, "bad.js:2");
194 compare (backtrace, 1, "bad.js:6");
195 compare (backtrace, 2, "bad.js:9");
196
197 jerry_release_value (backtrace);
198
199 jerry_cleanup ();
200 } /* test_exception_backtrace */
201
202 static void
test_large_line_count(void)203 test_large_line_count (void)
204 {
205 jerry_init (JERRY_INIT_EMPTY);
206
207 const char *source = ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
208 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
209 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
210 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
211 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
212 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
213 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
214 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
215 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
216 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
217 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
218 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
219 "g();\n");
220
221 jerry_value_t error = run ("bad.js", source);
222
223 TEST_ASSERT (jerry_value_is_error (error));
224
225 error = jerry_get_value_from_error (error, true);
226
227 TEST_ASSERT (jerry_value_is_object (error));
228
229 jerry_value_t name = jerry_create_string ((const jerry_char_t *) "stack");
230 jerry_value_t backtrace = jerry_get_property (error, name);
231
232 jerry_release_value (name);
233 jerry_release_value (error);
234
235 TEST_ASSERT (!jerry_value_is_error (backtrace)
236 && jerry_value_is_array (backtrace));
237
238 TEST_ASSERT (jerry_get_array_length (backtrace) == 1);
239
240 compare (backtrace, 0, "bad.js:385");
241
242 jerry_release_value (backtrace);
243
244 jerry_cleanup ();
245 } /* test_large_line_count */
246
247 int
main(void)248 main (void)
249 {
250 TEST_INIT ();
251
252 TEST_ASSERT (jerry_is_feature_enabled (JERRY_FEATURE_LINE_INFO));
253
254 test_get_backtrace_api_call ();
255 test_exception_backtrace ();
256 test_large_line_count ();
257
258 return 0;
259 } /* main */
260