aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShugo Maeda <shugo@ruby-lang.org>2018-11-08 21:02:45 +0900
committerShugo Maeda <shugo@ruby-lang.org>2018-11-08 21:02:45 +0900
commit3891c725ade96b7a847ac133496ad307bd05e920 (patch)
tree0bf019cccbe7940432c40a012e3218167853649a
parent7f7e7e8b39f56d35993bec4247ac0295cd0c943e (diff)
downloadrails-3891c725ade96b7a847ac133496ad307bd05e920.tar.gz
rails-3891c725ade96b7a847ac133496ad307bd05e920.tar.bz2
rails-3891c725ade96b7a847ac133496ad307bd05e920.zip
sub, sub!, gsub, and gsub! should set back references
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb46
-rw-r--r--activesupport/test/safe_buffer_test.rb18
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