diff --git a/lib/erb.rb b/lib/erb.rb index 0c4653d..040cd18 100644 --- a/lib/erb.rb +++ b/lib/erb.rb @@ -815,9 +815,6 @@ # [template processor]: https://en.wikipedia.org/wiki/Template_processor # class ERB - IDENTITY_METHOD = BasicObject.instance_method(:equal?) # :nodoc: - private_constant :IDENTITY_METHOD - # :markup: markdown # # :call-seq: @@ -1117,7 +1114,7 @@ def new_toplevel(vars = nil) private :new_toplevel def initialized_by_new? # :nodoc: - IDENTITY_METHOD.bind_call(@_init, self.class.singleton_class) + self.class.singleton_class.equal? @_init end private :initialized_by_new? diff --git a/lib/erb/compiler.rb b/lib/erb/compiler.rb index 6d70288..b6185cd 100644 --- a/lib/erb/compiler.rb +++ b/lib/erb/compiler.rb @@ -80,16 +80,11 @@ def initialize(str) end class Scanner # :nodoc: - @scanner_map = defined?(Ractor) ? Ractor.make_shareable({}) : {} + @scanner_map = {}.freeze + class << self - if defined?(Ractor) - def register_scanner(klass, trim_mode, percent) - @scanner_map = Ractor.make_shareable({ **@scanner_map, [trim_mode, percent] => klass }) - end - else - def register_scanner(klass, trim_mode, percent) - @scanner_map[[trim_mode, percent]] = klass - end + def register_scanner(klass, trim_mode, percent) + @scanner_map = @scanner_map.merge([trim_mode, percent].freeze => klass).freeze end alias :regist_scanner :register_scanner end diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb index 1de8925..6da2514 100644 --- a/test/erb/test_erb.rb +++ b/test/erb/test_erb.rb @@ -740,3 +740,43 @@ def teardown ERB::Compiler::Scanner.instance_variable_set('@scanner_map', @save_map) end end + +class TestERBRactor < Test::Unit::TestCase + def test_compile_and_result_in_ractor + assert_ractor(<<~RUBY, require: 'erb') + r = Ractor.new do + ERB.new("Hello, <%= 'world' %>!").result(binding) + end + assert_equal("Hello, world!", r.value) + RUBY + end + + def test_trim_mode_in_ractor + assert_ractor(<<~RUBY, require: 'erb') + src = "<% [1, 2].each do |i| %>\\n<%= i %>\\n<% end %>\\n" + r = Ractor.new(src) { |s| ERB.new(s, trim_mode: '-').result(binding) } + assert_equal("\\n1\\n\\n2\\n\\n", r.value) + + r = Ractor.new(src) { |s| ERB.new(s, trim_mode: '<>').result(binding) } + assert_equal("12", r.value) + RUBY + end + + def test_frozen_erb_instance_reused_across_ractors + assert_ractor(<<~RUBY, require: 'erb') + erb = ERB.new("<%= 1 + 1 %>") + erb.freeze + rs = 2.times.map { Ractor.new(erb) { |e| e.result(binding) } } + assert_equal(["2", "2"], rs.map(&:value)) + RUBY + end + + def test_util_html_escape_in_ractor + assert_ractor(<<~RUBY, require: 'erb') + r = Ractor.new do + ERB::Util.html_escape("