diff --git a/lib/cgi/escape.rb b/lib/cgi/escape.rb index 6d84773..6748198 100644 --- a/lib/cgi/escape.rb +++ b/lib/cgi/escape.rb @@ -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 @@ -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 diff --git a/test/cgi/test_cgi_escape.rb b/test/cgi/test_cgi_escape.rb index 73d99e8..4bf0d45 100644 --- a/test/cgi/test_cgi_escape.rb +++ b/test/cgi/test_cgi_escape.rb @@ -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