Applied the RegExp issues reported by Jeff Robinson here: http://jmrware.com/articles/2010/jqueryregex/jQueryRegexes.html Additionally broke out all remaining inline RegExp. Fixes #7062.

This commit is contained in:
jeresig 2010-09-22 09:16:28 -04:00
parent 19b5d9e874
commit 9dc6e0c572
8 changed files with 66 additions and 50 deletions

View file

@ -1,12 +1,13 @@
(function( jQuery ) { (function( jQuery ) {
var jsc = jQuery.now(), var jsc = jQuery.now(),
rscript = /<script(.|\s)*?\/script>/gi, rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
rselectTextarea = /select|textarea/i, rselectTextarea = /^(?:select|textarea)/i,
rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i, rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
rbracket = /\[\]$/,
jsre = /\=\?(&|$)/, jsre = /\=\?(&|$)/,
rquery = /\?/, rquery = /\?/,
rts = /(\?|&)_=.*?(&|$)/, rts = /([?&])_=[^&]*(&?)/,
rurl = /^(\w+:)?\/\/([^\/?#]+)/, rurl = /^(\w+:)?\/\/([^\/?#]+)/,
r20 = /%20/g, r20 = /%20/g,
@ -61,7 +62,7 @@ jQuery.fn.extend({
// See if a selector was specified // See if a selector was specified
self.html( selector ? self.html( selector ?
// Create a dummy div to hold the results // Create a dummy div to hold the results
jQuery("<div />") jQuery("<div>")
// inject the contents of the document in, removing the scripts // inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE // to avoid any 'Permission Denied' errors in IE
.append(res.responseText.replace(rscript, "")) .append(res.responseText.replace(rscript, ""))
@ -542,7 +543,7 @@ function buildParams( prefix, obj, traditional, add ) {
if ( jQuery.isArray(obj) ) { if ( jQuery.isArray(obj) ) {
// Serialize array item. // Serialize array item.
jQuery.each( obj, function( i, v ) { jQuery.each( obj, function( i, v ) {
if ( traditional || /\[\]$/.test( prefix ) ) { if ( traditional || rbracket.test( prefix ) ) {
// Treat each array item as a scalar. // Treat each array item as a scalar.
add( prefix, v ); add( prefix, v );

View file

@ -3,11 +3,11 @@
var rclass = /[\n\t]/g, var rclass = /[\n\t]/g,
rspace = /\s+/, rspace = /\s+/,
rreturn = /\r/g, rreturn = /\r/g,
rspecialurl = /href|src|style/, rspecialurl = /^(?:href|src|style)$/,
rtype = /(button|input)/i, rtype = /^(?:button|input)$/i,
rfocusable = /(button|input|object|select|textarea)/i, rfocusable = /^(?:button|input|object|select|textarea)$/i,
rclickable = /^(a|area)$/i, rclickable = /^a(?:rea)?$/i,
rradiocheck = /radio|checkbox/; rradiocheck = /^(?:radio|checkbox)$/i;
jQuery.fn.extend({ jQuery.fn.extend({
attr: function( name, value ) { attr: function( name, value ) {

View file

@ -17,21 +17,37 @@ var jQuery = function( selector, context ) {
// A simple way to check for HTML strings or ID strings // A simple way to check for HTML strings or ID strings
// (both of which we optimize for) // (both of which we optimize for)
quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w\-]+)$/, quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w-]+)$)/,
// Is it a simple selector // Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/, isSimple = /^.[^:#\[\.,]*$/,
// Check if a string has a non-whitespace character in it // Check if a string has a non-whitespace character in it
rnotwhite = /\S/, rnotwhite = /\S/,
rwhite = /\s/,
// Used for trimming whitespace // Used for trimming whitespace
trimLeft = /^\s+/, trimLeft = /^\s+/,
trimRight = /\s+$/, trimRight = /\s+$/,
// Check for non-word characters
rnonword = /\W/,
// Match a standalone tag // Match a standalone tag
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
// JSON RegExp
rvalidchars = /^[\],:{}\s]*$/,
rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
// Useragent RegExp
rwebkit = /(webkit)[ \/]([\w.]+)/,
ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
rmsie = /(msie) ([\w.]+)/,
rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
// Keep a UserAgent string for use with jQuery.browser // Keep a UserAgent string for use with jQuery.browser
userAgent = navigator.userAgent, userAgent = navigator.userAgent,
@ -136,7 +152,7 @@ jQuery.fn = jQuery.prototype = {
} }
// HANDLE: $("TAG") // HANDLE: $("TAG")
} else if ( !context && /^\w+$/.test( selector ) ) { } else if ( !context && !rnonword.test( selector ) ) {
this.selector = selector; this.selector = selector;
this.context = document; this.context = document;
selector = document.getElementsByTagName( selector ); selector = document.getElementsByTagName( selector );
@ -509,9 +525,9 @@ jQuery.extend({
// Make sure the incoming data is actual JSON // Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js // Logic borrowed from http://json.org/json2.js
if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") if ( rvalidchars.test(data.replace(rvalidescape, "@")
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") .replace(rvalidtokens, "]")
.replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { .replace(rvalidbraces, "")) ) {
// Try to use the native JSON parser first // Try to use the native JSON parser first
return window.JSON && window.JSON.parse ? return window.JSON && window.JSON.parse ?
@ -761,10 +777,10 @@ jQuery.extend({
uaMatch: function( ua ) { uaMatch: function( ua ) {
ua = ua.toLowerCase(); ua = ua.toLowerCase();
var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) || var match = rwebkit.exec( ua ) ||
/(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || ropera.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) || rmsie.exec( ua ) ||
!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
[]; [];
return { browser: match[1] || "", version: match[2] || "0" }; return { browser: match[1] || "", version: match[2] || "0" };
@ -792,7 +808,7 @@ if ( indexOf ) {
// Verify that \s matches non-breaking spaces // Verify that \s matches non-breaking spaces
// (IE fails on this test) // (IE fails on this test)
if ( !/\s/.test( "\xA0" ) ) { if ( !rwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/; trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/; trimRight = /[\s\xA0]+$/;
} }

View file

@ -1,7 +1,8 @@
(function( jQuery ) { (function( jQuery ) {
var windowData = {}, var windowData = {},
rbrace = /^(?:\{.*\}|\[.*\])$/; rbrace = /^(?:\{.*\}|\[.*\])$/,
rdigit = /\d/;
jQuery.extend({ jQuery.extend({
cache: {}, cache: {},
@ -157,7 +158,7 @@ jQuery.fn.extend({
data = data === "true" ? true : data = data === "true" ? true :
data === "false" ? false : data === "false" ? false :
data === "null" ? null : data === "null" ? null :
/\d/.test( data ) && !isNaN( data ) ? parseFloat( data ) : rdigit.test( data ) && !isNaN( data ) ? parseFloat( data ) :
rbrace.test( data ) ? jQuery.parseJSON( data ) : rbrace.test( data ) ? jQuery.parseJSON( data ) :
data; data;
} catch( e ) {} } catch( e ) {}

4
src/effects.js vendored
View file

@ -1,7 +1,7 @@
(function( jQuery ) { (function( jQuery ) {
var elemdisplay = {}, var elemdisplay = {},
rfxtypes = /toggle|show|hide/, rfxtypes = /^(?:toggle|show|hide)$/,
rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/, rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
timerId, timerId,
fxAttrs = [ fxAttrs = [
@ -31,7 +31,7 @@ jQuery.fn.extend({
display = elemdisplay[ nodeName ]; display = elemdisplay[ nodeName ];
} else { } else {
var elem = jQuery("<" + nodeName + " />").appendTo("body"); var elem = jQuery("<" + nodeName + ">").appendTo("body");
display = elem.css("display"); display = elem.css("display");

View file

@ -1,10 +1,12 @@
(function( jQuery ) { (function( jQuery ) {
var rnamespaces = /\.(.*)$/, var rnamespaces = /\.(.*)$/,
rformElems = /^(?:textarea|input|select)$/i,
rperiod = /\./g,
rspace = / /g,
rescape = /[^\w\s.|`]/g,
fcleanup = function( nm ) { fcleanup = function( nm ) {
return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { return nm.replace(rescape, "\\$&");
return "\\" + ch;
});
}; };
/* /*
@ -339,7 +341,7 @@ jQuery.event = {
jQuery.event.trigger( event, data, parent, true ); jQuery.event.trigger( event, data, parent, true );
} else if ( !event.isDefaultPrevented() ) { } else if ( !event.isDefaultPrevented() ) {
var target = event.target, old, targetType = type.replace(/\..*$/, ""), var target = event.target, old, targetType = type.replace(rnamespaces, ""),
isClick = jQuery.nodeName(target, "a") && targetType === "click", isClick = jQuery.nodeName(target, "a") && targetType === "click",
special = jQuery.event.special[ targetType ] || {}; special = jQuery.event.special[ targetType ] || {};
@ -697,9 +699,7 @@ if ( !jQuery.support.submitBubbles ) {
// change delegation, happens here so we have bind. // change delegation, happens here so we have bind.
if ( !jQuery.support.changeBubbles ) { if ( !jQuery.support.changeBubbles ) {
var formElems = /textarea|input|select/i, var changeFilters,
changeFilters,
getVal = function( elem ) { getVal = function( elem ) {
var type = elem.type, val = elem.value; var type = elem.type, val = elem.value;
@ -724,7 +724,7 @@ if ( !jQuery.support.changeBubbles ) {
testChange = function testChange( e ) { testChange = function testChange( e ) {
var elem = e.target, data, val; var elem = e.target, data, val;
if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
return; return;
} }
@ -788,13 +788,13 @@ if ( !jQuery.support.changeBubbles ) {
jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
} }
return formElems.test( this.nodeName ); return rformElems.test( this.nodeName );
}, },
teardown: function( namespaces ) { teardown: function( namespaces ) {
jQuery.event.remove( this, ".specialChange" ); jQuery.event.remove( this, ".specialChange" );
return formElems.test( this.nodeName ); return rformElems.test( this.nodeName );
} }
}; };
@ -1073,7 +1073,7 @@ function liveHandler( event ) {
} }
function liveConvert( type, selector ) { function liveConvert( type, selector ) {
return (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
} }
jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +

View file

@ -2,18 +2,13 @@
var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
rleadingWhitespace = /^\s+/, rleadingWhitespace = /^\s+/,
rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
rtagName = /<([\w:]+)/, rtagName = /<([\w:]+)/,
rtbody = /<tbody/i, rtbody = /<tbody/i,
rhtml = /<|&#?\w+;/, rhtml = /<|&#?\w+;/,
rnocache = /<script|<object|<embed|<option|<style/i, rnocache = /<(?:script|object|embed|option|style)/i,
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5) rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5)
fcloseTag = function( all, front, tag ) { raction = /\=([^="'>\s]+\/)>/g,
return rselfClosing.test( tag ) ?
all :
front + "></" + tag + ">";
},
wrapMap = { wrapMap = {
option: [ 1, "<select multiple='multiple'>", "</select>" ], option: [ 1, "<select multiple='multiple'>", "</select>" ],
legend: [ 1, "<fieldset>", "</fieldset>" ], legend: [ 1, "<fieldset>", "</fieldset>" ],
@ -207,7 +202,7 @@ jQuery.fn.extend({
return jQuery.clean([html.replace(rinlinejQuery, "") return jQuery.clean([html.replace(rinlinejQuery, "")
// Handle the case in IE 8 where action=/test/> self-closes a tag // Handle the case in IE 8 where action=/test/> self-closes a tag
.replace(/\=([^="'>\s]+\/)>/g, '="$1">') .replace(raction, '="$1">')
.replace(rleadingWhitespace, "")], ownerDocument)[0]; .replace(rleadingWhitespace, "")], ownerDocument)[0];
} else { } else {
return this.cloneNode(true); return this.cloneNode(true);
@ -235,7 +230,7 @@ jQuery.fn.extend({
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
value = value.replace(rxhtmlTag, fcloseTag); value = value.replace(rxhtmlTag, "<$1></$2>");
try { try {
for ( var i = 0, l = this.length; i < l; i++ ) { for ( var i = 0, l = this.length; i < l; i++ ) {
@ -479,7 +474,7 @@ jQuery.extend({
} else if ( typeof elem === "string" ) { } else if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers // Fix "XHTML"-style tags in all browsers
elem = elem.replace(rxhtmlTag, fcloseTag); elem = elem.replace(rxhtmlTag, "<$1></$2>");
// Trim whitespace, otherwise indexOf won't work as expected // Trim whitespace, otherwise indexOf won't work as expected
var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),

View file

@ -1,5 +1,8 @@
(function( jQuery ) { (function( jQuery ) {
var rtable = /^t(?:able|d|h)$/i,
rroot = /^(?:body|html)$/i;
if ( "getBoundingClientRect" in document.documentElement ) { if ( "getBoundingClientRect" in document.documentElement ) {
jQuery.fn.offset = function( options ) { jQuery.fn.offset = function( options ) {
var elem = this[0]; var elem = this[0];
@ -72,7 +75,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
top += elem.offsetTop; top += elem.offsetTop;
left += elem.offsetLeft; left += elem.offsetLeft;
if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) { if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
top += parseFloat( computedStyle.borderTopWidth ) || 0; top += parseFloat( computedStyle.borderTopWidth ) || 0;
left += parseFloat( computedStyle.borderLeftWidth ) || 0; left += parseFloat( computedStyle.borderLeftWidth ) || 0;
} }
@ -207,7 +210,7 @@ jQuery.fn.extend({
// Get correct offsets // Get correct offsets
offset = this.offset(), offset = this.offset(),
parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
// Subtract element margins // Subtract element margins
// note: when an element has margin: auto the offsetLeft and marginLeft // note: when an element has margin: auto the offsetLeft and marginLeft
@ -229,7 +232,7 @@ jQuery.fn.extend({
offsetParent: function() { offsetParent: function() {
return this.map(function() { return this.map(function() {
var offsetParent = this.offsetParent || document.body; var offsetParent = this.offsetParent || document.body;
while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
offsetParent = offsetParent.offsetParent; offsetParent = offsetParent.offsetParent;
} }
return offsetParent; return offsetParent;