Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions lib/cgi/escape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,6 @@ def unescapeHTML(string)
string.force_encoding enc
end

# Synonym for CGI.escapeHTML(str)
alias escape_html escapeHTML
alias h escapeHTML

# Synonym for CGI.unescapeHTML(str)
alias unescape_html unescapeHTML

# TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there
unless RUBY_ENGINE == 'truffleruby'
begin
Expand All @@ -175,6 +168,14 @@ def unescapeHTML(string)
end
end

# Aliases must be defined on EscapeExt so they resolve to the C methods.
target = defined?(CGI::EscapeExt) && CGI::EscapeExt.method_defined?(:escapeHTML) ? CGI::EscapeExt : self
target.module_eval do
alias escape_html escapeHTML
alias h escapeHTML
alias unescape_html unescapeHTML
end

# Escape only the tags of certain HTML elements in +string+.
#
# Takes an element or elements or array of elements. Each element
Expand Down
33 changes: 33 additions & 0 deletions test/cgi/test_cgi_escape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,39 @@ def test_cgi_unescapeElement
end
end

class CGIEscapeNativeExtTest < Test::Unit::TestCase
def test_escape_html_uses_native_implementation
omit "C extension not available" unless defined?(CGI::EscapeExt) && CGI::EscapeExt.method_defined?(:escapeHTML)
assert_equal CGI::EscapeExt, CGI.method(:escape_html).owner
assert_equal CGI::EscapeExt, CGI.method(:h).owner
assert_equal CGI::EscapeExt, CGI.method(:unescape_html).owner
end

def test_escape_html_allocates_same_as_escapeHTML
omit "C extension not available" unless defined?(CGI::EscapeExt) && CGI::EscapeExt.method_defined?(:escapeHTML)

input = "'&\"<>hello world"
n = 100

# Warm up
2.times { n.times { CGI.escapeHTML(input) } }
2.times { n.times { CGI.escape_html(input) } }

GC.disable
before = GC.stat(:total_allocated_objects)
n.times { CGI.escapeHTML(input) }
camel_allocs = GC.stat(:total_allocated_objects) - before

before = GC.stat(:total_allocated_objects)
n.times { CGI.escape_html(input) }
snake_allocs = GC.stat(:total_allocated_objects) - before
GC.enable

assert_equal camel_allocs, snake_allocs,
"escape_html allocated #{snake_allocs} objects vs escapeHTML #{camel_allocs} — alias may not be using the C extension"
end
end

class CGIEscapePureRubyTest < Test::Unit::TestCase
def setup
CGI::EscapeExt.module_eval do
Expand Down