Skip to content

Commit dc1e269

Browse files
authored
Print source code with a given context when a parse error happens (jerryscript-project#1403)
Example source: var s = "hello"; if (s) a[,] = s; Output: var s = "hello"; if (s) a[,] = s; ~~~~^ Script Error: SyntaxError: Primary expression expected. [line: 3, column: 5] JerryScript-DCO-1.0-Signed-off-by: László Langó [email protected]
1 parent c8f2747 commit dc1e269

File tree

1 file changed

+170
-2
lines changed

1 file changed

+170
-2
lines changed

Diff for: jerry-main/main-unix.c

+170-2
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,81 @@ print_help (char *name)
130130
name);
131131
} /* print_help */
132132

133+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
134+
135+
/**
136+
* Check whether an error is a SyntaxError or not
137+
*
138+
* @return true - if param is SyntaxError
139+
* false - otherwise
140+
*/
141+
static bool
142+
jerry_value_is_syntax_error (jerry_value_t error_value) /**< error value */
143+
{
144+
if (!jerry_value_is_object (error_value))
145+
{
146+
return false;
147+
}
148+
149+
jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *)"name");
150+
jerry_value_t error_name = jerry_get_property (error_value, prop_name);
151+
jerry_release_value (prop_name);
152+
153+
if (jerry_value_has_error_flag (error_name)
154+
|| !jerry_value_is_string (error_name))
155+
{
156+
return false;
157+
}
158+
159+
jerry_size_t err_str_size = jerry_get_string_size (error_name);
160+
jerry_char_t err_str_buf[err_str_size];
161+
162+
jerry_size_t sz = jerry_string_to_char_buffer (error_name, err_str_buf, err_str_size);
163+
jerry_release_value (error_name);
164+
165+
if (sz == 0)
166+
{
167+
return false;
168+
}
169+
170+
if (!strcmp ((char *) err_str_buf, "SyntaxError"))
171+
{
172+
return true;
173+
}
174+
175+
return false;
176+
} /* jerry_value_is_syntax_error */
177+
178+
/**
179+
* Convert string into unsigned integer
180+
*
181+
* @return converted number
182+
*/
183+
static uint32_t
184+
str_to_uint (const char *num_str_p) /**< string to convert */
185+
{
186+
uint32_t result = 0;
187+
188+
while (*num_str_p != '\0')
189+
{
190+
assert (*num_str_p >= '0' && *num_str_p <= '9');
191+
192+
result *= 10;
193+
result += (uint32_t) (*num_str_p - '0');
194+
num_str_p++;
195+
}
196+
197+
return result;
198+
} /* str_to_uint */
199+
200+
#define SYNTAX_ERROR_CONTEXT_SIZE 2
201+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
202+
203+
/**
204+
* Print error value
205+
*/
133206
static void
134-
print_unhandled_exception (jerry_value_t error_value)
207+
print_unhandled_exception (jerry_value_t error_value) /**< error value */
135208
{
136209
assert (jerry_value_has_error_flag (error_value));
137210

@@ -150,8 +223,103 @@ print_unhandled_exception (jerry_value_t error_value)
150223
{
151224
jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size);
152225
assert (sz == err_str_size);
226+
err_str_buf[err_str_size] = 0;
227+
228+
#ifdef JERRY_ENABLE_ERROR_MESSAGES
229+
if (jerry_value_is_syntax_error (error_value))
230+
{
231+
uint32_t err_line = 0;
232+
uint32_t err_col = 0;
233+
234+
/* 1. parse column and line information */
235+
for (uint32_t i = 0; i < sz; i++)
236+
{
237+
if (!strncmp ((char *) (err_str_buf + i), "[line: ", 7))
238+
{
239+
i += 7;
240+
241+
char num_str[8];
242+
uint32_t j = 0;
243+
244+
while (i < sz && err_str_buf[i] != ',')
245+
{
246+
num_str[j] = (char) err_str_buf[i];
247+
j++;
248+
i++;
249+
}
250+
num_str[j] = '\0';
251+
252+
err_line = str_to_uint (num_str);
253+
254+
if (strncmp ((char *) (err_str_buf + i), ", column: ", 10))
255+
{
256+
break; /* wrong position info format */
257+
}
258+
259+
i += 10;
260+
j = 0;
261+
262+
while (i < sz && err_str_buf[i] != ']')
263+
{
264+
num_str[j] = (char) err_str_buf[i];
265+
j++;
266+
i++;
267+
}
268+
num_str[j] = '\0';
269+
270+
err_col = str_to_uint (num_str);
271+
break;
272+
}
273+
} /* for */
274+
275+
if (err_line != 0 && err_col != 0)
276+
{
277+
uint32_t curr_line = 1;
278+
279+
bool is_printing_context = false;
280+
uint32_t pos = 0;
281+
282+
/* 2. seek and print */
283+
while (buffer[pos] != '\0')
284+
{
285+
if (buffer[pos] == '\n')
286+
{
287+
curr_line++;
288+
}
289+
290+
if (err_line < SYNTAX_ERROR_CONTEXT_SIZE
291+
|| (err_line >= curr_line
292+
&& (err_line - curr_line) <= SYNTAX_ERROR_CONTEXT_SIZE))
293+
{
294+
/* context must be printed */
295+
is_printing_context = true;
296+
}
297+
298+
if (curr_line > err_line)
299+
{
300+
break;
301+
}
302+
303+
if (is_printing_context)
304+
{
305+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%c", buffer[pos]);
306+
}
307+
308+
pos++;
309+
}
310+
311+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "\n");
312+
313+
while (--err_col)
314+
{
315+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "~");
316+
}
317+
318+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "^\n");
319+
}
320+
}
321+
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
153322
}
154-
err_str_buf[err_str_size] = 0;
155323

156324
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: %s\n", err_str_buf);
157325
jerry_release_value (err_str_val);

0 commit comments

Comments
 (0)