diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-09-10 18:12:38 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-09-10 18:12:38 +0900 |
| commit | c27e45193177b6e4d09d526a248af63c0961035a (patch) | |
| tree | 863c5082109295c880311b2abe1eefc4c748dc4d | |
| parent | c345fe432171cc2b90b614a0b44305b218090de6 (diff) | |
| parent | 9840e5352b2abf96235068f0e9d08f14b1d333cf (diff) | |
| download | mruby-c27e45193177b6e4d09d526a248af63c0961035a.tar.gz mruby-c27e45193177b6e4d09d526a248af63c0961035a.zip | |
Merge pull request #4933 from dearblue/variables
Fix take over file scope variables with `mruby` and `mirb` command
| -rw-r--r-- | include/mruby/compile.h | 1 | ||||
| -rw-r--r-- | lib/mruby/gem.rb | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mirb/bintest/mirb.rb | 17 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 13 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mruby/bintest/mruby.rb | 21 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mruby/tools/mruby/mruby.c | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/parse.y | 10 |
7 files changed, 69 insertions, 4 deletions
diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 7b878d460..e8ab91eb9 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -42,6 +42,7 @@ MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb); MRB_API void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt); MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data); +MRB_API void mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c); /* AST node structure */ typedef struct mrb_ast_node { diff --git a/lib/mruby/gem.rb b/lib/mruby/gem.rb index 4c3cd7f02..6fcaad9c1 100644 --- a/lib/mruby/gem.rb +++ b/lib/mruby/gem.rb @@ -180,6 +180,7 @@ module MRuby f.puts %Q[] f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_init(mrb_state *mrb) {] f.puts %Q[ int ai = mrb_gc_arena_save(mrb);] + f.puts %Q[ struct REnv *e;] unless rbfiles.empty? f.puts %Q[ mrb_#{funcname}_gem_init(mrb);] if objs != [objfile("#{build_dir}/gem_init")] unless rbfiles.empty? f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});] @@ -188,6 +189,9 @@ module MRuby f.puts %Q[ mrb_close(mrb);] f.puts %Q[ exit(EXIT_FAILURE);] f.puts %Q[ }] + f.puts %Q[ e = mrb->c->cibase->env;] + f.puts %Q[ mrb->c->cibase->env = NULL;] + f.puts %Q[ mrb_env_unshare(mrb, e);] end f.puts %Q[ mrb_gc_arena_restore(mrb, ai);] f.puts %Q[}] @@ -214,6 +218,7 @@ module MRuby f.puts %Q[#include <stdlib.h>] unless rbfiles.empty? f.puts %Q[#include <mruby.h>] f.puts %Q[#include <mruby/irep.h>] unless rbfiles.empty? + f.puts %Q[#include <mruby/proc.h>] unless rbfiles.empty? end def print_gem_test_header(f) diff --git a/mrbgems/mruby-bin-mirb/bintest/mirb.rb b/mrbgems/mruby-bin-mirb/bintest/mirb.rb index 0058896f1..3a03726bb 100644 --- a/mrbgems/mruby-bin-mirb/bintest/mirb.rb +++ b/mrbgems/mruby-bin-mirb/bintest/mirb.rb @@ -32,3 +32,20 @@ EOS o, _ = Open3.capture2("bin/mirb -r #{lib.path}", :stdin_data => "Hoge.new.hoge\n") assert_true o.include?('=> :hoge') end + +assert('top level local variables are in file scope') do + lib = Tempfile.new('lib.rb') + lib.write <<-TESTLIB +a = 1 +A = -> { a } + TESTLIB + lib.flush + + o, _ = Open3.capture2("bin/mirb -r #{lib.path}", :stdin_data => <<-TESTCODE) +a +a = 5 +A.call + TESTCODE + + assert_kind_of Integer, o =~ /\bundefined method 'a' \(NoMethodError\).*=> 5\b.*=> 1\b/m +end diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index a0eeaf459..51ba3fd78 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -495,12 +495,9 @@ main(int argc, char **argv) cxt = mrbc_context_new(mrb); -#ifndef DISABLE_MIRB_UNDERSCORE - decl_lv_underscore(mrb, cxt); -#endif - /* Load libraries */ for (i = 0; i < args.libc; i++) { + struct REnv *e; FILE *lfp = fopen(args.libv[i], "r"); if (lfp == NULL) { printf("Cannot open library file. (%s)\n", args.libv[i]); @@ -509,8 +506,16 @@ main(int argc, char **argv) } mrb_load_file_cxt(mrb, lfp, cxt); fclose(lfp); + e = mrb->c->cibase->env; + mrb->c->cibase->env = NULL; + mrb_env_unshare(mrb, e); + mrbc_cleanup_local_variables(mrb, cxt); } +#ifndef DISABLE_MIRB_UNDERSCORE + decl_lv_underscore(mrb, cxt); +#endif + cxt->capture_errors = TRUE; cxt->lineno = 1; mrbc_filename(mrb, cxt, "(mirb)"); diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index 9887a2830..a04093529 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -162,3 +162,24 @@ assert('codegen error') do code = "def f(#{(1..100).map{|n| "a#{n}"} * ","}); end" assert_mruby("", /\Acodegen error:.*\n\z/, false, ["-e", code]) end + +assert('top level local variables are in file scope') do + arb, amrb = Tempfile.new('a.rb'), Tempfile.new('a.mrb') + brb, bmrb = Tempfile.new('b.rb'), Tempfile.new('b.mrb') + crb, cmrb = Tempfile.new('c.rb'), Tempfile.new('c.mrb') + drb, dmrb = Tempfile.new('d.rb'), Tempfile.new('d.mrb') + + File.write arb.path, 'a = 1' + system "#{cmd('mrbc')} -g -o #{amrb.path} #{arb.path}" + File.write brb.path, 'p a' + system "#{cmd('mrbc')} -g -o #{bmrb.path} #{brb.path}" + assert_mruby("", /:1: undefined method 'a' \(NoMethodError\)\n\z/, false, ["-r", arb.path, brb.path]) + assert_mruby("", /:1: undefined method 'a' \(NoMethodError\)\n\z/, false, ["-b", "-r", amrb.path, bmrb.path]) + + File.write crb.path, 'a, b, c = 1, 2, 3; A = -> { b = -2; [a, b, c] }' + system "#{cmd('mrbc')} -g -o #{cmrb.path} #{crb.path}" + File.write drb.path, 'a, b = 5, 6; p A.call; p a, b' + system "#{cmd('mrbc')} -g -o #{dmrb.path} #{drb.path}" + assert_mruby("[1, -2, 3]\n5\n6\n", "", true, ["-r", crb.path, drb.path]) + assert_mruby("[1, -2, 3]\n5\n6\n", "", true, ["-b", "-r", cmrb.path, dmrb.path]) +end diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c index e5c8f3466..793245875 100644 --- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c @@ -10,6 +10,7 @@ #include <mruby/compile.h> #include <mruby/dump.h> #include <mruby/variable.h> +#include <mruby/proc.h> struct _args { FILE *rfp; @@ -307,6 +308,7 @@ main(int argc, char **argv) /* Load libraries */ for (i = 0; i < args.libc; i++) { + struct REnv *e; FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r"); if (lfp == NULL) { fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]); @@ -321,6 +323,10 @@ main(int argc, char **argv) v = mrb_load_file_cxt(mrb, lfp, c); } fclose(lfp); + e = mrb->c->cibase->env; + mrb->c->cibase->env = NULL; + mrb_env_unshare(mrb, e); + mrbc_cleanup_local_variables(mrb, c); } /* Load program */ diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 3ae2022cf..9de45a536 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6377,6 +6377,16 @@ mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser } MRB_API void +mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c) +{ + if (c->syms) { + mrb_free(mrb, c->syms); + c->syms = NULL; + c->slen = 0; + } +} + +MRB_API void mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) { mrb_sym sym; |
