Skip to content

Fix escape_html/h aliases to use C extension instead of pure Ruby fallback#110

Merged
hsbt merged 1 commit intoruby:masterfrom
ianks:fix-snake-case-alias-perf
Mar 9, 2026
Merged

Fix escape_html/h aliases to use C extension instead of pure Ruby fallback#110
hsbt merged 1 commit intoruby:masterfrom
ianks:fix-snake-case-alias-perf

Conversation

@ianks
Copy link
Contributor

@ianks ianks commented Mar 4, 2026

Situation

CGI.escape_html, CGI.h, and CGI.unescape_html (aliases) run the pure Ruby fallback instead of the optimized C extension. The aliases are defined before the ext is required, so they capture references to the Ruby methods.

CGI.escapeHTML  → CGI::EscapeExt (C)   → 80 bytes/call
CGI.escape_html → CGI::Escape   (Ruby) → 808 bytes/call

Execution

Moved alias definitions after the C extension loads, defining them on EscapeExt when available so they bind to the C methods. Falls back to self (pure Ruby) when the C ext isn't loaded (TruffleRuby, LoadError). Added tests verifying method owner and allocation parity.


class CGIEscapeNativeExtTest < Test::Unit::TestCase
def test_escape_html_uses_native_implementation
omit "C extension not available" unless defined?(CGI::EscapeExt)
Copy link

@rwstauner rwstauner Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are currently failing because the module is declared in ruby (empty):

module EscapeExt; end # :nodoc:

You need the method_defined? check like you did in the lib.

…lback

The snake_case aliases (escape_html, h, unescape_html) were defined
before `require 'cgi/escape.so'`, so they captured references to the
pure Ruby methods. After the C extension loads and prepends EscapeExt,
only the camelCase names (escapeHTML, etc.) resolved to the fast C
implementation — the aliases still called the ~10x slower Ruby path.

Move alias definitions after the C extension loads, and define them on
EscapeExt when available so they bind to the optimized C methods.
@ianks ianks force-pushed the fix-snake-case-alias-perf branch from b429540 to 12dc843 Compare March 5, 2026 16:21
@ianks ianks requested a review from rwstauner March 5, 2026 16:21
Copy link
Member

@ioquatix ioquatix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ioquatix
Copy link
Member

ioquatix commented Mar 9, 2026

@jeremyevans does this LGTY?

@ioquatix
Copy link
Member

ioquatix commented Mar 9, 2026

@hsbt would you mind taking a look at this PR? Thanks!

@hsbt hsbt merged commit 97b055d into ruby:master Mar 9, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants