diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 54d9f48..2ddb633 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: - ruby: ["3.0", "3.1", "3.2"] + ruby: ["3.0", "3.1", "3.2", "3.3"] steps: - uses: actions/checkout@v4 diff --git a/lib/live_ast/common.rb b/lib/live_ast/common.rb index 9cea0fd..5807023 100644 --- a/lib/live_ast/common.rb +++ b/lib/live_ast/common.rb @@ -14,6 +14,8 @@ def arg_to_str(arg) end def arg_to_str2(arg) + return "" if arg.nil? && RUBY_VERSION >= "3.3.0" + arg.to_str rescue NameError thing = arg&.class @@ -47,8 +49,10 @@ def location_for_eval(bind, filename = nil, lineno = nil) if filename lineno ||= 1 [filename, lineno] + elsif RUBY_VERSION >= "3.3.0" + file, line = bind.source_location + ["(eval at #{file}:#{line})", 1] else - bind.source_location ["(eval)", 1] end end diff --git a/lib/live_ast/linker.rb b/lib/live_ast/linker.rb index e79c5c5..0869cc2 100644 --- a/lib/live_ast/linker.rb +++ b/lib/live_ast/linker.rb @@ -74,6 +74,7 @@ def find_method_ast(klass, name, *location) def find_ast(*location) raise ASTNotFoundError unless location.size == 2 raise RawEvalError if location.first == "(eval)" + raise RawEvalError if location.first.match?(/^\(eval at .*\)$/) # Ruby 3.3 raise ASTNotFoundError if location.first == "" ast = fetch_from_cache(*location) diff --git a/test/backtrace_test.rb b/test/backtrace_test.rb index 31ba3f5..71d8caa 100644 --- a/test/backtrace_test.rb +++ b/test/backtrace_test.rb @@ -51,7 +51,14 @@ def test_raise_no_overrides RUBY end - assert_equal orig.first, live.first + if RUBY_VERSION >= "3.3.0" + expected = orig.first.sub(/:[0-9]+\)/, ":LINE)") + actual = live.first.sub(/:[0-9]+\)/, ":LINE)") + + assert_equal expected, actual + else + assert_equal orig.first, live.first + end end end diff --git a/test/caller_test.rb b/test/caller_test.rb index a66448b..173713b 100644 --- a/test/caller_test.rb +++ b/test/caller_test.rb @@ -31,6 +31,9 @@ def raise_after_eval(code, will_succeed) foo RUBY + orig.shift if orig.first.start_with? "= "3.3.0" + orig = assert_raises TypeError do Object.new.live_ast_original_instance_eval("1", nil) end @@ -184,6 +186,15 @@ def test_instance_eval_filename_argument_nil_type_error_no_block assert_equal orig.class, live.class end + def test_instance_eval_filename_argument_nil_ruby_3_3_no_block + unless RUBY_VERSION >= "3.3.0" + skip "nil is not an acceptable filename argument before Ruby 3.3" + end + + assert_equal 1, Object.new.live_ast_original_instance_eval("1", nil) + assert_equal 1, Object.new.instance_eval("1", nil) + end + def test_instance_eval_filename_argument_conversion_type_error_no_block orig = assert_raises TypeError do Object.new.live_ast_original_instance_eval("1", 23) @@ -360,6 +371,7 @@ def test_module_eval_file_line def test_module_eval_to_str file = Minitest::Mock.new file.expect(:to_str, "zebra.rb") + file.expect(:nil?, false) Class.new.module_eval("33 + 44", file) file.verify end @@ -404,33 +416,43 @@ def test_local_var_collision end def test_eval_location_without_binding - expected = ["(eval)", 2] + expected_file = if RUBY_VERSION >= "3.3.0" + /^\(eval at #{__FILE__}:[0-9]+\)$/ + else + /^\(eval\)$/ + end - assert_equal expected, live_ast_original_eval("\n[__FILE__, __LINE__]") + file, line = live_ast_original_eval("\n[__FILE__, __LINE__]") - unfixable do - assert_equal expected, eval("\n[__FILE__, __LINE__]") - end + assert_match expected_file, file + assert_equal 2, line file, line = eval("\n[__FILE__, __LINE__]") - file = LiveAST.strip_token file + adjusted_file = LiveAST.strip_token file - assert_equal expected, [file, line] + refute_match expected_file, file + assert_match expected_file, adjusted_file + assert_equal 2, line end def test_eval_location_with_binding - expected = ["(eval)", 2] + expected_file = if RUBY_VERSION >= "3.3.0" + /^\(eval at #{__FILE__}:[0-9]+\)$/ + else + /^\(eval\)$/ + end - assert_equal expected, live_ast_original_eval("\n[__FILE__, __LINE__]", binding) + file, line = live_ast_original_eval("\n[__FILE__, __LINE__]", binding) - unfixable do - assert_equal expected, eval("\n[__FILE__, __LINE__]", binding) - end + assert_match expected_file, file + assert_equal 2, line file, line = eval("\n[__FILE__, __LINE__]", binding) - file = LiveAST.strip_token file + adjusted_file = LiveAST.strip_token file - assert_equal expected, [file, line] + refute_match expected_file, file + assert_match expected_file, adjusted_file + assert_equal 2, line end DEFINE_BO_TEST = lambda do