Changeset 215921 in webkit
- Timestamp:
- Apr 27, 2017 11:00:20 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r215916 r215921 1 2017-04-27 Andy VanWagoner <thetalecrafter@gmail.com> 2 3 [INTL] Implement the caseFirst option for Intl.Collator 4 https://bugs.webkit.org/show_bug.cgi?id=158188 5 6 Reviewed by Geoffrey Garen. 7 8 Updates the Intl.Collator tests to check caseFirst support. 9 The caseFirst option or unicode locale extension lets the user explicitly 10 set if lower or upper case characters should be first in order. 11 12 * js/intl-collator-expected.txt: 13 * js/script-tests/intl-collator.js: 14 (testCollator): 15 1 16 2017-04-27 Joseph Pecoraro <pecoraro@apple.com> 2 17 -
trunk/LayoutTests/js/intl-collator-expected.txt
r215349 r215921 37 37 PASS testCollator(Intl.Collator('en-u-kn-false'), [{locale: 'en-u-kn-false', numeric: false}]) is true 38 38 PASS testCollator(Intl.Collator('en-u-kn-abcd'), [{locale: 'en'}]) is true 39 PASS testCollator(Intl.Collator('en-u-kf'), [{locale: 'en'}]) is true 40 PASS testCollator(Intl.Collator('en-u-kf-upper'), [{locale: 'en-u-kf-upper', caseFirst: 'upper'}]) is true 41 PASS testCollator(Intl.Collator('en-u-kf-lower'), [{locale: 'en-u-kf-lower', caseFirst: 'lower'}]) is true 42 PASS testCollator(Intl.Collator('en-u-kf-false'), [{locale: 'en-u-kf-false', caseFirst: 'false'}]) is true 43 PASS testCollator(Intl.Collator('en-u-kf-true'), [{locale: 'en'}]) is true 39 44 PASS testCollator(Intl.Collator('en-u-aa-aaaa-kn-true-bb-bbbb-co-eor-cc-cccc-y-yyd'), [{locale: 'en-u-co-eor-kn-true', collation: 'eor', numeric: true}, {locale: 'en-u-kn-true', numeric: true}]) is true 40 45 PASS testCollator(Intl.Collator('en-u-kn-true-a-aa'), [{locale: 'en-u-kn-true', numeric: true}]) is true … … 55 60 PASS testCollator(Intl.Collator('en', {numeric: { }}), [{locale: 'en', numeric: true}]) is true 56 61 PASS Intl.Collator('en', { get numeric() { throw 42; } }) threw exception 42. 57 PASS testCollator(Intl.Collator('en', {caseFirst: 'upper'}), [{locale: 'en' }]) is true58 PASS testCollator(Intl.Collator('en', {caseFirst: 'lower'}), [{locale: 'en' }]) is true59 PASS testCollator(Intl.Collator('en', {caseFirst: 'false'}), [{locale: 'en' }]) is true60 PASS testCollator(Intl.Collator('en', {caseFirst: false}), [{locale: 'en' }]) is true62 PASS testCollator(Intl.Collator('en', {caseFirst: 'upper'}), [{locale: 'en', caseFirst: 'upper'}]) is true 63 PASS testCollator(Intl.Collator('en', {caseFirst: 'lower'}), [{locale: 'en', caseFirst: 'lower'}]) is true 64 PASS testCollator(Intl.Collator('en', {caseFirst: 'false'}), [{locale: 'en', caseFirst: 'false'}]) is true 65 PASS testCollator(Intl.Collator('en', {caseFirst: false}), [{locale: 'en', caseFirst: 'false'}]) is true 61 66 PASS Intl.Collator('en', {caseFirst: 'true'}) threw exception RangeError: caseFirst must be either "upper", "lower", or "false". 62 67 PASS Intl.Collator('en', { get caseFirst() { throw 42; } }) threw exception 42. … … 75 80 PASS testCollator(Intl.Collator('en-u-kn-true', {numeric: true}), [{locale: 'en-u-kn-true', numeric: true}]) is true 76 81 PASS testCollator(Intl.Collator('en-u-kn-false', {numeric: false}), [{locale: 'en-u-kn-false', numeric: false}]) is true 77 PASS testCollator(Intl.Collator('en-a-aa-u-kn-false-co-eor- b-bb', {usage: 'sort', numeric: true, caseFirst: 'lower', sensitivity: 'case', ignorePunctuation: true}), [{locale: 'en-u-co-eor', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, collation: 'eor', numeric: true}, {locale: 'en', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, numeric: true}]) is true82 PASS testCollator(Intl.Collator('en-a-aa-u-kn-false-co-eor-kf-upper-b-bb', {usage: 'sort', numeric: true, caseFirst: 'lower', sensitivity: 'case', ignorePunctuation: true}), [{locale: 'en-u-co-eor', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, collation: 'eor', numeric: true, caseFirst: 'lower'}, {locale: 'en', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, numeric: true, caseFirst: 'lower'}]) is true 78 83 PASS Intl.Collator.length is 0 79 84 PASS Object.getOwnPropertyDescriptor(Intl.Collator, 'prototype').writable is false … … 181 186 PASS numericCompare('๒', '๑๐') is -1 182 187 PASS numericCompare('๐๑', '๑') is 0 183 PASS Intl.Collator('en', {caseFirst: 'upper'}).compare('a', 'A') is -1188 PASS Intl.Collator('en', {caseFirst: 'upper'}).compare('a', 'A') is 1 184 189 PASS Intl.Collator('en', {caseFirst: 'lower'}).compare('a', 'A') is -1 185 190 PASS Intl.Collator('en', {caseFirst: 'false'}).compare('a', 'A') is -1 … … 245 250 PASS defaultCollator.resolvedOptions() === defaultCollator.resolvedOptions() is false 246 251 PASS Intl.Collator.prototype.resolvedOptions.call(5) threw exception TypeError: Intl.Collator.prototype.resolvedOptions called on value that's not an object initialized as a Collator. 247 PASS var options = defaultCollator.resolvedOptions(); delete options['locale']; JSON.stringify(options) is '{"usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"default","numeric":false }'252 PASS var options = defaultCollator.resolvedOptions(); delete options['locale']; JSON.stringify(options) is '{"usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"default","numeric":false,"caseFirst":"false"}' 248 253 PASS successfullyParsed is true 249 254 -
trunk/LayoutTests/js/script-tests/intl-collator.js
r215349 r215921 35 35 ignorePunctuation: false, 36 36 collation: "default", 37 numeric: false 37 numeric: false, 38 caseFirst: "false" 38 39 } 39 40 Object.assign(defaultOptions, difference); … … 67 68 shouldBeTrue("testCollator(Intl.Collator('en-u-kn-abcd'), [{locale: 'en'}])"); 68 69 70 // The "kf" key is processed correctly. 71 shouldBeTrue("testCollator(Intl.Collator('en-u-kf'), [{locale: 'en'}])"); 72 shouldBeTrue("testCollator(Intl.Collator('en-u-kf-upper'), [{locale: 'en-u-kf-upper', caseFirst: 'upper'}])"); 73 shouldBeTrue("testCollator(Intl.Collator('en-u-kf-lower'), [{locale: 'en-u-kf-lower', caseFirst: 'lower'}])"); 74 shouldBeTrue("testCollator(Intl.Collator('en-u-kf-false'), [{locale: 'en-u-kf-false', caseFirst: 'false'}])"); 75 shouldBeTrue("testCollator(Intl.Collator('en-u-kf-true'), [{locale: 'en'}])"); 76 69 77 // Ignores irrelevant extension keys. 70 78 shouldBeTrue("testCollator(Intl.Collator('en-u-aa-aaaa-kn-true-bb-bbbb-co-eor-cc-cccc-y-yyd'), [{locale: 'en-u-co-eor-kn-true', collation: 'eor', numeric: true}, {locale: 'en-u-kn-true', numeric: true}])"); … … 96 104 97 105 // The option caseFirst is processed correctly. 98 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: 'upper'}), [{locale: 'en' }])");99 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: 'lower'}), [{locale: 'en' }])");100 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: 'false'}), [{locale: 'en' }])");101 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: false}), [{locale: 'en' }])");106 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: 'upper'}), [{locale: 'en', caseFirst: 'upper'}])"); 107 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: 'lower'}), [{locale: 'en', caseFirst: 'lower'}])"); 108 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: 'false'}), [{locale: 'en', caseFirst: 'false'}])"); 109 shouldBeTrue("testCollator(Intl.Collator('en', {caseFirst: false}), [{locale: 'en', caseFirst: 'false'}])"); 102 110 shouldThrow("Intl.Collator('en', {caseFirst: 'true'})", '\'RangeError: caseFirst must be either "upper", "lower", or "false"\''); 103 111 shouldThrow("Intl.Collator('en', { get caseFirst() { throw 42; } })", "'42'"); … … 124 132 125 133 // Options and extension keys are processed correctly. 126 shouldBeTrue("testCollator(Intl.Collator('en-a-aa-u-kn-false-co-eor- b-bb', {usage: 'sort', numeric: true, caseFirst: 'lower', sensitivity: 'case', ignorePunctuation: true}), [{locale: 'en-u-co-eor', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, collation: 'eor', numeric: true}, {locale: 'en', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, numeric: true}])");134 shouldBeTrue("testCollator(Intl.Collator('en-a-aa-u-kn-false-co-eor-kf-upper-b-bb', {usage: 'sort', numeric: true, caseFirst: 'lower', sensitivity: 'case', ignorePunctuation: true}), [{locale: 'en-u-co-eor', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, collation: 'eor', numeric: true, caseFirst: 'lower'}, {locale: 'en', usage: 'sort', sensitivity: 'case', ignorePunctuation: true, numeric: true, caseFirst: 'lower'}])"); 127 135 128 136 // 10.2 Properties of the Intl.Collator Constructor … … 325 333 326 334 // Test the caseFirst option. 327 // FIXME: The result of Intl.Collator('en', {caseFirst: 'upper'}).compare('a', 'A') should be 1. 328 shouldBe("Intl.Collator('en', {caseFirst: 'upper'}).compare('a', 'A')", "-1"); 335 shouldBe("Intl.Collator('en', {caseFirst: 'upper'}).compare('a', 'A')", "1"); 329 336 shouldBe("Intl.Collator('en', {caseFirst: 'lower'}).compare('a', 'A')", "-1"); 330 337 shouldBe("Intl.Collator('en', {caseFirst: 'false'}).compare('a', 'A')", "-1"); … … 365 372 366 373 // Returns the default options. 367 shouldBe("var options = defaultCollator.resolvedOptions(); delete options['locale']; JSON.stringify(options)", '\'{"usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"default","numeric":false }\'');374 shouldBe("var options = defaultCollator.resolvedOptions(); delete options['locale']; JSON.stringify(options)", '\'{"usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"default","numeric":false,"caseFirst":"false"}\''); -
trunk/Source/JavaScriptCore/ChangeLog
r215919 r215921 1 2017-04-27 Andy VanWagoner <thetalecrafter@gmail.com> 2 3 [INTL] Implement the caseFirst option for Intl.Collator 4 https://bugs.webkit.org/show_bug.cgi?id=158188 5 6 Reviewed by Geoffrey Garen. 7 8 Implements the caseFirst option and unicode locale extension. 9 The caseFirst option explicitly determines whether upper or lower case comes first. 10 11 * runtime/IntlCollator.cpp: 12 (JSC::sortLocaleData): Added kf data. 13 (JSC::searchLocaleData): Added kf data. 14 (JSC::IntlCollator::initializeCollator): Set caseFirst option. 15 (JSC::IntlCollator::createCollator): Set new attributes on ICU collator. 16 (JSC::IntlCollator::caseFirstString): Added. 17 (JSC::IntlCollator::resolvedOptions): Added caseFirst property. 18 * runtime/IntlCollator.h: 19 1 20 2017-04-27 Mark Lam <mark.lam@apple.com> 2 21 -
trunk/Source/JavaScriptCore/runtime/IntlCollator.cpp
r211247 r215921 46 46 const ClassInfo IntlCollator::s_info = { "Object", &Base::s_info, 0, CREATE_METHOD_TABLE(IntlCollator) }; 47 47 48 // FIXME: Implement kf (caseFirst). 49 static const char* const relevantExtensionKeys[2] = { "co", "kn" }; 48 static const char* const relevantExtensionKeys[3] = { "co", "kn", "kf" }; 50 49 static const size_t indexOfExtensionKeyCo = 0; 51 50 static const size_t indexOfExtensionKeyKn = 1; 51 static const size_t indexOfExtensionKeyKf = 2; 52 52 53 53 void IntlCollator::UCollatorDeleter::operator()(UCollator* collator) const … … 134 134 keyLocaleData.uncheckedAppend(ASCIILiteral("true")); 135 135 break; 136 case indexOfExtensionKeyKf: 137 keyLocaleData.reserveInitialCapacity(3); 138 keyLocaleData.uncheckedAppend(ASCIILiteral("false")); 139 keyLocaleData.uncheckedAppend(ASCIILiteral("lower")); 140 keyLocaleData.uncheckedAppend(ASCIILiteral("upper")); 141 break; 136 142 default: 137 143 ASSERT_NOT_REACHED(); … … 154 160 keyLocaleData.uncheckedAppend(ASCIILiteral("false")); 155 161 keyLocaleData.uncheckedAppend(ASCIILiteral("true")); 162 break; 163 case indexOfExtensionKeyKf: 164 keyLocaleData.reserveInitialCapacity(3); 165 keyLocaleData.uncheckedAppend(ASCIILiteral("false")); 166 keyLocaleData.uncheckedAppend(ASCIILiteral("lower")); 167 keyLocaleData.uncheckedAppend(ASCIILiteral("upper")); 156 168 break; 157 169 default: … … 276 288 const String& collation = result.get(ASCIILiteral("co")); 277 289 m_collation = collation.isNull() ? ASCIILiteral("default") : collation; 278 m_numeric = (result.get(ASCIILiteral("kn")) == "true"); 290 m_numeric = result.get(ASCIILiteral("kn")) == "true"; 291 292 const String& caseFirst = result.get(ASCIILiteral("kf")); 293 if (caseFirst == "lower") 294 m_caseFirst = CaseFirst::Lower; 295 else if (caseFirst == "upper") 296 m_caseFirst = CaseFirst::Upper; 297 else 298 m_caseFirst = CaseFirst::False; 279 299 280 300 // 24. Let s be GetOption(options, "sensitivity", "string", «"base", "accent", "case", "variant"», undefined). … … 334 354 UColAttributeValue strength = UCOL_PRIMARY; 335 355 UColAttributeValue caseLevel = UCOL_OFF; 356 UColAttributeValue caseFirst = UCOL_OFF; 336 357 switch (m_sensitivity) { 337 358 case Sensitivity::Base: … … 346 367 strength = UCOL_TERTIARY; 347 368 break; 348 default: 349 ASSERT_NOT_REACHED(); 350 } 369 } 370 switch (m_caseFirst) { 371 case CaseFirst::False: 372 break; 373 case CaseFirst::Lower: 374 caseFirst = UCOL_LOWER_FIRST; 375 break; 376 case CaseFirst::Upper: 377 caseFirst = UCOL_UPPER_FIRST; 378 break; 379 } 380 351 381 ucol_setAttribute(collator.get(), UCOL_STRENGTH, strength, &status); 352 382 ucol_setAttribute(collator.get(), UCOL_CASE_LEVEL, caseLevel, &status); 353 383 ucol_setAttribute(collator.get(), UCOL_CASE_FIRST, caseFirst, &status); 354 384 ucol_setAttribute(collator.get(), UCOL_NUMERIC_COLLATION, m_numeric ? UCOL_ON : UCOL_OFF, &status); 355 385 … … 416 446 } 417 447 448 const char* IntlCollator::caseFirstString(CaseFirst caseFirst) 449 { 450 switch (caseFirst) { 451 case CaseFirst::False: 452 return "false"; 453 case CaseFirst::Lower: 454 return "lower"; 455 case CaseFirst::Upper: 456 return "upper"; 457 } 458 ASSERT_NOT_REACHED(); 459 return nullptr; 460 } 461 418 462 JSObject* IntlCollator::resolvedOptions(ExecState& state) 419 463 { … … 442 486 options->putDirect(vm, vm.propertyNames->collation, jsString(&state, m_collation)); 443 487 options->putDirect(vm, vm.propertyNames->numeric, jsBoolean(m_numeric)); 488 options->putDirect(vm, vm.propertyNames->caseFirst, jsNontrivialString(&state, ASCIILiteral(caseFirstString(m_caseFirst)))); 444 489 return options; 445 490 } -
trunk/Source/JavaScriptCore/runtime/IntlCollator.h
r206525 r215921 62 62 enum class Usage { Sort, Search }; 63 63 enum class Sensitivity { Base, Accent, Case, Variant }; 64 enum class CaseFirst { Upper, Lower, False }; 64 65 65 66 struct UCollatorDeleter { … … 70 71 static const char* usageString(Usage); 71 72 static const char* sensitivityString(Sensitivity); 73 static const char* caseFirstString(CaseFirst); 72 74 73 75 Usage m_usage; … … 75 77 String m_collation; 76 78 Sensitivity m_sensitivity; 79 CaseFirst m_caseFirst; 77 80 WriteBarrier<JSBoundFunction> m_boundCompare; 78 81 std::unique_ptr<UCollator, UCollatorDeleter> m_collator;
Note: See TracChangeset
for help on using the changeset viewer.