Skip to content

Commit 4bd1e9b

Browse files
committed
ResumableParser: use throw rather than raise for handled EOS
Since the exception will be swallowed, building a message and backtrace is just a waste of time.
1 parent 181396c commit 4bd1e9b

1 file changed

Lines changed: 26 additions & 13 deletions

File tree

ext/json/ext/parser/parser.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -677,10 +677,17 @@ static VALUE parse_error_new(JSON_ParserState *state, VALUE message, long line,
677677

678678
NORETURN(static) void raise_parse_error(const char *format, JSON_ParserState *state, bool eos)
679679
{
680-
VALUE message = build_parse_error_message(format, state);
681-
if (state->parser) { // line and columns can't be accurate in resumable
682-
rb_exc_raise(parse_error_new(state, message, 0, 0, eos));
680+
if (state->parser) {
681+
if (eos) {
682+
// the error will be swallowed by ResumableParser#parse, so no
683+
// point building a message or backtrace.
684+
rb_throw_obj(state->parser, state->parser);
685+
} else {
686+
// line and columns can't be accurate in resumable
687+
rb_exc_raise(parse_error_new(state, build_parse_error_message(format, state), 0, 0, eos));
688+
}
683689
} else {
690+
VALUE message = build_parse_error_message(format, state);
684691
long line, column;
685692
cursor_position(state, &line, &column);
686693
rb_str_catf(message, " at line %ld column %ld", line, column);
@@ -2379,14 +2386,25 @@ static VALUE cResumableParser_feed(VALUE self, VALUE str)
23792386
struct json_parse_any_args {
23802387
JSON_ParserState *state;
23812388
JSON_ParserConfig *config;
2389+
VALUE parser;
23822390
};
23832391

2384-
static VALUE json_parse_any_resumable_safe(VALUE _args)
2392+
static VALUE json_parse_any_resumable_safe0(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, _args))
23852393
{
23862394
struct json_parse_any_args *args = (struct json_parse_any_args *)_args;
23872395
return (VALUE)json_parse_any(args->state, args->config, true);
23882396
}
23892397

2398+
static VALUE json_parse_any_resumable_safe(VALUE _args)
2399+
{
2400+
struct json_parse_any_args *args = (struct json_parse_any_args *)_args;
2401+
VALUE result = rb_catch_obj(args->parser, json_parse_any_resumable_safe0, _args);
2402+
if (result == args->parser) {
2403+
return (VALUE)false;
2404+
}
2405+
return result;
2406+
}
2407+
23902408
static JSON_ResumableParser *ResumableParser_acquire(VALUE self, bool lock)
23912409
{
23922410
JSON_ResumableParser *parser = cResumableParser_get(self);
@@ -2455,25 +2473,20 @@ static VALUE cResumableParser_parse(VALUE self)
24552473
struct json_parse_any_args args = {
24562474
.state = &parser->state,
24572475
.config = &parser->config,
2476+
.parser = self,
24582477
};
24592478
int status;
24602479
const char *initial_cursor = parser->state.cursor;
24612480
parser->complete = rb_protect(json_parse_any_resumable_safe, (VALUE)&args, &status);
2481+
24622482
if (status) {
2463-
VALUE error_source = rb_ivar_get(rb_errinfo(), i_at_eos);
2464-
if (error_source == self) {
2465-
parser->complete = false; // is an EOS error raised by ourself
2466-
rb_set_errinfo(Qnil);
2467-
status = 0;
2468-
} else {
2469-
parser->complete = true; // a parse error is considered complete
2470-
}
2483+
parser->complete = true; // a parse error is considered complete
24712484
}
24722485

24732486
parser->parsed_bytes += parser->state.cursor - initial_cursor;
24742487
parser->incomplete_bytes = parser->complete ? 0 : parser->state.end - parser->state.cursor;
2475-
24762488
parser->in_use = false;
2489+
24772490
if (status) {
24782491
rb_jump_tag(status); // reraise
24792492
}

0 commit comments

Comments
 (0)