Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22383,6 +22383,7 @@ typedef struct JSToken {
int line_num; /* line number of token start */
int col_num; /* column number of token start */
const uint8_t *ptr;
const uint8_t *line_start; /* first character of the line of token start */
union {
struct {
JSValue str;
Expand Down Expand Up @@ -22416,6 +22417,7 @@ typedef struct JSParseState {
const uint8_t *buf_start;
const uint8_t *buf_ptr;
const uint8_t *buf_end;
const uint8_t *line_start; /* first character of the current line */
const uint8_t *eol; // most recently seen end-of-line character
const uint8_t *mark; // first token character, invariant: eol < mark

Expand Down Expand Up @@ -22576,13 +22578,8 @@ int JS_PRINTF_FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, JS_PRINTF_FORMAT
/* s->col_num is not advanced during token scanning, so derive the column
as the 1-based offset of the token from the start of its line. */
int err_col_num = s->token.col_num;
if (s->token.ptr && s->token.ptr >= s->buf_start) {
const uint8_t *line_start = s->token.ptr;
while (line_start > s->buf_start &&
line_start[-1] != '\n' && line_start[-1] != '\r')
line_start--;
err_col_num = (int)(s->token.ptr - line_start) + 1;
}
if (s->token.ptr && s->token.ptr >= s->token.line_start)
err_col_num = (int)(s->token.ptr - s->token.line_start) + 1;
build_backtrace(ctx, ctx->rt->current_exception, JS_UNDEFINED, s->filename,
s->token.line_num, err_col_num, backtrace_flags);
return -1;
Expand Down Expand Up @@ -22682,6 +22679,7 @@ static __exception int js_parse_template_part(JSParseState *s,
}
if (c == '\n') {
s->line_num++;
s->line_start = p;
s->eol = &p[-1];
s->mark = p;
} else if (c >= 0x80) {
Expand Down Expand Up @@ -22775,6 +22773,7 @@ static __exception int js_parse_string(JSParseState *s, int sep,
p++;
if (sep != '`') {
s->line_num++;
s->line_start = p;
s->eol = &p[-1];
s->mark = p;
}
Expand Down Expand Up @@ -23102,6 +23101,7 @@ static __exception int next_token(JSParseState *s)
s->token.line_num = s->line_num;
s->token.col_num = s->col_num;
s->token.ptr = p;
s->token.line_start = s->line_start;
c = *p;
switch(c) {
case 0:
Expand Down Expand Up @@ -23129,6 +23129,7 @@ static __exception int next_token(JSParseState *s)
case '\n':
p++;
line_terminator:
s->line_start = p;
s->eol = &p[-1];
s->mark = p;
s->got_lf = true;
Expand Down Expand Up @@ -23157,10 +23158,12 @@ static __exception int next_token(JSParseState *s)
s->line_num++;
s->got_lf = true; /* considered as LF for ASI */
s->eol = p++;
s->line_start = p;
s->mark = p;
} else if (*p == '\r') {
s->got_lf = true; /* considered as LF for ASI */
p++;
s->line_start = p;
} else if (*p >= 0x80) {
c = utf8_decode(p, &p);
/* ignore invalid UTF-8 in comments */
Expand Down Expand Up @@ -23748,6 +23751,7 @@ static __exception int json_next_token(JSParseState *s)
s->token.line_num = s->line_num;
s->token.col_num = s->col_num;
s->token.ptr = p;
s->token.line_start = s->line_start;
c = *p;
switch(c) {
case 0:
Expand All @@ -23773,6 +23777,7 @@ static __exception int json_next_token(JSParseState *s)
case '\n':
s->line_num++;
s->eol = p++;
s->line_start = p;
s->mark = p;
goto redo;
case '\f':
Expand Down Expand Up @@ -25005,6 +25010,7 @@ typedef struct JSParsePos {
int col_num;
bool got_lf;
const uint8_t *ptr;
const uint8_t *line_start;
const uint8_t *eol;
const uint8_t *mark;
} JSParsePos;
Expand All @@ -25016,6 +25022,7 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
sp->line_num = s->token.line_num;
sp->col_num = s->token.col_num;
sp->ptr = s->token.ptr;
sp->line_start = s->line_start;
sp->eol = s->eol;
sp->mark = s->mark;
sp->got_lf = s->got_lf;
Expand All @@ -25029,6 +25036,7 @@ static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp
s->line_num = sp->line_num;
s->col_num = sp->col_num;
s->buf_ptr = sp->ptr;
s->line_start = sp->line_start;
s->eol = sp->eol;
s->mark = sp->mark;
s->got_lf = sp->got_lf;
Expand Down Expand Up @@ -27189,13 +27197,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
{
JSAtom name;
int identifier_line_num = s->token.line_num;
const uint8_t *identifier_line_start = s->token.ptr;
while (identifier_line_start > s->buf_start &&
identifier_line_start[-1] != '\n' &&
identifier_line_start[-1] != '\r')
identifier_line_start--;
int identifier_col_num =
(int)(s->token.ptr - identifier_line_start) + 1;
(int)(s->token.ptr - s->line_start) + 1;
if (s->token.u.ident.is_reserved) {
return js_parse_error_reserved_identifier(s);
}
Expand Down Expand Up @@ -38094,6 +38097,7 @@ static void js_parse_init(JSContext *ctx, JSParseState *s,
s->col_num = 1;
s->buf_start = s->buf_ptr = (const uint8_t *)input;
s->buf_end = s->buf_ptr + input_len;
s->line_start = s->buf_ptr;
s->mark = s->buf_ptr + min_int(1, input_len);
s->eol = s->buf_ptr;
s->token.val = ' ';
Expand Down
20 changes: 20 additions & 0 deletions tests/parse-error-column.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,23 @@ assert(errorLocation("a b").col, 3);
assert(loc.line, 2);
assert(loc.col, 9);
}

/* the offending token starts after a multi-line template literal */
{
const loc = errorLocation("`line1\nline2\nline3`; let y = @");
assert(loc.line, 3);
assert(loc.col, 17);
}

/* the error is raised while scanning a multi-line token: the location is
the token's start, not where scanning stopped */
{
const loc = errorLocation("let x = `abc\ndef");
assert(loc.line, 1);
assert(loc.col, 9);
}
{
const loc = errorLocation("let s = 'ab\\\ncd");
assert(loc.line, 1);
assert(loc.col, 9);
}
Loading