diff options
author | Shugo Maeda <shugo@ruby-lang.org> | 2018-11-08 21:02:45 +0900 |
---|---|---|
committer | Shugo Maeda <shugo@ruby-lang.org> | 2018-11-08 21:02:45 +0900 |
commit | 3891c725ade96b7a847ac133496ad307bd05e920 (patch) | |
tree | 0bf019cccbe7940432c40a012e3218167853649a /activesupport | |
parent | 7f7e7e8b39f56d35993bec4247ac0295cd0c943e (diff) | |
download | rails-3891c725ade96b7a847ac133496ad307bd05e920.tar.gz rails-3891c725ade96b7a847ac133496ad307bd05e920.tar.bz2 rails-3891c725ade96b7a847ac133496ad307bd05e920.zip |
sub, sub!, gsub, and gsub! should set back references
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/core_ext/string/output_safety.rb | 46 | ||||
-rw-r--r-- | activesupport/test/safe_buffer_test.rb | 18 |
2 files changed, 62 insertions, 2 deletions
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 3a80de4617..e3f62d7d26 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -135,10 +135,12 @@ module ActiveSupport #:nodoc: class SafeBuffer < String UNSAFE_STRING_METHODS = %w( capitalize chomp chop delete delete_prefix delete_suffix - downcase gsub lstrip next reverse rstrip slice squeeze strip - sub succ swapcase tr tr_s unicode_normalize upcase + downcase lstrip next reverse rstrip slice squeeze strip + succ swapcase tr tr_s unicode_normalize upcase ) + UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub) + alias_method :original_concat, :concat private :original_concat @@ -249,11 +251,51 @@ module ActiveSupport #:nodoc: end end + UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method| + if unsafe_method.respond_to?(unsafe_method) + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{unsafe_method}(*args, &block) + if block + to_str.#{unsafe_method}(*args) { |*params| + set_block_back_references(block, $~) + block.call(*params) + } + else + to_str.#{unsafe_method}(*args) + end + end + + def #{unsafe_method}!(*args, &block) + @html_safe = false + if block + super(*args) { |*params| + set_block_back_references(block, $~) + block.call(*params) + } + else + super + end + end + EOT + end + end + private def html_escape_interpolated_argument(arg) (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s) end + + def set_block_back_references(block, match_data) + Thread.current[:__active_support_safe_buffer_backref] = match_data + begin + block.binding.eval(<<-EOC) + $~ = Thread.current[:__active_support_safe_buffer_backref] + EOC + ensure + Thread.current[:__active_support_safe_buffer_backref] = nil + end + end end end diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 49a3951623..9449adb6de 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -216,4 +216,22 @@ class SafeBufferTest < ActiveSupport::TestCase x = "Hello".html_safe assert_nil x[/a/, 1] end + + test "Should set back references" do + a = "foo123".html_safe + a2 = a.sub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a2 + assert_not_predicate a2, :html_safe? + a.sub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a + assert_not_predicate a, :html_safe? + + b = "foo123 bar456".html_safe + b2 = b.gsub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b2 + assert_not_predicate b2, :html_safe? + b.gsub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b + assert_not_predicate b, :html_safe? + end end |