Skip to content

Commit e06fda6

Browse files
committed
Attributes: Avoid infinite recursion on non-lowercase attribute getters
Attribute hooks are determined for the lowercase versions of attribute names but this has not been reflected in the bool attribute hooks. The code that temporarily removed a handler to avoid an infinite loop was removing an incorrect handler causing stack overflow. Fixes gh-3133 Refs gh-2914 Refs gh-2916 Closes gh-3134
1 parent 5430c54 commit e06fda6

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

src/attributes/attr.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,18 @@ jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name )
117117
var getter = attrHandle[ name ] || jQuery.find.attr;
118118

119119
attrHandle[ name ] = function( elem, name, isXML ) {
120-
var ret, handle;
120+
var ret, handle,
121+
lowercaseName = name.toLowerCase();
122+
121123
if ( !isXML ) {
122124

123125
// Avoid an infinite loop by temporarily removing this function from the getter
124-
handle = attrHandle[ name ];
125-
attrHandle[ name ] = ret;
126+
handle = attrHandle[ lowercaseName ];
127+
attrHandle[ lowercaseName ] = ret;
126128
ret = getter( elem, name, isXML ) != null ?
127-
name.toLowerCase() :
129+
lowercaseName :
128130
null;
129-
attrHandle[ name ] = handle;
131+
attrHandle[ lowercaseName ] = handle;
130132
}
131133
return ret;
132134
};

test/unit/attributes.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,3 +1642,22 @@ QUnit.test( "SVG class manipulation (gh-2199)", function( assert ) {
16421642
assert.ok( !elem.hasClass( "awesome" ), "SVG element (" + this + ") toggles the class off" );
16431643
} );
16441644
} );
1645+
1646+
QUnit.test( "non-lowercase boolean attribute getters should not crash", function( assert ) {
1647+
assert.expect( 3 );
1648+
1649+
var elem = jQuery( "<input checked required autofocus type='checkbox'>" );
1650+
1651+
jQuery.each( {
1652+
checked: "Checked",
1653+
required: "requiRed",
1654+
autofocus: "AUTOFOCUS"
1655+
}, function( lowercased, original ) {
1656+
try {
1657+
assert.strictEqual( elem.attr( original ), lowercased,
1658+
"The '" + this + "' attribute getter should return the lowercased name" );
1659+
} catch ( e ) {
1660+
assert.ok( false, "The '" + this + "' attribute getter threw" );
1661+
}
1662+
} );
1663+
} );

0 commit comments

Comments
 (0)