Move lang-code checking for case-mapping to C++ from JS
Move the language code checking for 4 languages requiring special case mapping to C++ from JavaScript. This is a speculative fix for crashes reported from Windows and Mac Chrome canary builds when icu-case-mapping is enabled by default. (see crbug.com/676643) In addition, tighten up comparision operators in a couple of places in i18n.js (=== and !== instead of == and !=). BUG=v8:4477, v8:4476, chromium:676643 TEST=test262/{built-ins,intl402}/Strings/*, webkit/fast/js/*, mjsunit/string-case, intl/general/case* Review-Url: https://codereview.chromium.org/2621393002 Cr-Commit-Position: refs/heads/master@{#42246}
This commit is contained in:
parent
84d3abe390
commit
db883422c8
@ -1124,7 +1124,7 @@ AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false);
|
||||
* For example \u00DFP (Eszett+P) becomes SSP.
|
||||
*/
|
||||
function isWellFormedCurrencyCode(currency) {
|
||||
return typeof currency == "string" && currency.length == 3 &&
|
||||
return typeof currency === "string" && currency.length === 3 &&
|
||||
IS_NULL(%regexp_internal_match(/[^A-Za-z]/, currency));
|
||||
}
|
||||
|
||||
@ -2029,18 +2029,11 @@ function LocaleConvertCase(s, locales, isToUpper) {
|
||||
|
||||
// StringSplit is slower than this.
|
||||
var pos = %StringIndexOf(language, '-', 0);
|
||||
if (pos != -1) {
|
||||
if (pos !== -1) {
|
||||
language = %_Call(StringSubstring, language, 0, pos);
|
||||
}
|
||||
|
||||
var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr'];
|
||||
var langIndex = %ArrayIndexOf(CUSTOM_CASE_LANGUAGES, language, 0);
|
||||
if (langIndex == -1) {
|
||||
// language-independent case conversion.
|
||||
return isToUpper ? %StringToUpperCaseI18N(s) : %StringToLowerCaseI18N(s);
|
||||
}
|
||||
return %StringLocaleConvertCase(s, isToUpper,
|
||||
CUSTOM_CASE_LANGUAGES[langIndex]);
|
||||
return %StringLocaleConvertCase(s, isToUpper, language);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1010,21 +1010,14 @@ inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) {
|
||||
return length;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
|
||||
|
||||
int length = s->length();
|
||||
s = String::Flatten(s);
|
||||
|
||||
MUST_USE_RESULT Object* ConvertToLower(Handle<String> s, Isolate* isolate) {
|
||||
if (!s->HasOnlyOneByteChars()) {
|
||||
// Use a slower implementation for strings with characters beyond U+00FF.
|
||||
return LocaleConvertCase(s, isolate, false, "");
|
||||
}
|
||||
|
||||
int length = s->length();
|
||||
|
||||
// We depend here on the invariant that the length of a Latin1
|
||||
// string is invariant under ToLowerCase, and the result always
|
||||
// fits in the Latin1 range in the *root locale*. It does not hold
|
||||
@ -1080,14 +1073,8 @@ RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
|
||||
return *result;
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
|
||||
|
||||
MUST_USE_RESULT Object* ConvertToUpper(Handle<String> s, Isolate* isolate) {
|
||||
int32_t length = s->length();
|
||||
s = String::Flatten(s);
|
||||
|
||||
if (s->HasOnlyOneByteChars() && length > 0) {
|
||||
Handle<SeqOneByteString> result =
|
||||
isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
|
||||
@ -1147,26 +1134,65 @@ RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
|
||||
return LocaleConvertCase(s, isolate, true, "");
|
||||
}
|
||||
|
||||
MUST_USE_RESULT Object* ConvertCase(Handle<String> s, bool is_upper,
|
||||
Isolate* isolate) {
|
||||
return is_upper ? ConvertToUpper(s, isolate) : ConvertToLower(s, isolate);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
|
||||
s = String::Flatten(s);
|
||||
return ConvertToLower(s, isolate);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
|
||||
s = String::Flatten(s);
|
||||
return ConvertToUpper(s, isolate);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
|
||||
CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(SeqOneByteString, lang, 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, lang_arg, 2);
|
||||
|
||||
// All the languages requiring special handling ("az", "el", "lt", "tr")
|
||||
// have a 2-letter language code.
|
||||
DCHECK(lang->length() == 2);
|
||||
uint8_t lang_str[3];
|
||||
memcpy(lang_str, lang->GetChars(), 2);
|
||||
lang_str[2] = 0;
|
||||
DCHECK(lang_arg->length() <= 3);
|
||||
lang_arg = String::Flatten(lang_arg);
|
||||
|
||||
// All the languages requiring special-handling have two-letter codes.
|
||||
if (V8_UNLIKELY(lang_arg->length() > 2))
|
||||
return ConvertCase(s, is_upper, isolate);
|
||||
|
||||
char c1, c2;
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
String::FlatContent lang = lang_arg->GetFlatContent();
|
||||
c1 = lang.Get(0);
|
||||
c2 = lang.Get(1);
|
||||
}
|
||||
s = String::Flatten(s);
|
||||
// TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath
|
||||
// in the root locale needs to be adjusted for az, lt and tr because even case
|
||||
// mapping of ASCII range characters are different in those locales.
|
||||
// Greek (el) does not require any adjustment, though.
|
||||
return LocaleConvertCase(s, isolate, is_upper,
|
||||
reinterpret_cast<const char*>(lang_str));
|
||||
// Greek (el) does not require any adjustment.
|
||||
if (V8_UNLIKELY(c1 == 't' && c2 == 'r'))
|
||||
return LocaleConvertCase(s, isolate, is_upper, "tr");
|
||||
if (V8_UNLIKELY(c1 == 'e' && c2 == 'l'))
|
||||
return LocaleConvertCase(s, isolate, is_upper, "el");
|
||||
if (V8_UNLIKELY(c1 == 'l' && c2 == 't'))
|
||||
return LocaleConvertCase(s, isolate, is_upper, "lt");
|
||||
if (V8_UNLIKELY(c1 == 'a' && c2 == 'z'))
|
||||
return LocaleConvertCase(s, isolate, is_upper, "az");
|
||||
|
||||
return ConvertCase(s, is_upper, isolate);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
|
||||
|
Loading…
Reference in New Issue
Block a user