• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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