From d4c1877d6c650c3368e1c81bba0695b5dc91df43 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 22 Jan 2015 14:48:18 +0900 Subject: [PATCH 01/26] mrbgem system solves dependency problem. --- mrblib/require.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index 3cf6255..4d2ea25 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -2,8 +2,7 @@ class LoadError < ScriptError; end module Kernel def load(path) - raise NotImplementedError.new "'require' method depends on File" unless Object.const_defined?(:File) - raise TypeError unless path.class == String + raise TypeError unless path.class == String if File.exist?(path) && File.extname(path) == ".mrb" _load_mrb_file path @@ -15,8 +14,7 @@ def load(path) end def require(path) - raise NotImplementedError.new "'require' method depends on File" unless Object.const_defined?(:File) - raise TypeError unless path.class == String + raise TypeError unless path.class == String # require method can load .rb, .mrb or without-ext filename only. unless ["", ".rb", ".mrb"].include? File.extname(path) From 864c740ef0e937ca6fbc87a8977a342c399690cf Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Tue, 3 Mar 2015 14:29:30 +0900 Subject: [PATCH 02/26] Kernel.eval accepts only one argument on mruby 1.0.0. --- mrblib/require.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index f9b3f07..2a8160b 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -1,6 +1,17 @@ class LoadError < ScriptError; end module Kernel + begin + eval "1", nil + def _eval_load(*args) + Kernel.eval(*args) + end + rescue ArgumentError + def _eval_load(*args) + Kernel.eval(args[0]) + end + end + def load(path) raise TypeError unless path.class == String @@ -8,7 +19,7 @@ def load(path) _load_mrb_file path elsif File.exist?(path) # _load_rb_str File.open(path).read.to_s, path - Kernel.eval File.open(path).read.to_s, nil, path + _eval_load File.open(path).read.to_s, nil, path else raise LoadError.new "File not found -- #{path}" end From c5ed540e0e0be79e9ac75a5243be327533ace00c Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Tue, 3 Mar 2015 14:40:59 +0900 Subject: [PATCH 03/26] mruby-require uses eval now. --- run_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/run_test.rb b/run_test.rb index d1e6fec..2a99a9d 100644 --- a/run_test.rb +++ b/run_test.rb @@ -20,6 +20,7 @@ toolchain :gcc conf.gembox 'default' + conf.gem :core => 'mruby-eval' conf.gem :git => 'https://github.com/iij/mruby-io.git' conf.gem :git => 'https://github.com/iij/mruby-dir.git' conf.gem :git => 'https://github.com/iij/mruby-tempfile.git' From 0838f04c869092c924688680259e78525f959762 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Tue, 3 Mar 2015 16:37:30 +0900 Subject: [PATCH 04/26] more tests for Kernel.require --- test/d/required.rb | 12 ++++++++++++ test/require.rb | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 test/d/required.rb create mode 100644 test/require.rb diff --git a/test/d/required.rb b/test/d/required.rb new file mode 100644 index 0000000..679f487 --- /dev/null +++ b/test/d/required.rb @@ -0,0 +1,12 @@ +# global variables +$gvar0 = 1 +$gvar1 = 1 + +# toplevel local variables +lvar0 = 1 +lvar1 = 1 + +# define a procedure +def proc0 + :proc0 +end diff --git a/test/require.rb b/test/require.rb new file mode 100644 index 0000000..43104ee --- /dev/null +++ b/test/require.rb @@ -0,0 +1,24 @@ +assert("Kernel.require") do + # see d/required.rb + $gvar1 = 0 + lvar1 = 0 + + assert_true require(File.join(File.dirname(__FILE__), "d", "required.rb")) + + # Kernel.require can create a global variable + assert_equal 1, $gvar0 + + # Kernel.require can change value of a global variable + assert_equal 1, $gvar1 + + # Kernel.require cannot create a local variable + assert_raise(NoMethodError) do + lvar0 + end + + # Kernel.require cannot change value of a local variable + assert_equal 0, lvar1 + + # Kernel.require can define a toplevel procedure + assert_equal :proc0, proc0 +end From 99568dc5309710f27df05a2db2c13ddad60cc6b9 Mon Sep 17 00:00:00 2001 From: cho45 Date: Wed, 14 Dec 2016 11:33:00 +0900 Subject: [PATCH 05/26] Make compatible `self` in required file with normal ruby's. --- mrblib/require.rb | 4 ++-- test/test_context.rb | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/test_context.rb diff --git a/mrblib/require.rb b/mrblib/require.rb index 2a8160b..620a30b 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -4,11 +4,11 @@ module Kernel begin eval "1", nil def _eval_load(*args) - Kernel.eval(*args) + self.eval(*args) end rescue ArgumentError def _eval_load(*args) - Kernel.eval(args[0]) + self.eval(args[0]) end end diff --git a/test/test_context.rb b/test/test_context.rb new file mode 100644 index 0000000..0011747 --- /dev/null +++ b/test/test_context.rb @@ -0,0 +1,33 @@ +$dir = File.join(Dir.tmpdir, "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}") + +def test_setup + Dir.mkdir($dir) unless File.exist?($dir) + + File.open(File.join($dir, "foo.rb"), "w") do |f| + f.puts "$require_context = self" + end +end + +def test_cleanup + if $dir && File.exist?($dir) + Dir.entries($dir).each do |e| + next if ['.', '..'].include? e + File.unlink File.join($dir,e) + end + Dir.unlink $dir + end +end + + +##### +test_setup +##### + +assert("require context") do + require File.join($dir, 'foo.rb') + assert_equal self, $require_context +end + +##### +test_cleanup +##### From 78d37057641336cb594ad3be5a728ff6127f9119 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 13 Jan 2017 14:42:35 +0900 Subject: [PATCH 06/26] "self" in required script must be the toplevel self. fixes #13. --- mrblib/require.rb | 22 +++++++++++----------- test/d/required.rb | 7 +++++++ test/require.rb | 4 ++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index 620a30b..cdf25ac 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -1,17 +1,17 @@ class LoadError < ScriptError; end -module Kernel - begin - eval "1", nil - def _eval_load(*args) - self.eval(*args) - end - rescue ArgumentError - def _eval_load(*args) - self.eval(args[0]) - end +begin + eval "1", nil + def _require_eval_load(*args) + self.eval(*args) end +rescue ArgumentError + def _require_eval_load(*args) + self.eval(args[0]) + end +end +module Kernel def load(path) raise TypeError unless path.class == String @@ -19,7 +19,7 @@ def load(path) _load_mrb_file path elsif File.exist?(path) # _load_rb_str File.open(path).read.to_s, path - _eval_load File.open(path).read.to_s, nil, path + _require_eval_load File.open(path).read.to_s, nil, path else raise LoadError.new "File not found -- #{path}" end diff --git a/test/d/required.rb b/test/d/required.rb index 679f487..d6218cd 100644 --- a/test/d/required.rb +++ b/test/d/required.rb @@ -10,3 +10,10 @@ def proc0 :proc0 end + +# define a new method of an existing class. +class MrubyRequireClass + def foo + :foo + end +end diff --git a/test/require.rb b/test/require.rb index 43104ee..95e1ef0 100644 --- a/test/require.rb +++ b/test/require.rb @@ -2,6 +2,7 @@ # see d/required.rb $gvar1 = 0 lvar1 = 0 + class MrubyRequireClass; end assert_true require(File.join(File.dirname(__FILE__), "d", "required.rb")) @@ -21,4 +22,7 @@ # Kernel.require can define a toplevel procedure assert_equal :proc0, proc0 + + # Kernel.require can add a method to an existing class + assert_equal :foo, MrubyRequireClass.new.foo end From c0248d47693aa5990d5e4b66269d2918d5d304b0 Mon Sep 17 00:00:00 2001 From: masahino Date: Thu, 18 Jan 2018 22:29:41 +0900 Subject: [PATCH 07/26] use MRB_PROC_SET_TARGET_CLASS --- src/require.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/require.c b/src/require.c index 0f48c03..6c0132a 100644 --- a/src/require.c +++ b/src/require.c @@ -93,7 +93,7 @@ eval_load_irep(mrb_state *mrb, mrb_irep *irep) replace_stop_with_return(mrb, irep); proc = mrb_proc_new(mrb, irep); - proc->target_class = mrb->object_class; + MRB_PROC_SET_TARGET_CLASS(proc, mrb->object_class); ai = mrb_gc_arena_save(mrb); mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class); From c8556d98f9877dd4d28ca251cdfa68f84dc8dd66 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 8 Mar 2018 15:00:42 +0900 Subject: [PATCH 08/26] fix build with mruby < 1.4.0. --- src/require.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/require.c b/src/require.c index 6c0132a..71c1b9b 100644 --- a/src/require.c +++ b/src/require.c @@ -24,6 +24,12 @@ mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *a #define mrb_yield_with_class mrb_yield_internal #endif +#if MRUBY_RELEASE_NO < 10400 +#define MRB_PROC_SET_TARGET_CLASS(p,tc) do { \ + (p)->target_class = (tc); \ +} while (0) +#endif + #if defined(_WIN32) || defined(_WIN64) #include int mkstemp(char *template) From 910ec033b28758e5ca63a8b4df8dcaf55e4f6445 Mon Sep 17 00:00:00 2001 From: Ichito Nagata Date: Fri, 16 Mar 2018 15:22:20 +0900 Subject: [PATCH 09/26] remove mruby-tempfile dependency --- mrbgem.rake | 1 - 1 file changed, 1 deletion(-) diff --git a/mrbgem.rake b/mrbgem.rake index a8262d4..431e91f 100644 --- a/mrbgem.rake +++ b/mrbgem.rake @@ -5,7 +5,6 @@ MRuby::Gem::Specification.new('mruby-require') do |spec| spec.add_dependency 'mruby-array-ext' spec.add_dependency 'mruby-dir' spec.add_dependency 'mruby-io' - spec.add_dependency 'mruby-tempfile' spec.add_dependency 'mruby-time' spec.add_dependency 'mruby-eval' From 993c612f0bf8c6727c74b27f429c8b5178a3a4cf Mon Sep 17 00:00:00 2001 From: OKUMURA Takahiro Date: Fri, 16 Mar 2018 17:20:05 +0900 Subject: [PATCH 10/26] Add mruby-tempfile to test dependencies When I used mruby-require for test, but raised `NoMethodError: undefined method 'tmpdir'`. - mruby 1.4.0 - mruby-require origin/HEAD (8153a0f193ef434e2249fbd9303e05815ba8b28b) mrbgem.rake: ```ruby MRuby::Gem::Specification.new('mruby-test') do |spec| spec.license = 'MIT' spec.authors = 'Okumura Takahiro' spec.add_test_dependency 'mruby-require', github: 'iij/mruby-require' end ``` Rakefile: ```ruby file :mruby do sh "git clone --branch=1.4.0 --depth=1 git://github.com/mruby/mruby.git" end desc "test" task :test => :mruby do sh "cd mruby && rake all test MRUBY_CONFIG=#{File.expand_path('build_config.rb')}" end task :default => :test ``` build_config.rb: ```ruby MRuby::Build.new do |conf| toolchain :gcc conf.gembox 'full-core' conf.enable_test conf.gem File.expand_path(File.dirname(__FILE__)) end ``` Run `rake`, and then occur the following error: ``` $ rake cd mruby && rake all test MRUBY_CONFIG=/private/tmp/mruby-test/build_config.rb ... snip ... Build summary: ================================================ Config Name: host Output Directory: build/host Binaries: mruby-config, mrbc, mrbtest Included Gems: mruby-sprintf - standard Kernel#sprintf method mruby-print - standard print/puts/p mruby-enum-ext - Enumerable module extension mruby-fiber - Fiber class mruby-enumerator - Enumerator class mruby-array-ext - Array class extension mruby-hash-ext - Hash class extension mruby-toplevel-ext - toplevel object (main) methods extension mruby-struct - standard Struct class mruby-enum-lazy - Enumerator::Lazy class mruby-compiler - mruby compiler library mruby-proc-ext - Proc class extension mruby-method - Method and UnboundMethod class mruby-bin-mirb - mirb command - Binaries: mirb mruby-pack - Array#pack and String#unpack method mruby-bin-strip - irep dump debug section remover command - Binaries: mruby-strip mruby-math - standard Math module mruby-range-ext - Range class extension mruby-io - IO and File class mruby-socket - standard socket class mruby-objectspace - ObjectSpace class mruby-random - Random class mruby-inline-struct - inline structure mruby-kernel-ext - Kernel module extension mruby-class-ext - class/module extension mruby-exit - Kernel#exit method mruby-numeric-ext - Numeric class extension mruby-compar-ext - Enumerable module extension mruby-time - standard Time class mruby-symbol-ext - Symbol class extension mruby-string-ext - String class extension mruby-bin-mrbc - mruby compiler executable mruby-eval - standard Kernel#eval method mruby-error - extensional error handling mruby-object-ext - Object class extension mruby-bin-mruby - mruby command - Binaries: mruby mruby-test - mruby test mruby-dir mruby-require ================================================ >>> Test host <<< mrbtest - Embeddable Ruby Test ......................................................................................................................................................................................?..........................??..................................................................................?.......................................................................................................................?..........................................................................................................................................................................................................................................?..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................??...................NoMethodError: undefined method 'tmpdir' rake aborted! Command failed with status (1): ["build/host/bin/mrbtest"...] /private/tmp/mruby-test/mruby/lib/mruby/build.rb:299:in `run_test' /private/tmp/mruby-test/mruby/Rakefile:123:in `block (2 levels) in ' /private/tmp/mruby-test/mruby/lib/mruby/build.rb:13:in `instance_eval' /private/tmp/mruby-test/mruby/lib/mruby/build.rb:13:in `block in each_target' /private/tmp/mruby-test/mruby/lib/mruby/build.rb:12:in `each' /private/tmp/mruby-test/mruby/lib/mruby/build.rb:12:in `each_target' /private/tmp/mruby-test/mruby/Rakefile:122:in `block in ' Tasks: TOP => test (See full trace by running task with --trace) rake aborted! Command failed with status (1): [cd mruby && rake all test MRUBY_CONFIG=/pr...] /private/tmp/mruby-test/Rakefile:7:in `block in ' Tasks: TOP => default => test (See full trace by running task with --trace) ``` Examining the backtrace --- mruby-tempfile remove from dependencies at 910ec033b28758e5ca63a8b4df8dcaf55e4f6445 --- mrbgem.rake | 1 + 1 file changed, 1 insertion(+) diff --git a/mrbgem.rake b/mrbgem.rake index 431e91f..07bdf0a 100644 --- a/mrbgem.rake +++ b/mrbgem.rake @@ -7,6 +7,7 @@ MRuby::Gem::Specification.new('mruby-require') do |spec| spec.add_dependency 'mruby-io' spec.add_dependency 'mruby-time' spec.add_dependency 'mruby-eval' + spec.add_test_dependency 'mruby-tempfile' spec.cc.include_paths << "#{build.root}/src" end From 9eac8b2513d05dd6dbfa323e50d9ef9935a2848b Mon Sep 17 00:00:00 2001 From: Takeshi Watanabe Date: Wed, 4 Apr 2018 15:21:43 +0900 Subject: [PATCH 11/26] Fix memory leak of `mrb_irep`. Closes #20. --- src/require.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/require.c b/src/require.c index 71c1b9b..b1b1c29 100644 --- a/src/require.c +++ b/src/require.c @@ -99,6 +99,7 @@ eval_load_irep(mrb_state *mrb, mrb_irep *irep) replace_stop_with_return(mrb, irep); proc = mrb_proc_new(mrb, irep); + mrb_irep_decref(mrb, irep); MRB_PROC_SET_TARGET_CLASS(proc, mrb->object_class); ai = mrb_gc_arena_save(mrb); From b764184272df75b5e6b78c7df73cad5d1b3d6171 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 20 Apr 2018 11:20:28 +0900 Subject: [PATCH 12/26] For all f, File.file?(f) -> File.exist?(f). unless someone removes f between two operations. --- mrblib/require.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index cdf25ac..7ae3f84 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -47,19 +47,19 @@ def require(path) filename = nil if ['/', '.'].include? path[0] path0 = filenames.find do |fname| - File.file?(fname) && File.exist?(fname) + File.file?(fname) end else dir = ($LOAD_PATH || []).find do |dir0| filename = filenames.find do |fname| path0 = File.join dir0, fname - File.file?(path0) && File.exist?(path0) + File.file?(path0) end end path0 = dir && filename ? File.join(dir, filename) : nil end - if path0 && File.exist?(path0) && File.file?(path0) + if path0 && File.file?(path0) __require__ path0 else raise LoadError.new "cannot load such file -- #{path}" From 437f846bfaa99b782d8662904bd36c7b4302dd9a Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 20 Apr 2018 12:02:00 +0900 Subject: [PATCH 13/26] compare absolute pathnames. fixes #22. --- mrblib/require.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index 7ae3f84..74dc7e3 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -21,7 +21,7 @@ def load(path) # _load_rb_str File.open(path).read.to_s, path _require_eval_load File.open(path).read.to_s, nil, path else - raise LoadError.new "File not found -- #{path}" + raise LoadError, "File not found -- #{path}" end true @@ -32,7 +32,7 @@ def require(path) # require method can load .rb, .mrb or without-ext filename only. unless ["", ".rb", ".mrb"].include? File.extname(path) - raise LoadError.new "cannot load such file -- #{path}" + raise LoadError, "cannot load such file -- #{path}" end filenames = [] @@ -59,20 +59,14 @@ def require(path) path0 = dir && filename ? File.join(dir, filename) : nil end - if path0 && File.file?(path0) - __require__ path0 - else - raise LoadError.new "cannot load such file -- #{path}" + unless path0 && File.file?(path0) + raise LoadError, "cannot load such file -- #{path}" end - end - def __require__(realpath) - raise LoadError.new "File not found -- #{realpath}" unless File.exist? realpath - $" ||= [] - $__mruby_loading_files__ ||= [] + realpath = File.realpath(path0) # already required - return false if ($" + $__mruby_loading_files__).include?(realpath) + return false if ($" + $__mruby_loading_files__).include?(realpath) $__mruby_loading_files__ << realpath load realpath From 6b2500bbb37cc87285f94856932c304615b3da7f Mon Sep 17 00:00:00 2001 From: Ichito Nagata Date: Fri, 11 May 2018 12:13:42 +0900 Subject: [PATCH 14/26] remove mruby-io dependency from test setting --- run_test.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/run_test.rb b/run_test.rb index 2a99a9d..783ec73 100644 --- a/run_test.rb +++ b/run_test.rb @@ -21,7 +21,6 @@ conf.gembox 'default' conf.gem :core => 'mruby-eval' - conf.gem :git => 'https://github.com/iij/mruby-io.git' conf.gem :git => 'https://github.com/iij/mruby-dir.git' conf.gem :git => 'https://github.com/iij/mruby-tempfile.git' From 50d14fd27beadbdddfa5c4944389d2827034eb34 Mon Sep 17 00:00:00 2001 From: Ichito Nagata Date: Fri, 11 May 2018 12:14:58 +0900 Subject: [PATCH 15/26] enable test and debug --- run_test.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run_test.rb b/run_test.rb index 2a99a9d..b9f45c8 100644 --- a/run_test.rb +++ b/run_test.rb @@ -20,6 +20,9 @@ toolchain :gcc conf.gembox 'default' + enable_debug + enable_test + conf.gem :core => 'mruby-eval' conf.gem :git => 'https://github.com/iij/mruby-io.git' conf.gem :git => 'https://github.com/iij/mruby-dir.git' From 83270474cc9621ad8446f6eedc00d1a0a8b61275 Mon Sep 17 00:00:00 2001 From: Ichito Nagata Date: Fri, 11 May 2018 14:08:47 +0900 Subject: [PATCH 16/26] use mruby-io from core --- run_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/run_test.rb b/run_test.rb index 783ec73..ef74be2 100644 --- a/run_test.rb +++ b/run_test.rb @@ -21,6 +21,7 @@ conf.gembox 'default' conf.gem :core => 'mruby-eval' + conf.gem :core => 'mruby-io' conf.gem :git => 'https://github.com/iij/mruby-dir.git' conf.gem :git => 'https://github.com/iij/mruby-tempfile.git' From 0c920c14eabd63af9b267fc0e05e36c4ee12cdba Mon Sep 17 00:00:00 2001 From: Ichito Nagata Date: Fri, 11 May 2018 12:16:15 +0900 Subject: [PATCH 17/26] compare with realpath --- test/test2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test2.rb b/test/test2.rb index b66b9fd..a0a290e 100644 --- a/test/test2.rb +++ b/test/test2.rb @@ -1,4 +1,4 @@ -$dir = File.join(Dir.tmpdir, "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}") +$dir = File.join(File.realpath(Dir.tmpdir), "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}") def test_setup Dir.mkdir($dir) unless File.exist?($dir) From ea927d6cf798acf741fd84663e5abd7cda81d637 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 18 May 2018 10:56:51 +0900 Subject: [PATCH 18/26] mruby-time is not required to build. --- mrbgem.rake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mrbgem.rake b/mrbgem.rake index 07bdf0a..c5edfe6 100644 --- a/mrbgem.rake +++ b/mrbgem.rake @@ -4,11 +4,11 @@ MRuby::Gem::Specification.new('mruby-require') do |spec| spec.add_dependency 'mruby-array-ext' spec.add_dependency 'mruby-dir' - spec.add_dependency 'mruby-io' - spec.add_dependency 'mruby-time' spec.add_dependency 'mruby-eval' + spec.add_dependency 'mruby-io' + spec.add_test_dependency 'mruby-tempfile' + spec.add_test_dependency 'mruby-time' spec.cc.include_paths << "#{build.root}/src" end - From 94965207e051eb8d4ef61ecd565ee933fd815e19 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 18 May 2018 11:00:26 +0900 Subject: [PATCH 19/26] create a temporary file and "require" it. "test/d/required.rb" file may not be available when mrbtest is run. --- test/d/required.rb | 19 ------------------- test/require.rb | 30 ++++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 21 deletions(-) delete mode 100644 test/d/required.rb diff --git a/test/d/required.rb b/test/d/required.rb deleted file mode 100644 index d6218cd..0000000 --- a/test/d/required.rb +++ /dev/null @@ -1,19 +0,0 @@ -# global variables -$gvar0 = 1 -$gvar1 = 1 - -# toplevel local variables -lvar0 = 1 -lvar1 = 1 - -# define a procedure -def proc0 - :proc0 -end - -# define a new method of an existing class. -class MrubyRequireClass - def foo - :foo - end -end diff --git a/test/require.rb b/test/require.rb index 95e1ef0..8e06733 100644 --- a/test/require.rb +++ b/test/require.rb @@ -1,10 +1,36 @@ assert("Kernel.require") do - # see d/required.rb + # preparation $gvar1 = 0 lvar1 = 0 class MrubyRequireClass; end - assert_true require(File.join(File.dirname(__FILE__), "d", "required.rb")) + ret = Tempfile.open(["mruby-require-test", ".rb"]) { |f| + f.write <<-PROGRAM + # global variables + $gvar0 = 1 + $gvar1 = 1 + + # toplevel local variables + lvar0 = 1 + lvar1 = 1 + + # define a procedure + def proc0 + :proc0 + end + + # define a new method of an existing class. + class MrubyRequireClass + def foo + :foo + end + end + PROGRAM + f.flush + + require(f.path) + } + assert_true ret # Kernel.require can create a global variable assert_equal 1, $gvar0 From 4c8d7f0279a30b728f379f2c6f7e58937727cfff Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 18 May 2018 13:21:32 +0900 Subject: [PATCH 20/26] add CI status badge. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 70818ff..1368d47 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ mruby-require ============= +[![Build Status](https://travis-ci.org/iij/mruby-require.svg?branch=master)](https://travis-ci.org/iij/mruby-require) "mruby-require" is a mrbgem, provides [require](http://docs.ruby-lang.org/ja/2.0.0/class/Kernel.html#M_REQUIRE) and From 3262873e63e407aad695472ef966b196e4b8e761 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 18 May 2018 13:57:06 +0900 Subject: [PATCH 21/26] refactor testcases. --- test/load.rb | 20 ++++++++++++++++++ test/require.rb | 48 +++++++++++++++++++++++++++++++++++++++++++- test/test.rb | 34 ------------------------------- test/test_context.rb | 33 ------------------------------ 4 files changed, 67 insertions(+), 68 deletions(-) create mode 100644 test/load.rb delete mode 100644 test/test.rb delete mode 100644 test/test_context.rb diff --git a/test/load.rb b/test/load.rb new file mode 100644 index 0000000..9d04ffc --- /dev/null +++ b/test/load.rb @@ -0,0 +1,20 @@ +assert("Kernel.load") do + assert_raise(LoadError) do + load "/nonexistent.rb" + end + + $load_count = 0 + ret = Tempfile.open(["mruby-require-test", ".rb"]) { |f| + f.write <<-PROGRAM + $load_count += 1 + PROGRAM + f.flush + + load f.path + load f.path + load f.path + } + + assert_true ret + assert_equal 3, $load_count +end diff --git a/test/require.rb b/test/require.rb index 8e06733..3636ea6 100644 --- a/test/require.rb +++ b/test/require.rb @@ -1,9 +1,14 @@ -assert("Kernel.require") do +assert("Kernel.require", "15.3.1.2.13") do # preparation $gvar1 = 0 lvar1 = 0 + lvar2 = 0 class MrubyRequireClass; end + assert_raise(LoadError) do + require "/nonexistent.rb" + end + ret = Tempfile.open(["mruby-require-test", ".rb"]) { |f| f.write <<-PROGRAM # global variables @@ -14,6 +19,12 @@ class MrubyRequireClass; end lvar0 = 1 lvar1 = 1 + # can not read local variables + begin + x = lvar2 + rescue NameError => $lvar2_exc + end + # define a procedure def proc0 :proc0 @@ -30,6 +41,8 @@ def foo require(f.path) } + + # Kernel.require returns true unless an exception is raised assert_true ret # Kernel.require can create a global variable @@ -46,9 +59,42 @@ def foo # Kernel.require cannot change value of a local variable assert_equal 0, lvar1 + # Kernel.require cannot read a local variable + assert_true $lvar2_exc.is_a? NameError + # Kernel.require can define a toplevel procedure assert_equal :proc0, proc0 # Kernel.require can add a method to an existing class + # https://github.com/iij/mruby-require/issues/13 assert_equal :foo, MrubyRequireClass.new.foo end + +$top_self = self +assert("Kernel.require #12") do + Tempfile.open(["mruby-require-test", ".rb"]) { |f| + f.write <<-PROGRAM + $require_context = self + PROGRAM + f.flush + + require(f.path) + } + + assert_equal $top_self, $require_context +end + +assert("Kernel.require #22") do + $gvar2 = 0 + Tempfile.open(["mruby-require-test", ".rb"]) { |f| + f.write <<-PROGRAM + $gvar2 += 1 + PROGRAM + f.flush + + require(f.path) + require("/./" + f.path) + } + + assert_equal 1, $gvar2 +end diff --git a/test/test.rb b/test/test.rb deleted file mode 100644 index 0886cab..0000000 --- a/test/test.rb +++ /dev/null @@ -1,34 +0,0 @@ -$" = [] # init - -assert "Kernel#_load_rb_str" do - assert_equal true, self.methods.include?(:_load_rb_str) - assert_equal false, Object.const_defined?(:LOAD_RB_STR_TEST) - _load_rb_str("LOAD_RB_STR_TEST = 1") - assert_equal true, Object.const_defined?(:LOAD_RB_STR_TEST) -end - -assert "$LOAD_PATH check" do - assert_equal Array, $LOAD_PATH.class -end - -assert '$" check' do - assert_equal [], $" -end - -assert('load - error check') do - assert_raise TypeError, "load(nil) should raise TypeError" do - load nil - end - assert_raise LoadError, "load('notfound') should raise LoadError" do - load 'notfound' - end -end - -assert('require - error check') do - assert_raise TypeError, "require(nil) should raise TypeError" do - require nil - end - assert_raise LoadError, "require('notfound') should raise LoadError" do - require "notfound" - end -end diff --git a/test/test_context.rb b/test/test_context.rb deleted file mode 100644 index 0011747..0000000 --- a/test/test_context.rb +++ /dev/null @@ -1,33 +0,0 @@ -$dir = File.join(Dir.tmpdir, "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}") - -def test_setup - Dir.mkdir($dir) unless File.exist?($dir) - - File.open(File.join($dir, "foo.rb"), "w") do |f| - f.puts "$require_context = self" - end -end - -def test_cleanup - if $dir && File.exist?($dir) - Dir.entries($dir).each do |e| - next if ['.', '..'].include? e - File.unlink File.join($dir,e) - end - Dir.unlink $dir - end -end - - -##### -test_setup -##### - -assert("require context") do - require File.join($dir, 'foo.rb') - assert_equal self, $require_context -end - -##### -test_cleanup -##### From 553591e022bcbd438d019434c03817eb53d70a9c Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Fri, 18 May 2018 13:58:50 +0900 Subject: [PATCH 22/26] set "self" in required program to "main". closes #15. --- mrblib/require.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index 74dc7e3..9692b1e 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -1,13 +1,14 @@ class LoadError < ScriptError; end +$__mruby_require_toplevel_self__ = self begin eval "1", nil def _require_eval_load(*args) - self.eval(*args) + $__mruby_require_toplevel_self__.eval(*args) end rescue ArgumentError def _require_eval_load(*args) - self.eval(args[0]) + $__mruby_require_toplevel_self__.eval(args[0]) end end @@ -80,11 +81,9 @@ def require(path) $LOAD_PATH ||= [] $LOAD_PATH << '.' - if Object.const_defined?(:ENV) $LOAD_PATH.unshift(*ENV['MRBLIB'].split(':')) unless ENV['MRBLIB'].nil? end - $LOAD_PATH.uniq! $" ||= [] From 6cc25394c5a01479aa6488f30132eaf4b060d6a9 Mon Sep 17 00:00:00 2001 From: Yuji Yamano Date: Fri, 14 Sep 2018 06:05:56 -0400 Subject: [PATCH 23/26] Fix compilation error with latest mruby. Fixed #26. Mruby don't stop vm with new byte code implmentation. --- src/require.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/require.c b/src/require.c index b1b1c29..2914e1c 100644 --- a/src/require.c +++ b/src/require.c @@ -19,6 +19,11 @@ #define E_LOAD_ERROR (mrb_class_get(mrb, "LoadError")) +/* We can't use MRUBY_RELEASE_NO to determine if byte code implementation is old */ +#ifdef MKOP_A +#define USE_MRUBY_OLD_BYTE_CODE +#endif + #if MRUBY_RELEASE_NO < 10000 mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c); #define mrb_yield_with_class mrb_yield_internal @@ -48,6 +53,7 @@ mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *a } #endif +#ifdef USE_MRUBY_OLD_BYTE_CODE static void replace_stop_with_return(mrb_state *mrb, mrb_irep *irep) { @@ -58,6 +64,7 @@ replace_stop_with_return(mrb_state *mrb, mrb_irep *irep) irep->ilen++; } } +#endif static int compile_rb2mrb(mrb_state *mrb0, const char *code, int code_len, const char *path, FILE* tmpfp) @@ -97,7 +104,9 @@ eval_load_irep(mrb_state *mrb, mrb_irep *irep) int ai; struct RProc *proc; +#ifdef USE_MRUBY_OLD_BYTE_CODE replace_stop_with_return(mrb, irep); +#endif proc = mrb_proc_new(mrb, irep); mrb_irep_decref(mrb, irep); MRB_PROC_SET_TARGET_CLASS(proc, mrb->object_class); From 03fe79f044c3529ffc47646d0080f33e2d84d225 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 22 Jun 2022 09:29:54 +0900 Subject: [PATCH 24/26] do not use global level `def` block, because it is generating TypeError for whatever reason --- mrblib/require.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index 9692b1e..0dbd2da 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -1,16 +1,6 @@ class LoadError < ScriptError; end $__mruby_require_toplevel_self__ = self -begin - eval "1", nil - def _require_eval_load(*args) - $__mruby_require_toplevel_self__.eval(*args) - end -rescue ArgumentError - def _require_eval_load(*args) - $__mruby_require_toplevel_self__.eval(args[0]) - end -end module Kernel def load(path) @@ -20,7 +10,7 @@ def load(path) _load_mrb_file path elsif File.exist?(path) # _load_rb_str File.open(path).read.to_s, path - _require_eval_load File.open(path).read.to_s, nil, path + $__mruby_require_toplevel_self__.eval(File.open(path).read.to_s, nil, path) else raise LoadError, "File not found -- #{path}" end From 5afbed21d2cf6e8f0c75fa9d4e0397a8ff893d32 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 22 Jun 2022 11:13:01 +0900 Subject: [PATCH 25/26] mruby-dir is only used while testing --- mrbgem.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgem.rake b/mrbgem.rake index c5edfe6..5f64350 100644 --- a/mrbgem.rake +++ b/mrbgem.rake @@ -3,10 +3,10 @@ MRuby::Gem::Specification.new('mruby-require') do |spec| spec.authors = 'Internet Initiative Japan Inc.' spec.add_dependency 'mruby-array-ext' - spec.add_dependency 'mruby-dir' spec.add_dependency 'mruby-eval' spec.add_dependency 'mruby-io' + spec.add_test_dependency 'mruby-dir' spec.add_test_dependency 'mruby-tempfile' spec.add_test_dependency 'mruby-time' From d4df27c1c9d32ac57457b6c47fcfee4941a6e935 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 25 Jun 2022 21:39:09 +0900 Subject: [PATCH 26/26] Small improvements for mruby-3.1 support Address mruby-3.1.0-specific problem where constants cannot be referenced in certain blocks. ref. https://github.com/mruby/mruby/issues/5725 --- mrblib/require.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mrblib/require.rb b/mrblib/require.rb index 0dbd2da..1757a0a 100644 --- a/mrblib/require.rb +++ b/mrblib/require.rb @@ -38,13 +38,13 @@ def require(path) filename = nil if ['/', '.'].include? path[0] path0 = filenames.find do |fname| - File.file?(fname) + ::File.file?(fname) end else dir = ($LOAD_PATH || []).find do |dir0| filename = filenames.find do |fname| - path0 = File.join dir0, fname - File.file?(path0) + path0 = ::File.join dir0, fname + ::File.file?(path0) end end path0 = dir && filename ? File.join(dir, filename) : nil