diff --git a/src/selector-native.js b/src/selector-native.js index ee8148342..3b2525d69 100644 --- a/src/selector-native.js +++ b/src/selector-native.js @@ -37,7 +37,26 @@ var hasDuplicate, sortInput, documentElement.webkitMatchesSelector || documentElement.mozMatchesSelector || documentElement.oMatchesSelector || - documentElement.msMatchesSelector; + documentElement.msMatchesSelector, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }; function sortOrder( a, b ) { @@ -110,7 +129,14 @@ function uniqueSort( results ) { return results; } +function escape( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +} + jQuery.extend( { + uniqueSort: uniqueSort, + unique: uniqueSort, + escapeSelector: escape, find: function( selector, context, results, seed ) { var elem, nodeType, i = 0; @@ -140,8 +166,6 @@ jQuery.extend( { return results; }, - uniqueSort: uniqueSort, - unique: uniqueSort, text: function( elem ) { var node, ret = "", diff --git a/src/selector-sizzle.js b/src/selector-sizzle.js index dcee45f37..462cd240a 100644 --- a/src/selector-sizzle.js +++ b/src/selector-sizzle.js @@ -10,5 +10,6 @@ jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; } ); diff --git a/test/unit/selector.js b/test/unit/selector.js index 2f6e9affd..c3394e380 100644 --- a/test/unit/selector.js +++ b/test/unit/selector.js @@ -536,3 +536,9 @@ QUnit.asyncTest( "Iframe dispatch should not affect jQuery (#13936)", 1, functio iframeDoc.write( "
" ); iframeDoc.close(); } ); + +QUnit.test( "Ensure escapeSelector exists (escape tests in Sizzle)", function( assert ) { + assert.expect( 1 ); + + assert.equal( jQuery.escapeSelector( "#foo.bar" ), "\\#foo\\.bar", "escapeSelector present" ); +} );