diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart index 3fb0f721ee8..dbe8dc03ee2 100644 --- a/runtime/lib/string_patch.dart +++ b/runtime/lib/string_patch.dart @@ -200,12 +200,40 @@ class _StringBase { native "StringBase_substringUnchecked"; // Checks for one-byte whitespaces only. - // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid - // whitespaces for one byte strings. static bool _isOneByteWhitespace(int codePoint) { return (codePoint == 32) || // Space. - ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc. + ((9 <= codePoint) && (codePoint <= 13)) || // CR, LF, TAB, etc. + (codePoint == 0x85) || // NEL + (codePoint == 0xA0); // NBSP + } + + // Characters with Whitespace property (Unicode 6.2). + // 0009..000D ; White_Space # Cc .. + // 0020 ; White_Space # Zs SPACE + // 0085 ; White_Space # Cc + // 00A0 ; White_Space # Zs NO-BREAK SPACE + // 1680 ; White_Space # Zs OGHAM SPACE MARK + // 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR + // 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE + // 2028 ; White_Space # Zl LINE SEPARATOR + // 2029 ; White_Space # Zp PARAGRAPH SEPARATOR + // 202F ; White_Space # Zs NARROW NO-BREAK SPACE + // 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE + // 3000 ; White_Space # Zs IDEOGRAPHIC SPACE + // + // BOM: 0xFEFF + static bool _isTwoByteWhitespace(int codePoint) { + if (codePoint < 256) return _isOneByteWhitespace(codePoint); + return (codePoint == 0x1680) || + (codePoint == 0x180E) || + ((0x2000 <= codePoint) && (codePoint <= 0x200A)) || + (codePoint == 0x2028) || + (codePoint == 0x2029) || + (codePoint == 0x202F) || + (codePoint == 0x205F) || + (codePoint == 0x3000) || + (codePoint == 0xFEFF); } String trim() { @@ -573,8 +601,7 @@ class _TwoByteString extends _StringBase implements String { } bool _isWhitespace(int codePoint) { - // For now we only check for one byte white space characters. - return _StringBase._isOneByteWhitespace(codePoint); + return _StringBase._isTwoByteWhitespace(codePoint); } } @@ -598,8 +625,7 @@ class _ExternalTwoByteString extends _StringBase implements String { } bool _isWhitespace(int codePoint) { - // For now we only check for one byte white space characters. - return _StringBase._isOneByteWhitespace(codePoint); + return _StringBase._isTwoByteWhitespace(codePoint); } } diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart index ebcfe10950f..7db20f3cdc0 100644 --- a/sdk/lib/core/string.dart +++ b/sdk/lib/core/string.dart @@ -145,13 +145,31 @@ abstract class String implements Comparable, Pattern { String substring(int startIndex, [int endIndex]); /** - * Removes leading and trailing whitespace from a string. If the string - * contains leading or trailing whitespace a new string with no leading and - * no trailing whitespace is returned. Otherwise, the string itself is - * returned. Whitespace is defined as every Unicode character in the Zs, Zl - * and Zp categories (this includes no-break space), the spacing control - * characters from 9 to 13 (tab, lf, vtab, ff and cr), and 0xfeff the BOM - * character. + * Removes leading and trailing whitespace from a string. + * + * If the string contains leading or trailing whitespace a new string with no + * leading and no trailing whitespace is returned. Otherwise, the string + * itself is returned. + * + * Whitespace is defined by the Unicode White_Space property (as defined in + * version 6.2 or later) and the BOM character, 0xFEFF. + * + * Here is the list of trimmed characters (following version 6.2): + * + * 0009..000D ; White_Space # Cc .. + * 0020 ; White_Space # Zs SPACE + * 0085 ; White_Space # Cc + * 00A0 ; White_Space # Zs NO-BREAK SPACE + * 1680 ; White_Space # Zs OGHAM SPACE MARK + * 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR + * 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE + * 2028 ; White_Space # Zl LINE SEPARATOR + * 2029 ; White_Space # Zp PARAGRAPH SEPARATOR + * 202F ; White_Space # Zs NARROW NO-BREAK SPACE + * 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE + * 3000 ; White_Space # Zs IDEOGRAPHIC SPACE + * + * FEFF ; BOM ZERO WIDTH NO_BREAK SPACE */ String trim(); diff --git a/tests/corelib/string_trim2_test.dart b/tests/corelib/string_trim2_test.dart new file mode 100644 index 00000000000..2f42c8cdf4a --- /dev/null +++ b/tests/corelib/string_trim2_test.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:expect/expect.dart"; + +const WHITESPACE = const [ + 9, + 10, + 11, + 12, + 13, + 0x20, + 0xA0, + 0x85, + 0x1680, + 0x180E, + 0x2000, + 0x2001, + 0x2002, + 0x2003, + 0x2004, + 0x2005, + 0x2006, + 0x2007, + 0x2008, + 0x2009, + 0x200A, + 0x202F, + 0x205F, + 0x3000, + 0x2028, + 0x2029, + 0xFEFF, +]; + +main() { + for (var ws in WHITESPACE) { + Expect.equals("", new String.fromCharCode(ws).trim()); + } + Expect.equals("", new String.fromCharCodes(WHITESPACE).trim()); + for (var ws in WHITESPACE) { + var c = new String.fromCharCode(ws); + Expect.equals("a", ("a" + c).trim()); + Expect.equals("a", (c + "a").trim()); + Expect.equals("a", (c + c + "a" + c + c).trim()); + } +}