Skip to content

Commit 66018e1

Browse files
committed
Performance: improve .trim performance for large strings contains lots of whitespaces
The old implementation took O(N^2) time to trim the string when multiple adjacent spaces were present. For instance, consider the string "A B" (10 spaces between A and B). Then old regexp /[\s]+$/ would take 10 steps until it realizes the regexp does not match at position 1. Then it would try to match the regexp at position 2, and it would take 9 steps. Then 8 steps for position 3, ... so it would take 10*10/2 steps until it figures out the regexp does not match. The new approach is to require "non-whitespace" char before the whitespace run, so it spends just one step for each space in the string.
1 parent 0f6c3d9 commit 66018e1

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/deprecated.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ define( [
1515

1616
// Support: Android <=4.0 only
1717
// Make sure we trim BOM and NBSP
18-
var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
18+
// Require that the "whitespace run" starts from a non-whitespace
19+
// to avoid O(N^2) behavior when the engine would try matching "\s$" at each space position.
20+
// It is important that non-whitespace char is mandatory for regexp performance reasons,
21+
// however, it does not break correctness since whitespace-only string will be trimmed by ltrim above.
22+
var ltrim = /^[\s\uFEFF\xA0]+/,
23+
rtrim = /([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/,
24+
useDefaultTrim = false;
1925

2026
// Bind a function to a context, optionally partially applying any
2127
// arguments.
@@ -79,9 +85,21 @@ jQuery.isNumeric = function( obj ) {
7985
!isNaN( obj - parseFloat( obj ) );
8086
};
8187

82-
jQuery.trim = function( text ) {
83-
return text == null ?
84-
"" :
85-
( text + "" ).replace( rtrim, "" );
86-
};
88+
if ( String.prototype.trim ) {
89+
useDefaultTrim = "_" === " \uFEFF\xA0_\uFEFF\xA0 ".trim();
90+
}
91+
92+
if ( useDefaultTrim ) {
93+
jQuery.trim = function( text ) {
94+
return text == null ?
95+
"" :
96+
( text + "" ).trim();
97+
};
98+
} else {
99+
jQuery.trim = function( text ) {
100+
return text == null ?
101+
"" :
102+
( text + "" ).replace( ltrim, "" ).replace( rtrim, "$1" );
103+
};
104+
}
87105
} );

0 commit comments

Comments
 (0)