зеркало из https://github.com/github/ruby.git
[PRISM] Do not load -r until we check if main script can be read
This commit is contained in:
Родитель
dcc976add9
Коммит
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;
|
||||
if (RB_TYPE_P(src, T_FILE)) {
|
||||
VALUE filepath = rb_io_path(src);
|
||||
error = pm_parse_file(&result, filepath);
|
||||
error = pm_load_parse_file(&result, filepath);
|
||||
RB_GC_GUARD(filepath);
|
||||
}
|
||||
else {
|
||||
|
@ -1646,7 +1646,7 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
|
|||
pm_parse_result_t result = { 0 };
|
||||
result.options.line = 1;
|
||||
|
||||
VALUE error = pm_parse_file(&result, file);
|
||||
VALUE error = pm_load_parse_file(&result, file);
|
||||
|
||||
if (error == Qnil) {
|
||||
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 };
|
||||
result.options.line = 1;
|
||||
|
||||
VALUE error = pm_parse_file(&result, fname);
|
||||
VALUE error = pm_load_parse_file(&result, fname);
|
||||
|
||||
if (error == Qnil) {
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* TODO: This should raise a better error when the file cannot be read.
|
||||
* Attempt to load the file into memory. Return a Ruby error if the file cannot
|
||||
* be read.
|
||||
*/
|
||||
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))) {
|
||||
#ifdef _WIN32
|
||||
|
@ -8274,6 +8270,18 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath)
|
|||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* resulting scope node in the given parse result struct. This function could
|
||||
|
|
|
@ -44,7 +44,9 @@ typedef struct {
|
|||
bool parsed;
|
||||
} 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_load_parse_file(pm_parse_result_t *result, 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);
|
||||
|
||||
|
|
43
ruby.c
43
ruby.c
|
@ -2080,11 +2080,15 @@ process_script(ruby_cmdline_options_t *opt)
|
|||
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
|
||||
prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
||||
prism_opt_init(ruby_cmdline_options_t *opt)
|
||||
{
|
||||
ruby_opt_init(opt);
|
||||
memset(result, 0, sizeof(pm_parse_result_t));
|
||||
|
||||
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
|
||||
rb_category_warn(
|
||||
|
@ -2095,8 +2099,18 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
|||
"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_line_set(options, 1);
|
||||
pm_options_command_line_p_set(options, opt->do_print);
|
||||
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");
|
||||
}
|
||||
else if (opt->e_script) {
|
||||
prism_opt_init(opt);
|
||||
error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"));
|
||||
}
|
||||
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
|
||||
// global DATA constant that is a file object that can be read
|
||||
// to read the contents after the marker.
|
||||
// If reading the file did not error, at that point we load the command
|
||||
// line options. We do it in this order so that if the main script fails
|
||||
// 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) {
|
||||
int xflag = opt->xflag;
|
||||
VALUE file = open_load_file(opt->script_name, &xflag);
|
||||
|
||||
size_t offset = result->parser.data_loc.start - result->parser.start + 7;
|
||||
if ((result->parser.start + offset < result->parser.end) && result->parser.start[offset] == '\r') offset++;
|
||||
if ((result->parser.start + offset < result->parser.end) && result->parser.start[offset] == '\n') offset++;
|
||||
const pm_parser_t *parser = &result->parser;
|
||||
size_t offset = parser->data_loc.start - parser->start + 7;
|
||||
|
||||
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_define_global_const("DATA", file);
|
||||
|
|
Загрузка…
Ссылка в новой задаче