[PRISM] Do not load -r until we check if main script can be read
This commit is contained in:
parent
dcc976add9
commit
f8355e88d6
4
iseq.c
4
iseq.c
@ -1245,7 +1245,7 @@ pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
|
|||||||
VALUE error;
|
VALUE error;
|
||||||
if (RB_TYPE_P(src, T_FILE)) {
|
if (RB_TYPE_P(src, T_FILE)) {
|
||||||
VALUE filepath = rb_io_path(src);
|
VALUE filepath = rb_io_path(src);
|
||||||
error = pm_parse_file(&result, filepath);
|
error = pm_load_parse_file(&result, filepath);
|
||||||
RB_GC_GUARD(filepath);
|
RB_GC_GUARD(filepath);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1646,7 +1646,7 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
|
|||||||
pm_parse_result_t result = { 0 };
|
pm_parse_result_t result = { 0 };
|
||||||
result.options.line = 1;
|
result.options.line = 1;
|
||||||
|
|
||||||
VALUE error = pm_parse_file(&result, file);
|
VALUE error = pm_load_parse_file(&result, file);
|
||||||
|
|
||||||
if (error == Qnil) {
|
if (error == Qnil) {
|
||||||
make_compile_option(&option, opt);
|
make_compile_option(&option, opt);
|
||||||
|
2
load.c
2
load.c
@ -747,7 +747,7 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
|
|||||||
pm_parse_result_t result = { 0 };
|
pm_parse_result_t result = { 0 };
|
||||||
result.options.line = 1;
|
result.options.line = 1;
|
||||||
|
|
||||||
VALUE error = pm_parse_file(&result, fname);
|
VALUE error = pm_load_parse_file(&result, fname);
|
||||||
|
|
||||||
if (error == Qnil) {
|
if (error == Qnil) {
|
||||||
iseq = pm_iseq_new_top(&result.node, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL);
|
iseq = pm_iseq_new_top(&result.node, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL);
|
||||||
|
@ -8252,15 +8252,11 @@ pm_parse_file_script_lines(const pm_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the given filepath and store the resulting scope node in the given
|
* Attempt to load the file into memory. Return a Ruby error if the file cannot
|
||||||
* parse result struct. It returns a Ruby error if the file cannot be read or
|
* be read.
|
||||||
* if it cannot be parsed properly. It is assumed that the parse result object
|
|
||||||
* is zeroed out.
|
|
||||||
*
|
|
||||||
* TODO: This should raise a better error when the file cannot be read.
|
|
||||||
*/
|
*/
|
||||||
VALUE
|
VALUE
|
||||||
pm_parse_file(pm_parse_result_t *result, VALUE filepath)
|
pm_load_file(pm_parse_result_t *result, VALUE filepath)
|
||||||
{
|
{
|
||||||
if (!pm_string_mapped_init(&result->input, RSTRING_PTR(filepath))) {
|
if (!pm_string_mapped_init(&result->input, RSTRING_PTR(filepath))) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -8274,6 +8270,18 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given filepath and store the resulting scope node in the given
|
||||||
|
* parse result struct. It returns a Ruby error if the file cannot be read or
|
||||||
|
* if it cannot be parsed properly. It is assumed that the parse result object
|
||||||
|
* is zeroed out.
|
||||||
|
*/
|
||||||
|
VALUE
|
||||||
|
pm_parse_file(pm_parse_result_t *result, VALUE filepath)
|
||||||
|
{
|
||||||
VALUE error = pm_parse_input(result, filepath);
|
VALUE error = pm_parse_input(result, filepath);
|
||||||
|
|
||||||
// If we're parsing a filepath, then we need to potentially support the
|
// If we're parsing a filepath, then we need to potentially support the
|
||||||
@ -8292,6 +8300,21 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load and then parse the given filepath. It returns a Ruby error if the file
|
||||||
|
* cannot be read or if it cannot be parsed properly.
|
||||||
|
*/
|
||||||
|
VALUE
|
||||||
|
pm_load_parse_file(pm_parse_result_t *result, VALUE filepath)
|
||||||
|
{
|
||||||
|
VALUE error = pm_load_file(result, filepath);
|
||||||
|
if (NIL_P(error)) {
|
||||||
|
error = pm_parse_file(result, filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the given source that corresponds to the given filepath and store the
|
* Parse the given source that corresponds to the given filepath and store the
|
||||||
* resulting scope node in the given parse result struct. This function could
|
* resulting scope node in the given parse result struct. This function could
|
||||||
|
@ -44,7 +44,9 @@ typedef struct {
|
|||||||
bool parsed;
|
bool parsed;
|
||||||
} pm_parse_result_t;
|
} pm_parse_result_t;
|
||||||
|
|
||||||
|
VALUE pm_load_file(pm_parse_result_t *result, VALUE filepath);
|
||||||
VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath);
|
VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath);
|
||||||
|
VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath);
|
||||||
VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath);
|
VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath);
|
||||||
void pm_parse_result_free(pm_parse_result_t *result);
|
void pm_parse_result_free(pm_parse_result_t *result);
|
||||||
|
|
||||||
|
43
ruby.c
43
ruby.c
@ -2080,11 +2080,15 @@ process_script(ruby_cmdline_options_t *opt)
|
|||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call ruby_opt_init to set up the global state based on the command line
|
||||||
|
* options, and then warn if prism is enabled and the experimental warning
|
||||||
|
* category is enabled.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
prism_opt_init(ruby_cmdline_options_t *opt)
|
||||||
{
|
{
|
||||||
ruby_opt_init(opt);
|
ruby_opt_init(opt);
|
||||||
memset(result, 0, sizeof(pm_parse_result_t));
|
|
||||||
|
|
||||||
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
|
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
|
||||||
rb_category_warn(
|
rb_category_warn(
|
||||||
@ -2095,8 +2099,18 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
|||||||
"issue tracker."
|
"issue tracker."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the command line options and parse the script into the given result.
|
||||||
|
* Raise an error if the script cannot be parsed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
||||||
|
{
|
||||||
|
memset(result, 0, sizeof(pm_parse_result_t));
|
||||||
pm_options_t *options = &result->options;
|
pm_options_t *options = &result->options;
|
||||||
|
|
||||||
pm_options_line_set(options, 1);
|
pm_options_line_set(options, 1);
|
||||||
pm_options_command_line_p_set(options, opt->do_print);
|
pm_options_command_line_p_set(options, opt->do_print);
|
||||||
pm_options_command_line_n_set(options, opt->do_loop);
|
pm_options_command_line_n_set(options, opt->do_loop);
|
||||||
@ -2108,21 +2122,32 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
|||||||
rb_raise(rb_eRuntimeError, "Prism support for streaming code from stdin is not currently supported");
|
rb_raise(rb_eRuntimeError, "Prism support for streaming code from stdin is not currently supported");
|
||||||
}
|
}
|
||||||
else if (opt->e_script) {
|
else if (opt->e_script) {
|
||||||
|
prism_opt_init(opt);
|
||||||
error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"));
|
error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error = pm_parse_file(result, opt->script_name);
|
error = pm_load_file(result, opt->script_name);
|
||||||
|
|
||||||
// If we found an __END__ marker, then we're going to define a
|
// If reading the file did not error, at that point we load the command
|
||||||
// global DATA constant that is a file object that can be read
|
// line options. We do it in this order so that if the main script fails
|
||||||
// to read the contents after the marker.
|
// to load, it doesn't require files required by -r.
|
||||||
|
if (NIL_P(error)) {
|
||||||
|
prism_opt_init(opt);
|
||||||
|
error = pm_parse_file(result, opt->script_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found an __END__ marker, then we're going to define a global
|
||||||
|
// DATA constant that is a file object that can be read to read the
|
||||||
|
// contents after the marker.
|
||||||
if (NIL_P(error) && result->parser.data_loc.start != NULL) {
|
if (NIL_P(error) && result->parser.data_loc.start != NULL) {
|
||||||
int xflag = opt->xflag;
|
int xflag = opt->xflag;
|
||||||
VALUE file = open_load_file(opt->script_name, &xflag);
|
VALUE file = open_load_file(opt->script_name, &xflag);
|
||||||
|
|
||||||
size_t offset = result->parser.data_loc.start - result->parser.start + 7;
|
const pm_parser_t *parser = &result->parser;
|
||||||
if ((result->parser.start + offset < result->parser.end) && result->parser.start[offset] == '\r') offset++;
|
size_t offset = parser->data_loc.start - parser->start + 7;
|
||||||
if ((result->parser.start + offset < result->parser.end) && result->parser.start[offset] == '\n') offset++;
|
|
||||||
|
if ((parser->start + offset < parser->end) && parser->start[offset] == '\r') offset++;
|
||||||
|
if ((parser->start + offset < parser->end) && parser->start[offset] == '\n') offset++;
|
||||||
|
|
||||||
rb_funcall(file, rb_intern_const("seek"), 2, SIZET2NUM(offset), INT2FIX(SEEK_SET));
|
rb_funcall(file, rb_intern_const("seek"), 2, SIZET2NUM(offset), INT2FIX(SEEK_SET));
|
||||||
rb_define_global_const("DATA", file);
|
rb_define_global_const("DATA", file);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user