1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ECMAScript 402 API implementation. 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Intl object is a single object that has some named properties, 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * all of which are constructors. 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch(function(global, utils) { 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch"use strict"; 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch%CheckIsBootstrapping(); 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ------------------------------------------------------------------- 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Imports 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar ArrayJoin; 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar ArrayPush; 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalDate = global.Date; 2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvar GlobalIntl = global.Intl; 2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvar GlobalIntlDateTimeFormat = GlobalIntl.DateTimeFormat; 2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvar GlobalIntlNumberFormat = GlobalIntl.NumberFormat; 2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvar GlobalIntlCollator = GlobalIntl.Collator; 2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvar GlobalIntlv8BreakIterator = GlobalIntl.v8BreakIterator; 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalNumber = global.Number; 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalRegExp = global.RegExp; 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalString = global.String; 3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvar IntlFallbackSymbol = utils.ImportNow("intl_fallback_symbol"); 323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvar InstallFunctions = utils.InstallFunctions; 333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvar InstallGetter = utils.InstallGetter; 34bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvar InternalArray = utils.InternalArray; 353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvar ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); 363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvar OverrideFunction = utils.OverrideFunction; 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar patternSymbol = utils.ImportNow("intl_pattern_symbol"); 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); 393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvar SetFunctionName = utils.SetFunctionName; 40f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvar StringSubstr = GlobalString.prototype.substr; 41f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvar StringSubstring = GlobalString.prototype.substring; 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochutils.Import(function(from) { 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ArrayJoin = from.ArrayJoin; 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ArrayPush = from.ArrayPush; 46bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}); 47bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Utilities for definitions 493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochfunction InstallFunction(object, name, func) { 513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch InstallFunctions(object, DONT_ENUM, [name, func]); 523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch/** 563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch * Adds bound method to the prototype of the given object. 573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch */ 5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction AddBoundMethod(obj, methodName, implementation, length, typename, 5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch compat) { 603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch %CheckIsBootstrapping(); 613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch var internalName = %CreatePrivateSymbol(methodName); 62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Making getter an anonymous function will cause 63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // %DefineGetterPropertyUnchecked to properly set the "name" 64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // property on each JSFunction instance created here, rather 65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // than (as utils.InstallGetter would) on the SharedFunctionInfo 66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // associated with all functions returned from AddBoundMethod. 67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var getter = ANONYMOUS_FUNCTION(function() { 6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var receiver = Unwrap(this, typename, obj, methodName, compat); 6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IS_UNDEFINED(receiver[internalName])) { 703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch var boundMethod; 713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (IS_UNDEFINED(length) || length === 2) { 72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch boundMethod = 7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ANONYMOUS_FUNCTION((fst, snd) => implementation(receiver, fst, snd)); 743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else if (length === 1) { 7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch boundMethod = ANONYMOUS_FUNCTION(fst => implementation(receiver, fst)); 763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch boundMethod = ANONYMOUS_FUNCTION((...args) => { 78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // DateTimeFormat.format needs to be 0 arg method, but can still 79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // receive an optional dateValue param. If one was provided, pass it 803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // along. 813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (args.length > 0) { 8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return implementation(receiver, args[0]); 833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return implementation(receiver); 853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch }); 873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch %SetNativeFlag(boundMethod); 8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch receiver[internalName] = boundMethod; 903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return receiver[internalName]; 92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch }); 933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch %FunctionRemovePrototype(getter); 95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch %DefineGetterPropertyUnchecked(obj.prototype, methodName, getter, DONT_ENUM); 96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch %SetNativeFlag(getter); 973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction IntlConstruct(receiver, constructor, create, newTarget, args, 10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch compat) { 10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var locales = args[0]; 10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var options = args[1]; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IS_UNDEFINED(newTarget)) { 10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (compat && receiver instanceof constructor) { 10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch let success = %object_define_property(receiver, IntlFallbackSymbol, 10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { value: new constructor(locales, options) }); 10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!success) { 10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch throw %make_type_error(kReinitializeIntl, constructor); 11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return receiver; 11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return new constructor(locales, options); 11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return create(locales, options); 11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction Unwrap(receiver, typename, constructor, method, compat) { 12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!%IsInitializedIntlObjectOfType(receiver, typename)) { 12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (compat && receiver instanceof constructor) { 12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch let fallback = receiver[IntlFallbackSymbol]; 12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (%IsInitializedIntlObjectOfType(fallback, typename)) { 12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return fallback; 12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch throw %make_type_error(kIncompatibleMethodReceiver, method, receiver); 13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return receiver; 13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// ------------------------------------------------------------------- 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Caches available locales for each service. 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar AVAILABLE_LOCALES = { 142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'collator': UNDEFINED, 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'numberformat': UNDEFINED, 144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformat': UNDEFINED, 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'breakiterator': UNDEFINED 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Caches default ICU locale. 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar DEFAULT_ICU_LOCALE = UNDEFINED; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction GetDefaultICULocaleJS() { 154bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { 155bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); 15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check that this is a valid default, otherwise fall back to "und" 15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (let service in AVAILABLE_LOCALES) { 15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IS_UNDEFINED(getAvailableLocalesOf(service)[DEFAULT_ICU_LOCALE])) { 15962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DEFAULT_ICU_LOCALE = "und"; 16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 16162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 16262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 164bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return DEFAULT_ICU_LOCALE; 165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Unicode extension regular expression. 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar UNICODE_EXTENSION_RE = UNDEFINED; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetUnicodeExtensionRE() { 173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(UNDEFINED)) { 174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UNICODE_EXTENSION_RE = new GlobalRegExp('-u(-[a-z0-9]{2,8})+', 'g'); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return UNICODE_EXTENSION_RE; 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Matches any Unicode extension. 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar ANY_EXTENSION_RE = UNDEFINED; 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetAnyExtensionRE() { 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(ANY_EXTENSION_RE)) { 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ANY_EXTENSION_RE = new GlobalRegExp('-[a-z0-9]{1}-.*', 'g'); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ANY_EXTENSION_RE; 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Replace quoted text (single quote, anything but the quote and quote again). 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar QUOTED_STRING_RE = UNDEFINED; 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetQuotedStringRE() { 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(QUOTED_STRING_RE)) { 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch QUOTED_STRING_RE = new GlobalRegExp("'[^']+'", 'g'); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return QUOTED_STRING_RE; 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Matches valid service name. 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar SERVICE_RE = UNDEFINED; 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetServiceRE() { 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(SERVICE_RE)) { 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SERVICE_RE = 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch new GlobalRegExp('^(collator|numberformat|dateformat|breakiterator)$'); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return SERVICE_RE; 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Validates a language tag against bcp47 spec. 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Actual value is assigned on first run. 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar LANGUAGE_TAG_RE = UNDEFINED; 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetLanguageTagRE() { 223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(LANGUAGE_TAG_RE)) { 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildLanguageTagREs(); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LANGUAGE_TAG_RE; 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Helps find duplicate variants in the language tag. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar LANGUAGE_VARIANT_RE = UNDEFINED; 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetLanguageVariantRE() { 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(LANGUAGE_VARIANT_RE)) { 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildLanguageTagREs(); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LANGUAGE_VARIANT_RE; 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Helps find duplicate singletons in the language tag. 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar LANGUAGE_SINGLETON_RE = UNDEFINED; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetLanguageSingletonRE() { 247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(LANGUAGE_SINGLETON_RE)) { 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildLanguageTagREs(); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LANGUAGE_SINGLETON_RE; 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Matches valid IANA time zone names. 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar TIMEZONE_NAME_CHECK_RE = UNDEFINED; 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetTimezoneNameCheckRE() { 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(TIMEZONE_NAME_CHECK_RE)) { 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TIMEZONE_NAME_CHECK_RE = new GlobalRegExp( 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch '^([A-Za-z]+)/([A-Za-z_-]+)((?:\/[A-Za-z_-]+)+)*$'); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return TIMEZONE_NAME_CHECK_RE; 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Matches valid location parts of IANA time zone names. 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar TIMEZONE_NAME_LOCATION_PART_RE = UNDEFINED; 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction GetTimezoneNameLocationPartRE() { 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(TIMEZONE_NAME_LOCATION_PART_RE)) { 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TIMEZONE_NAME_LOCATION_PART_RE = 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch new GlobalRegExp('^([A-Za-z]+)((?:[_-][A-Za-z]+)+)*$'); 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return TIMEZONE_NAME_LOCATION_PART_RE; 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns an intersection of locales and service supported locales. 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Parameter locales is treated as a priority list. 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction supportedLocalesOf(service, locales, options) { 285c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (IS_NULL(%regexp_internal_match(GetServiceRE(), service))) { 286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_error(kWrongServiceType, service); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Provide defaults if matcher was not specified. 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch options = TO_OBJECT(options); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var matcher = options.localeMatcher; 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(matcher)) { 29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch matcher = TO_STRING(matcher); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (matcher !== 'lookup' && matcher !== 'best fit') { 300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kLocaleMatcher, matcher); 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch matcher = 'best fit'; 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocales = initializeLocaleList(locales); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var availableLocales = getAvailableLocalesOf(service); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use either best fit or lookup algorithm to match locales. 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (matcher === 'best fit') { 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return initializeLocaleList(bestFitSupportedLocalesOf( 31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch requestedLocales, availableLocales)); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return initializeLocaleList(lookupSupportedLocalesOf( 31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch requestedLocales, availableLocales)); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the provided BCP 47 language priority list for which 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * this service has a matching locale when using the BCP 47 Lookup algorithm. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Locales appear in the same order in the returned list as in the input list. 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction lookupSupportedLocalesOf(requestedLocales, availableLocales) { 327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var matchedLocales = new InternalArray(); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 0; i < requestedLocales.length; ++i) { 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove -u- extension. 330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var locale = %RegExpInternalReplace( 3313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch GetUnicodeExtensionRE(), requestedLocales[i], ''); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(availableLocales[locale])) { 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push requested locale not the resolved one. 335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, matchedLocales, requestedLocales[i]); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Truncate locale if possible, if not break. 339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var pos = %StringLastIndexOf(locale, '-'); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pos === -1) { 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch locale = %_Call(StringSubstring, locale, 0, pos); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (true); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return matchedLocales; 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the provided BCP 47 language priority list for which 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * this service has a matching locale when using the implementation 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * dependent algorithm. 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Locales appear in the same order in the returned list as in the input list. 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction bestFitSupportedLocalesOf(requestedLocales, availableLocales) { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(cira): implement better best fit algorithm. 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return lookupSupportedLocalesOf(requestedLocales, availableLocales); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a getOption function that extracts property value for given 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * options object. If property is missing it returns defaultValue. If value 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * is out of range for that property it throws RangeError. 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getGetOption(options, caller) { 369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IS_UNDEFINED(options)) throw %make_error(kDefaultOptionsMissing, caller); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = function getOption(property, type, values, defaultValue) { 372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(options[property])) { 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = options[property]; 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (type) { 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 'boolean': 37613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch value = TO_BOOLEAN(value); 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 'string': 37913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch value = TO_STRING(value); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 'number': 38213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch value = TO_NUMBER(value); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_error(kWrongValueType); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IS_UNDEFINED(values) && %ArrayIndexOf(values, value, 0) === -1) { 389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kValueOutOfRange, value, caller, property); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value; 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return defaultValue; 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return getOption; 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Ecma 402 9.2.5 404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * TODO(jshin): relevantExtensionKeys and localeData need to be taken into 405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * account per spec. 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Compares a BCP 47 language priority list requestedLocales against the locales 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * in availableLocales and determines the best available language to meet the 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * request. Two algorithms are available to match the locales: the Lookup 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * algorithm described in RFC 4647 section 3.4, and an implementation dependent 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * best-fit algorithm. Independent of the locale matching algorithm, options 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * specified through Unicode locale extension sequences are negotiated 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * separately, taking the caller's relevant extension keys and locale data as 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * well as client-provided options into consideration. Returns an object with 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * a locale property whose value is the language tag of the selected locale, 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * and properties for each key in relevantExtensionKeys providing the selected 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * value for that key. 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction resolveLocale(service, requestedLocales, options) { 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocales = initializeLocaleList(requestedLocales); 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, service); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var matcher = getOption('localeMatcher', 'string', 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['lookup', 'best fit'], 'best fit'); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var resolved; 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (matcher === 'lookup') { 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved = lookupMatcher(service, requestedLocales); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved = bestFitMatcher(service, requestedLocales); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return resolved; 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns best matched supported locale and extension info using basic 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * lookup algorithm. 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction lookupMatcher(service, requestedLocales) { 440c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (IS_NULL(%regexp_internal_match(GetServiceRE(), service))) { 441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_error(kWrongServiceType, service); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var availableLocales = getAvailableLocalesOf(service); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 0; i < requestedLocales.length; ++i) { 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove all extensions. 448c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var locale = %RegExpInternalReplace( 4493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch GetAnyExtensionRE(), requestedLocales[i], ''); 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IS_UNDEFINED(availableLocales[locale])) { 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the resolved locale and extension. 453c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var extensionMatch = %regexp_internal_match( 4543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch GetUnicodeExtensionRE(), requestedLocales[i]); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {'locale': locale, 'extension': extension, 'position': i}; 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Truncate locale if possible. 459f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var pos = %StringLastIndexOf(locale, '-'); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pos === -1) { 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch locale = %_Call(StringSubstring, locale, 0, pos); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (true); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Didn't find a match, return default. 468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return {'locale': GetDefaultICULocaleJS(), 'extension': '', 'position': -1}; 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns best matched supported locale and extension info using 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * implementation dependend algorithm. 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction bestFitMatcher(service, requestedLocales) { 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(cira): implement better best fit algorithm. 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return lookupMatcher(service, requestedLocales); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Parses Unicode extension into key - value map. 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns empty object if the extension string is invalid. 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * We are not concerned with the validity of the values at this point. 486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * 'attribute' in RFC 6047 is not supported. Keys without explicit 487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * values are assigned UNDEFINED. 488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * TODO(jshin): Fix the handling of 'attribute' (in RFC 6047, but none 489f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * has been defined so that it's not used) and boolean keys without 490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * an explicit value. 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction parseExtension(extension) { 493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var extensionSplit = %StringSplit(extension, '-', kMaxUint32); 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assume ['', 'u', ...] input, but don't throw. 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (extensionSplit.length <= 2 || 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {}; 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Key is {2}alphanum, value is {3,8}alphanum. 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Some keys may not have explicit values (booleans). 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = {}; 504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var key = UNDEFINED; 505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var value = UNDEFINED; 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 2; i < extensionSplit.length; ++i) { 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var length = extensionSplit[i].length; 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var element = extensionSplit[i]; 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (length === 2) { 510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IS_UNDEFINED(key)) { 511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!(key in extensionMap)) { 512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch extensionMap[key] = value; 513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch value = UNDEFINED; 515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch key = element; 517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (length >= 3 && length <= 8 && !IS_UNDEFINED(key)) { 518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IS_UNDEFINED(value)) { 519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch value = element; 520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch value = value + "-" + element; 522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There is a value that's too long, or that doesn't have a key. 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {}; 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IS_UNDEFINED(key) && !(key in extensionMap)) { 529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch extensionMap[key] = value; 530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return extensionMap; 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Populates internalOptions object with boolean key-value pairs 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * from extensionMap and options. 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns filtered extension (number and date format constructors use 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Unicode extensions for passing parameters to ICU). 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * It's used for extension-option pairs only, e.g. kn-normalization, but not 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * for 'sensitivity' since it doesn't have extension equivalent. 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Extensions like nu and ca don't have options equivalent, so we place 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * undefined in the map.property to denote that. 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) { 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = ''; 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var updateExtension = function updateExtension(key, value) { 55013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return '-' + key + '-' + TO_STRING(value); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var updateProperty = function updateProperty(property, type, value) { 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type === 'boolean' && (typeof value === 'string')) { 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = (value === 'true') ? true : false; 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(property)) { 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(outOptions, property, value); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var key in keyValues) { 5643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(keyValues, key)) { 565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var value = UNDEFINED; 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var map = keyValues[key]; 567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(map.property)) { 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This may return true if user specifies numeric: 'false', since 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Boolean('nonempty') === true. 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = getOption(map.property, map.type, map.values); 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch updateProperty(map.property, map.type, value); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension += updateExtension(key, value); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // User options didn't have it, check Unicode extension. 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Here we want to convert strings 'true', 'false' into proper Boolean 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values (not a user error). 5803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(extensionMap, key)) { 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = extensionMap[key]; 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch updateProperty(map.property, map.type, value); 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension += updateExtension(key, value); 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (map.type === 'boolean') { 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Boolean keys are allowed not to have values in Unicode extension. 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Those default to true. 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch updateProperty(map.property, map.type, true); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension += updateExtension(key, true); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return extension === ''? '' : '-u' + extension; 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch * Given an array-like, outputs an Array with the numbered 601bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch * properties copied over and defined 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * configurable: false, writable: false, enumerable: true. 603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * When |expandable| is true, the result array can be expanded. 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction freezeArray(input) { 606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var array = []; 607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var l = input.length; 608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var i = 0; i < l; i++) { 609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (i in input) { 610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(array, i, {value: input[i], 611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: false, 612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: false, 613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true}); 614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(array, 'length', {value: l, writable: false}); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return array; 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/* Make JS array[] out of InternalArray */ 622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochfunction makeArray(input) { 623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var array = []; 624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch %MoveArrayContents(input, array); 625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return array; 626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * It's sometimes desireable to leave user requested locale instead of ICU 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * one, if that was what user requested). 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * This function returns user specified tag if its maximized form matches ICU 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * resolved locale. If not we return ICU result. 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getOptimalLanguageTag(original, resolved) { 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns Array<Object>, where each object has maximized and base properties. 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Maximized: zh -> zh-Hans-CN 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Base: zh-CN-u-ca-gregory -> zh-CN 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Take care of grandfathered or simple cases. 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (original === resolved) { 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return original; 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locales = %GetLanguageTagVariants([original, resolved]); 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locales[0].maximized !== locales[1].maximized) { 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return resolved; 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve extensions of resolved locale, but swap base tags with original. 6503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); 651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return %RegExpInternalReplace(resolvedBase, resolved, locales[0].base); 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns an Object that contains all of supported locales for a given 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * service. 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * that is supported. This is required by the spec. 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getAvailableLocalesOf(service) { 66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Cache these, they don't ever change per service. 66362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 66462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AVAILABLE_LOCALES[service]; 66562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 66662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var available = %AvailableLocalesOf(service); 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i in available) { 6703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(available, i)) { 671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var parts = %regexp_internal_match( 6723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); 6733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!IS_NULL(parts)) { 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build xx-ZZ. We don't care about the actual value, 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as long it's not undefined. 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch available[parts[1] + '-' + parts[3]] = null; 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 68162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AVAILABLE_LOCALES[service] = available; 68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return available; 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Defines a property and sets writable and enumerable to true. 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Configurable is false by default. 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction defineWEProperty(object, property, value) { 692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(object, property, 693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch {value: value, writable: true, enumerable: true}); 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Adds property to an object if the value is not undefined. 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Sets configurable descriptor to false. 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction addWEPropertyIfDefined(object, property, value) { 702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(object, property, value); 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Defines a property and sets writable, enumerable and configurable to true. 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction defineWECProperty(object, property, value) { 712bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(object, property, {value: value, 713bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: true, 714bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true, 715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: true}); 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Adds property to an object if the value is not undefined. 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Sets all descriptors to true. 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction addWECPropertyIfDefined(object, property, value) { 724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(object, property, value); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns titlecased word, aMeRricA -> America. 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toTitleCaseWord(word) { 73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %StringToUpperCaseI18N(%_Call(StringSubstr, word, 0, 1)) + 73562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch %StringToLowerCaseI18N(%_Call(StringSubstr, word, 1)); 736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch/** 739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Returns titlecased location, bueNos_airES -> Buenos_Aires 740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only 741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * deals with ASCII only characters. 742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * 'of', 'au' and 'es' are special-cased and lowercased. 743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction toTitleCaseTimezoneLocation(location) { 745c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var match = %regexp_internal_match(GetTimezoneNameLocationPartRE(), location) 746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IS_NULL(match)) throw %make_range_error(kExpectedLocation, location); 747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var result = toTitleCaseWord(match[1]); 749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(match[2]) && 2 < match.length) { 750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The first character is a separator, '_' or '-'. 751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // None of IANA zone names has both '_' and '-'. 752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var separator = %_Call(StringSubstring, match[2], 0, 1); 753f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var parts = %StringSplit(match[2], separator, kMaxUint32); 754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var i = 1; i < parts.length; i++) { 755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var part = parts[i] 75662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var lowercasedPart = %StringToLowerCaseI18N(part); 757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = result + separator + 758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ((lowercasedPart !== 'es' && 759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch lowercasedPart !== 'of' && lowercasedPart !== 'au') ? 760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch toTitleCaseWord(part) : lowercasedPart); 761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return result; 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Canonicalizes the language tag, or throws in case the tag is invalid. 768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * ECMA 402 9.2.1 steps 7.c ii ~ v. 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction canonicalizeLanguageTag(localeID) { 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // null is typeof 'object' so we have to do extra check. 772bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IS_NULL(localeID)) { 774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kLanguageID); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Optimize for the most common case; a language code alone in 778bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the canonical form/lowercase (e.g. "en", "fil"). 779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IS_STRING(localeID) && 780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch !IS_NULL(%regexp_internal_match(/^[a-z]{2,3}$/, localeID))) { 781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return localeID; 782bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 783bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 78413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var localeString = TO_STRING(localeID); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (isStructuallyValidLanguageTag(localeString) === false) { 787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kInvalidLanguageTag, localeString); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ECMA 402 6.2.3 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var tag = %CanonicalizeLanguageTag(localeString); 792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jshin): This should not happen because the structual validity 793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // is already checked. If that's the case, remove this. 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (tag === 'invalid-tag') { 795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kInvalidLanguageTag, localeString); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return tag; 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 803f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Returns an InternalArray where all locales are canonicalized and duplicates 804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * removed. 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Throws on locales that are not well formed BCP47 tags. 806f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * ECMA 402 8.2.1 steps 1 (ECMA 402 9.2.1) and 2. 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochfunction canonicalizeLocaleList(locales) { 809bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var seen = new InternalArray(); 810bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (!IS_UNDEFINED(locales)) { 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We allow single string localeID. 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (typeof locales === 'string') { 813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales)); 814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return seen; 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var o = TO_OBJECT(locales); 818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var len = TO_LENGTH(o.length); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var k = 0; k < len; k++) { 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (k in o) { 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = o[k]; 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var tag = canonicalizeLanguageTag(value); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 826f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (%ArrayIndexOf(seen, tag, 0) === -1) { 827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, seen, tag); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 833f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return seen; 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 836f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochfunction initializeLocaleList(locales) { 837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return freezeArray(canonicalizeLocaleList(locales)); 838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Check the structual Validity of the language tag per ECMA 402 6.2.2: 842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * - Well-formed per RFC 5646 2.1 843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * - There are no duplicate variant subtags 844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * - There are no duplicate singletion (extension) subtags 845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * 846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * One extra-check is done (from RFC 5646 2.2.9): the tag is compared 847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * against the list of grandfathered tags. However, subtags for 848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * primary/extended language, script, region, variant are not checked 849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * against the IANA language subtag registry. 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * ICU is too permissible and lets invalid tags, like 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * hant-cmn-cn, through. 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns false if the language tag is invalid. 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 856f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochfunction isStructuallyValidLanguageTag(locale) { 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if it's well-formed, including grandfadered tags. 858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (IS_NULL(%regexp_internal_match(GetLanguageTagRE(), locale))) { 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch locale = %StringToLowerCaseI18N(locale); 86362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Just return if it's a x- form. It's all private. 865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (%StringIndexOf(locale, 'x-', 0) === 0) { 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if there are any duplicate variants or singletons (extensions). 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove private use section. 872f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch locale = %StringSplit(locale, '-x-', kMaxUint32)[0]; 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip language since it can match variant regex, so we start from 1. 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We are matching i-klingon here, but that's ok, since i-klingon-klingon 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is not valid and would fail LANGUAGE_TAG_RE test. 877bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var variants = new InternalArray(); 878bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var extensions = new InternalArray(); 879f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var parts = %StringSplit(locale, '-', kMaxUint32); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 1; i < parts.length; i++) { 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = parts[i]; 882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!IS_NULL(%regexp_internal_match(GetLanguageVariantRE(), value)) && 883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch extensions.length === 0) { 884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (%ArrayIndexOf(variants, value, 0) === -1) { 885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, variants, value); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!IS_NULL(%regexp_internal_match(GetLanguageSingletonRE(), value))) { 892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (%ArrayIndexOf(extensions, value, 0) === -1) { 893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, extensions, value); 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Builds a regular expresion that validates the language tag 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * against bcp47 spec. 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Uses http://tools.ietf.org/html/bcp47, section 2.1, ABNF. 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Runs on load and initializes the global REs. 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction BuildLanguageTagREs() { 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var alpha = '[a-zA-Z]'; 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var digit = '[0-9]'; 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var alphanum = '(' + alpha + '|' + digit + ')'; 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var regular = '(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|' + 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'zh-min|zh-min-nan|zh-xiang)'; 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var irregular = '(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|' + 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|' + 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)'; 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var grandfathered = '(' + irregular + '|' + regular + ')'; 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var privateUse = '(x(-' + alphanum + '{1,8})+)'; 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var singleton = '(' + digit + '|[A-WY-Za-wy-z])'; 923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LANGUAGE_SINGLETON_RE = new GlobalRegExp('^' + singleton + '$', 'i'); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = '(' + singleton + '(-' + alphanum + '{2,8})+)'; 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var variant = '(' + alphanum + '{5,8}|(' + digit + alphanum + '{3}))'; 928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LANGUAGE_VARIANT_RE = new GlobalRegExp('^' + variant + '$', 'i'); 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var region = '(' + alpha + '{2}|' + digit + '{3})'; 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var script = '(' + alpha + '{4})'; 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extLang = '(' + alpha + '{3}(-' + alpha + '{3}){0,2})'; 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' + 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch alpha + '{5,8})'; 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var langTag = language + '(-' + script + ')?(-' + region + ')?(-' + 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch variant + ')*(-' + extension + ')*(-' + privateUse + ')?'; 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var languageTag = 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$'; 940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LANGUAGE_TAG_RE = new GlobalRegExp(languageTag, 'i'); 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar resolvedAccessor = { 944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch get() { 945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %IncrementUseCounter(kIntlResolved); 946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this[resolvedSymbol]; 947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }, 948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set(value) { 949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch this[resolvedSymbol] = value; 950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 953f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ECMA 402 section 8.2.1 95462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) { 955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return makeArray(canonicalizeLocaleList(locales)); 956f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch); 958f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid Collator instance. 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 96362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction CreateCollator(locales, options) { 964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'collator'); 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'usage', getOption( 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'usage', 'string', ['sort', 'search'], 'sort')); 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var sensitivity = getOption('sensitivity', 'string', 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['base', 'accent', 'case', 'variant']); 977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') { 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sensitivity = 'variant'; 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'sensitivity', sensitivity); 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'ignorePunctuation', getOption( 983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ignorePunctuation', 'boolean', UNDEFINED, false)); 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('collator', locales, options); 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 987f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jshin): ICU now can take kb, kc, etc. Switch over to using ICU 988f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // directly. See Collator::InitializeCollator and 989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Collator::CreateICUCollator in src/i18n.cc 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU can't take kb, kc... parameters through localeID, so we need to pass 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // them as options. 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One exception is -co- which has to be part of the extension, but only for 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // usage: sort, and its value can't be 'standard' or 'search'. 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = parseExtension(locale.extension); 995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Map of Unicode extensions to option properties, and their values and types, 998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * for a collator. 999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var COLLATOR_KEY_MAP = { 1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'kn': {'property': 'numeric', 'type': 'boolean'}, 1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'kf': {'property': 'caseFirst', 'type': 'string', 1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'values': ['false', 'lower', 'upper']} 1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch setOptions( 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions); 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var collation = 'default'; 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = ''; 10113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(extensionMap, 'co') && internalOptions.usage === 'sort') { 1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Allowed -u-co- values. List taken from: 1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml 1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var ALLOWED_CO_VALUES = [ 1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', 1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' 1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ]; 1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (%ArrayIndexOf(ALLOWED_CO_VALUES, extensionMap.co, 0) !== -1) { 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension = '-u-co-' + extensionMap.co; 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU can't tell us what the collation is, so save user's input. 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch collation = extensionMap.co; 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (internalOptions.usage === 'search') { 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension = '-u-co-search'; 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'collation', collation); 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocale = locale.locale + extension; 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We define all properties C++ code may produce, to prevent security 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // problems. If malicious user decides to redefine Object.prototype.locale 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can't just use plain x.locale = 'us' or in C++ Set("locale", "us"). 1037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // %object_define_properties will either succeed defining or throw an error. 1038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var resolved = %object_define_properties({}, { 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch caseFirst: {writable: true}, 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch collation: {value: internalOptions.collation, writable: true}, 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ignorePunctuation: {writable: true}, 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true}, 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch numeric: {writable: true}, 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: requestedLocale, writable: true}, 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sensitivity: {writable: true}, 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch strength: {writable: true}, 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch usage: {value: internalOptions.usage, writable: true} 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var collator = %CreateCollator(requestedLocale, internalOptions, resolved); 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch %MarkAsInitializedIntlObjectOfType(collator, 'collator'); 1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch collator[resolvedSymbol] = resolved; 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return collator; 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.Collator object given optional locales and options 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 106562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction CollatorConstructor() { 106662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntlConstruct(this, GlobalIntlCollator, CreateCollator, new.target, 106762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch arguments); 106862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 106962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%SetCode(GlobalIntlCollator, CollatorConstructor); 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Collator resolvedOptions method. 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 107562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlCollator.prototype, 'resolvedOptions', function() { 107662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions', 107762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch false); 1078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = getOptimalLanguageTag(coll[resolvedSymbol].requestedLocale, 1079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch coll[resolvedSymbol].locale); 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return { 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch usage: coll[resolvedSymbol].usage, 1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch sensitivity: coll[resolvedSymbol].sensitivity, 1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ignorePunctuation: coll[resolvedSymbol].ignorePunctuation, 1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numeric: coll[resolvedSymbol].numeric, 1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch caseFirst: coll[resolvedSymbol].caseFirst, 1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch collation: coll[resolvedSymbol].collation 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 10903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlCollator, 'supportedLocalesOf', function(locales) { 1101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return supportedLocalesOf('collator', locales, arguments[1]); 11023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * When the compare method is called with two arguments x and y, it returns a 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Number other than NaN that represents the result of a locale-sensitive 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * String comparison of x with y. 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * The result is intended to order String values in the sort order specified 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * by the effective locale and collation options computed during construction 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * of this Collator object, and will be negative, zero, or positive, depending 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * on whether x comes before y in the sort order, the Strings are equal under 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * the sort order, or x comes after y in the sort order, respectively. 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction compare(collator, x, y) { 111762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %InternalCompare(collator, TO_STRING(x), TO_STRING(y)); 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false); 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Verifies that the input is a well-formed ISO 4217 currency code. 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Don't uppercase to test. It could convert invalid code into a valid one. 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * For example \u00DFP (Eszett+P) becomes SSP. 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction isWellFormedCurrencyCode(currency) { 112962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return typeof currency === "string" && currency.length === 3 && 1130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IS_NULL(%regexp_internal_match(/[^A-Za-z]/, currency)); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the valid digit count for a property, or throws RangeError on 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * a value out of the range. 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getNumberOption(options, property, min, max, fallback) { 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = options[property]; 1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 114113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch value = TO_NUMBER(value); 114213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (NUMBER_IS_NAN(value) || value < min || value > max) { 1143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kPropertyValueOutOfRange, property); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 11453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return %math_floor(value); 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fallback; 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar patternAccessor = { 1152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch get() { 1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %IncrementUseCounter(kIntlPattern); 1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this[patternSymbol]; 1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }, 1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set(value) { 1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch this[patternSymbol] = value; 1158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid NumberFormat instance. 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 116562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction CreateNumberFormat(locales, options) { 1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'numberformat'); 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('numberformat', locales, options); 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'style', getOption( 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal')); 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var currency = getOption('currency', 'string'); 1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) { 1180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kInvalidCurrencyCode, currency); 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { 1184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kCurrencyCode); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var currencyDisplay = getOption( 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (internalOptions.style === 'currency') { 119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch defineWEProperty(internalOptions, 'currency', %StringToUpperCaseI18N(currency)); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Digit ranges. 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid); 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var mnfd = options['minimumFractionDigits']; 1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var mxfd = options['maximumFractionDigits']; 1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(mnfd) || internalOptions.style !== 'currency') { 1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); 1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); 1203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(mxfd) || internalOptions.style !== 'currency') { 1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var min_mxfd = internalOptions.style === 'percent' ? 0 : 3; 1207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mnfd = IS_UNDEFINED(mnfd) ? 0 : mnfd; 1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var fallback_limit = (mnfd > min_mxfd) ? mnfd : min_mxfd; 1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, fallback_limit); 1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd); 1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var mnsd = options['minimumSignificantDigits']; 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var mxsd = options['maximumSignificantDigits']; 1215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) { 121662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 1); 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd); 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21); 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd); 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Grouping. 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'useGrouping', getOption( 1225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'useGrouping', 'boolean', UNDEFINED, true)); 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU prefers options to be passed using -u- extension key/values for 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // number format, so we need to build that. 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = parseExtension(locale.extension); 1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Map of Unicode extensions to option properties, and their values and types, 1233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * for a number format. 1234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var NUMBER_FORMAT_KEY_MAP = { 1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'nu': {'property': UNDEFINED, 'type': 'string'} 1237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP, 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch getOption, internalOptions); 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocale = locale.locale + extension; 1243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var resolved = %object_define_properties({}, { 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch currency: {writable: true}, 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch currencyDisplay: {writable: true}, 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true}, 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch maximumFractionDigits: {writable: true}, 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minimumFractionDigits: {writable: true}, 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minimumIntegerDigits: {writable: true}, 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch numberingSystem: {writable: true}, 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: requestedLocale, writable: true}, 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch style: {value: internalOptions.style, writable: true}, 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch useGrouping: {writable: true} 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 12553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(internalOptions, 'minimumSignificantDigits')) { 1256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(resolved, 'minimumSignificantDigits', UNDEFINED); 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 12583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(internalOptions, 'maximumSignificantDigits')) { 1259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(resolved, 'maximumSignificantDigits', UNDEFINED); 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 126162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var numberFormat = %CreateNumberFormat(requestedLocale, internalOptions, 126262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch resolved); 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (internalOptions.style === 'currency') { 1265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(resolved, 'currencyDisplay', 1266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch {value: currencyDisplay, writable: true}); 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 126962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch %MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat'); 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numberFormat[resolvedSymbol] = resolved; 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return numberFormat; 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.NumberFormat object given optional locales and options 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 128262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction NumberFormatConstructor() { 128362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntlConstruct(this, GlobalIntlNumberFormat, CreateNumberFormat, 128462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch new.target, arguments, true); 128562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 128662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%SetCode(GlobalIntlNumberFormat, NumberFormatConstructor); 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * NumberFormat resolvedOptions method. 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 129262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlNumberFormat.prototype, 'resolvedOptions', 129362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function() { 129462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat, 129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'resolvedOptions', true); 1296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, 1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].locale); 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var result = { 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numberingSystem: format[resolvedSymbol].numberingSystem, 1302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch style: format[resolvedSymbol].style, 1303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch useGrouping: format[resolvedSymbol].useGrouping, 1304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch minimumIntegerDigits: format[resolvedSymbol].minimumIntegerDigits, 1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch minimumFractionDigits: format[resolvedSymbol].minimumFractionDigits, 1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch maximumFractionDigits: format[resolvedSymbol].maximumFractionDigits, 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result.style === 'currency') { 1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWECProperty(result, 'currency', format[resolvedSymbol].currency); 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(result, 'currencyDisplay', 1312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].currencyDisplay); 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(format[resolvedSymbol], 'minimumSignificantDigits')) { 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(result, 'minimumSignificantDigits', 1317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].minimumSignificantDigits); 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (HAS_OWN_PROPERTY(format[resolvedSymbol], 'maximumSignificantDigits')) { 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(result, 'maximumSignificantDigits', 1322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].maximumSignificantDigits); 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 13263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 133662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlNumberFormat, 'supportedLocalesOf', 133762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function(locales) { 1338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return supportedLocalesOf('numberformat', locales, arguments[1]); 13393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a String value representing the result of calling ToNumber(value) 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * according to the effective locale and the formatting options of this 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * NumberFormat. 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction formatNumber(formatter, value) { 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Spec treats -0 and +0 as 0. 1350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var number = TO_NUMBER(value) + 0; 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %InternalNumberFormat(formatter, number); 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlNumberFormat, 'format', formatNumber, 1, 135762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'numberformat', true); 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a string that matches LDML representation of the options object. 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toLDMLString(options) { 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'dateformat'); 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var ldmlString = ''; 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var option = getOption('weekday', 'string', ['narrow', 'short', 'long']); 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString( 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option, {narrow: 'EEEEE', short: 'EEE', long: 'EEEE'}); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('era', 'string', ['narrow', 'short', 'long']); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString( 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option, {narrow: 'GGGGG', short: 'GGG', long: 'GGGG'}); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('year', 'string', ['2-digit', 'numeric']); 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'yy', 'numeric': 'y'}); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('month', 'string', 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['2-digit', 'numeric', 'narrow', 'short', 'long']); 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'MM', 'numeric': 'M', 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'narrow': 'MMMMM', 'short': 'MMM', 'long': 'MMMM'}); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('day', 'string', ['2-digit', 'numeric']); 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString( 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option, {'2-digit': 'dd', 'numeric': 'd'}); 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var hr12 = getOption('hour12', 'boolean'); 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('hour', 'string', ['2-digit', 'numeric']); 1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(hr12)) { 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'jj', 'numeric': 'j'}); 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (hr12 === true) { 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'hh', 'numeric': 'h'}); 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'HH', 'numeric': 'H'}); 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('minute', 'string', ['2-digit', 'numeric']); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'mm', 'numeric': 'm'}); 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('second', 'string', ['2-digit', 'numeric']); 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'ss', 'numeric': 's'}); 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('timeZoneName', 'string', ['short', 'long']); 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {short: 'z', long: 'zzzz'}); 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ldmlString; 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns either LDML equivalent of the current option or empty string. 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction appendToLDMLString(option, pairs) { 1414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(option)) { 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return pairs[option]; 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ''; 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns object that matches LDML representation of the date. 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction fromLDMLString(ldmlString) { 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // First remove '' quoted text, so we lose 'Uhr' strings. 1427c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ldmlString = %RegExpInternalReplace(GetQuotedStringRE(), ldmlString, ''); 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var options = {}; 1430c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var match = %regexp_internal_match(/E{3,5}/, ldmlString); 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/G{3,5}/, ldmlString); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/y{1,2}/, ldmlString); 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'year', match, {y: 'numeric', yy: '2-digit'}); 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1442c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/M{1,5}/, ldmlString); 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sometimes we get L instead of M for month - standalone name. 1447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/L{1,5}/, ldmlString); 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/d{1,2}/, ldmlString); 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'day', match, {d: 'numeric', dd: '2-digit'}); 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1455c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/h{1,2}/, ldmlString); 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (match !== null) { 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options['hour12'] = true; 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'hour', match, {h: 'numeric', hh: '2-digit'}); 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/H{1,2}/, ldmlString); 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (match !== null) { 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options['hour12'] = false; 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'hour', match, {H: 'numeric', HH: '2-digit'}); 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/m{1,2}/, ldmlString); 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'minute', match, {m: 'numeric', mm: '2-digit'}); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1473c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/s{1,2}/, ldmlString); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'second', match, {s: 'numeric', ss: '2-digit'}); 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch match = %regexp_internal_match(/z|zzzz/, ldmlString); 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction appendToDateTimeObject(options, option, match, pairs) { 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IS_NULL(match)) { 14873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!HAS_OWN_PROPERTY(options, option)) { 1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(options, option, UNDEFINED); 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var property = match[0]; 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(options, option, pairs[property]); 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns options with at least default values in it. 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toDateTimeOptions(options, required, defaults) { 1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch options = TO_OBJECT(options); 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 151062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch options = %object_create(options); 151162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var needsDefault = true; 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((required === 'date' || required === 'any') && 1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (!IS_UNDEFINED(options.weekday) || !IS_UNDEFINED(options.year) || 1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch !IS_UNDEFINED(options.month) || !IS_UNDEFINED(options.day))) { 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needsDefault = false; 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((required === 'time' || required === 'any') && 1520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (!IS_UNDEFINED(options.hour) || !IS_UNDEFINED(options.minute) || 1521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch !IS_UNDEFINED(options.second))) { 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needsDefault = false; 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needsDefault && (defaults === 'date' || defaults === 'all')) { 1526bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(options, 'year', {value: 'numeric', 1527bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: true, 1528bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true, 1529bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: true}); 1530bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(options, 'month', {value: 'numeric', 1531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: true, 1532bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true, 1533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: true}); 1534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(options, 'day', {value: 'numeric', 1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writable: true, 1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch enumerable: true, 1537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch configurable: true}); 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (needsDefault && (defaults === 'time' || defaults === 'all')) { 1541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(options, 'hour', {value: 'numeric', 1542bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: true, 1543bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true, 1544bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: true}); 1545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(options, 'minute', {value: 'numeric', 1546bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: true, 1547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true, 1548bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: true}); 1549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch %object_define_property(options, 'second', {value: 'numeric', 1550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch writable: true, 1551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch enumerable: true, 1552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch configurable: true}); 1553bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 1554bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid DateTimeFormat instance. 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 156362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction CreateDateTimeFormat(locales, options) { 1564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('dateformat', locales, options); 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = toDateTimeOptions(options, 'any', 'date'); 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'dateformat'); 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We implement only best fit algorithm, but still need to check 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if the formatMatcher values are in range. 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var matcher = getOption('formatMatcher', 'string', 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['basic', 'best fit'], 'best fit'); 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build LDML string for the skeleton that we pass to the formatter. 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var ldmlString = toLDMLString(options); 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Filter out supported extension keys so we know what to put in resolved 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // section later on. 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need to pass calendar and number system to the method. 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var tz = canonicalizeTimeZoneID(options.timeZone); 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU prefers options to be passed using -u- extension key/values, so 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we need to build that. 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = parseExtension(locale.extension); 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Map of Unicode extensions to option properties, and their values and types, 1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * for a date/time format. 1595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var DATETIME_FORMAT_KEY_MAP = { 1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ca': {'property': UNDEFINED, 'type': 'string'}, 1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'nu': {'property': UNDEFINED, 'type': 'string'} 1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP, 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch getOption, internalOptions); 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocale = locale.locale + extension; 1605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var resolved = %object_define_properties({}, { 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch calendar: {writable: true}, 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch day: {writable: true}, 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch era: {writable: true}, 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hour12: {writable: true}, 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hour: {writable: true}, 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true}, 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minute: {writable: true}, 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch month: {writable: true}, 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch numberingSystem: {writable: true}, 1615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch [patternSymbol]: {writable: true}, 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: requestedLocale, writable: true}, 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch second: {writable: true}, 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch timeZone: {writable: true}, 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch timeZoneName: {writable: true}, 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tz: {value: tz, writable: true}, 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weekday: {writable: true}, 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch year: {writable: true} 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var dateFormat = %CreateDateTimeFormat( 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved); 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (resolved.timeZone === "Etc/Unknown") { 1629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kUnsupportedTimeZone, tz); 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 163262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat'); 1633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dateFormat[resolvedSymbol] = resolved; 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return dateFormat; 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.DateTimeFormat object given optional locales and options 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 164562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction DateTimeFormatConstructor() { 164662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntlConstruct(this, GlobalIntlDateTimeFormat, CreateDateTimeFormat, 164762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch new.target, arguments, true); 164862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 164962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%SetCode(GlobalIntlDateTimeFormat, DateTimeFormatConstructor); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * DateTimeFormat resolvedOptions method. 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 165562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlDateTimeFormat.prototype, 'resolvedOptions', 165662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function() { 165762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat, 165862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'resolvedOptions', true); 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Maps ICU calendar names to LDML/BCP47 types for key 'ca'. 1662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * See typeMap section in third_party/icu/source/data/misc/keyTypeData.txt 1663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * and 1664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml 1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var ICU_CALENDAR_MAP = { 1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'gregorian': 'gregory', 1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ethiopic-amete-alem': 'ethioaa' 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var fromPattern = fromLDMLString(format[resolvedSymbol][patternSymbol]); 1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var userCalendar = ICU_CALENDAR_MAP[format[resolvedSymbol].calendar]; 1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(userCalendar)) { 1674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // No match means that ICU's legacy name is identical to LDML/BCP type. 1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch userCalendar = format[resolvedSymbol].calendar; 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, 1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].locale); 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var result = { 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numberingSystem: format[resolvedSymbol].numberingSystem, 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch calendar: userCalendar, 1685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch timeZone: format[resolvedSymbol].timeZone 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'timeZoneName', fromPattern.timeZoneName); 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'era', fromPattern.era); 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'year', fromPattern.year); 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'month', fromPattern.month); 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'day', fromPattern.day); 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'weekday', fromPattern.weekday); 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'hour12', fromPattern.hour12); 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'hour', fromPattern.hour); 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'minute', fromPattern.minute); 1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'second', fromPattern.second); 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 17003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 171062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlDateTimeFormat, 'supportedLocalesOf', 171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function(locales) { 1712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return supportedLocalesOf('dateformat', locales, arguments[1]); 17133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a String value representing the result of calling ToNumber(date) 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * according to the effective locale and the formatting options of this 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * DateTimeFormat. 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction formatDate(formatter, dateValue) { 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var dateMs; 1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(dateValue)) { 1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dateMs = %DateCurrentTime(); 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dateMs = TO_NUMBER(dateValue); 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!NUMBER_IS_FINITE(dateMs)) throw %make_range_error(kDateRange); 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %InternalDateFormat(formatter, new GlobalDate(dateMs)); 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1735f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochfunction FormatDateToParts(dateValue) { 1736f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "Intl.DateTimeFormat.prototype.formatToParts"); 1737f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (!IS_OBJECT(this)) { 1738f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch throw %make_type_error(kCalledOnNonObject, this); 1739f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 174062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) { 174162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch throw %make_type_error(kIncompatibleMethodReceiver, 174262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'Intl.DateTimeFormat.prototype.formatToParts', 174362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch this); 174462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1745f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var dateMs; 1746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IS_UNDEFINED(dateValue)) { 1747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch dateMs = %DateCurrentTime(); 1748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch dateMs = TO_NUMBER(dateValue); 1750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (!NUMBER_IS_FINITE(dateMs)) throw %make_range_error(kDateRange); 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 175462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %InternalDateFormatToParts(this, new GlobalDate(dateMs)); 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch%FunctionSetLength(FormatDateToParts, 0); 1758f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 0 because date is optional argument. 176162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlDateTimeFormat, 'format', formatDate, 0, 'dateformat', 176262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch true); 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Returns canonical Area/Location(/Location) name, or throws an exception 1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * if the zone name is invalid IANA name. 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction canonicalizeTimeZoneID(tzID) { 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip undefined zones. 1771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(tzID)) { 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return tzID; 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1775f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Convert zone name to string. 1776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tzID = TO_STRING(tzID); 1777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Special case handling (UTC, GMT). 177962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var upperID = %StringToUpperCaseI18N(tzID); 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (upperID === 'UTC' || upperID === 'GMT' || 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 'UTC'; 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) 1786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We expect only _, '-' and / beside ASCII letters. 1788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // All inputs should conform to Area/Location(/Location)* from now on. 1789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var match = %regexp_internal_match(GetTimezoneNameCheckRE(), tzID); 1790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IS_NULL(match)) throw %make_range_error(kExpectedTimezoneID, tzID); 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var result = toTitleCaseTimezoneLocation(match[1]) + '/' + 1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch toTitleCaseTimezoneLocation(match[2]); 1794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(match[3]) && 3 < match.length) { 1796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var locations = %StringSplit(match[3], '/', kMaxUint32); 1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The 1st element is empty. Starts with i=1. 1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var i = 1; i < locations.length; i++) { 1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); 1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid BreakIterator instance. 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 181062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction CreateBreakIterator(locales, options) { 1811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'breakiterator'); 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'type', getOption( 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'type', 'string', ['character', 'word', 'sentence', 'line'], 'word')); 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('breakiterator', locales, options); 1823bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var resolved = %object_define_properties({}, { 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: locale.locale, writable: true}, 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type: {value: internalOptions.type, writable: true}, 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true} 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 182962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var iterator = %CreateBreakIterator(locale.locale, internalOptions, resolved); 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 183162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch %MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator'); 1832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch iterator[resolvedSymbol] = resolved; 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return iterator; 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.v8BreakIterator object given optional locales and options 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 184462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochfunction v8BreakIteratorConstructor() { 184562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IntlConstruct(this, GlobalIntlv8BreakIterator, CreateBreakIterator, 184662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch new.target, arguments); 184762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 184862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%SetCode(GlobalIntlv8BreakIterator, v8BreakIteratorConstructor); 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * BreakIterator resolvedOptions method. 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 185462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlv8BreakIterator.prototype, 'resolvedOptions', 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function() { 1856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var segmenter = Unwrap(this, 'breakiterator', GlobalIntlv8BreakIterator, 186162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'resolvedOptions', false); 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = 1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch getOptimalLanguageTag(segmenter[resolvedSymbol].requestedLocale, 1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch segmenter[resolvedSymbol].locale); 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return { 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch type: segmenter[resolvedSymbol].type 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 18713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 188162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInstallFunction(GlobalIntlv8BreakIterator, 'supportedLocalesOf', 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function(locales) { 1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1887109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return supportedLocalesOf('breakiterator', locales, arguments[1]); 18883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Adopts text to segment using the iterator. Old text, if present, 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * gets discarded. 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction adoptText(iterator, text) { 189762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch %BreakIteratorAdoptText(iterator, TO_STRING(text)); 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns index of the first break in the string and moves current pointer. 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction first(iterator) { 190562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %BreakIteratorFirst(iterator); 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the index of the next break and moves the pointer. 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction next(iterator) { 191362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %BreakIteratorNext(iterator); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns index of the current break. 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction current(iterator) { 192162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %BreakIteratorCurrent(iterator); 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns type of the current break. 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction breakType(iterator) { 192962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %BreakIteratorBreakType(iterator); 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 193362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1, 193462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'breakiterator'); 193562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0, 'breakiterator'); 193662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0, 'breakiterator'); 193762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlv8BreakIterator, 'current', current, 0, 1938bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 'breakiterator'); 193962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAddBoundMethod(GlobalIntlv8BreakIterator, 'breakType', breakType, 0, 1940bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 'breakiterator'); 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Save references to Intl objects and methods we use, for added security. 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar savedObjects = { 194462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'collator': GlobalIntlCollator, 194562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'numberformat': GlobalIntlNumberFormat, 194662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'dateformatall': GlobalIntlDateTimeFormat, 194762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'dateformatdate': GlobalIntlDateTimeFormat, 194862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 'dateformattime': GlobalIntlDateTimeFormat 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Default (created with undefined locales and options parameters) collator, 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// number and date format instances. They'll be created as needed. 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar defaultObjects = { 1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'collator': UNDEFINED, 1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'numberformat': UNDEFINED, 1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformatall': UNDEFINED, 1958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformatdate': UNDEFINED, 1959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformattime': UNDEFINED, 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochfunction clearDefaultObjects() { 196313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch defaultObjects['dateformatall'] = UNDEFINED; 196413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch defaultObjects['dateformatdate'] = UNDEFINED; 196513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch defaultObjects['dateformattime'] = UNDEFINED; 196613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 196713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 196813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvar date_cache_version = 0; 196913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 197013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochfunction checkDateCacheCurrent() { 197113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch var new_date_cache_version = %DateCacheVersion(); 197213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (new_date_cache_version == date_cache_version) { 197313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return; 197413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 197513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch date_cache_version = new_date_cache_version; 197613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 197713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch clearDefaultObjects(); 197813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns cached or newly created instance of a given service. 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * We cache only default instances (where no locales or options are provided). 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction cachedOrNewService(service, locales, options, defaults) { 1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults; 1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) { 198713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch checkDateCacheCurrent(); 1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(defaultObjects[service])) { 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defaultObjects[service] = new savedObjects[service](locales, useOptions); 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return defaultObjects[service]; 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new savedObjects[service](locales, useOptions); 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction LocaleConvertCase(s, locales, isToUpper) { 1997bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ECMA 402 section 13.1.2 steps 1 through 12. 1998bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var language; 1999bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Optimize for the most common two cases. initializeLocaleList() can handle 2000bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // them as well, but it's rather slow accounting for over 60% of 2001bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // toLocale{U,L}Case() and about 40% of toLocale{U,L}Case("<locale>"). 2002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (IS_UNDEFINED(locales)) { 2003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch language = GetDefaultICULocaleJS(); 2004bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else if (IS_STRING(locales)) { 2005bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch language = canonicalizeLanguageTag(locales); 2006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 2007bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch var locales = initializeLocaleList(locales); 2008bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch language = locales.length > 0 ? locales[0] : GetDefaultICULocaleJS(); 2009bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // StringSplit is slower than this. 2012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch var pos = %StringIndexOf(language, '-', 0); 201362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (pos !== -1) { 2014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch language = %_Call(StringSubstring, language, 0, pos); 2015bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 201762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %StringLocaleConvertCase(s, isToUpper, language); 2018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Compares this and that, and returns less than 0, 0 or greater than 0 value. 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Overrides the built-in method. 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalString.prototype, 'localeCompare', function(that) { 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IS_NULL_OR_UNDEFINED(this)) { 2026f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kMethodInvokedOnNullOrUndefined); 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2029109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var locales = arguments[1]; 2030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var options = arguments[2]; 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var collator = cachedOrNewService('collator', locales, options); 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return compare(collator, this, that); 2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Unicode normalization. This method is called with one argument that 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * specifies the normalization form. 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If none is specified, "NFC" is assumed. 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If the form is not one of "NFC", "NFD", "NFKC", or "NFKD", then throw 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * a RangeError Exception. 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalString.prototype, 'normalize', function() { 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); 2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var s = TO_STRING(this); 2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var formArg = arguments[0]; 2050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var form = IS_UNDEFINED(formArg) ? 'NFC' : TO_STRING(formArg); 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var normalizationForm = %ArrayIndexOf(NORMALIZATION_FORMS, form, 0); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (normalizationForm === -1) { 2056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_range_error(kNormalizationForm, 2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayJoin, NORMALIZATION_FORMS, ', ')); 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return %StringNormalize(s, normalizationForm); 2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// TODO(littledan): Rewrite these two functions as C++ builtins 2065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction ToLowerCaseI18N() { 2066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase"); 206762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %StringToLowerCaseI18N(TO_STRING(this)); 2068bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2069bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2070bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction ToUpperCaseI18N() { 2071bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toUpperCase"); 207262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return %StringToUpperCaseI18N(TO_STRING(this)); 2073bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2074bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2075bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction ToLocaleLowerCaseI18N(locales) { 2076bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase"); 2077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LocaleConvertCase(TO_STRING(this), locales, false); 2078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2080bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch%FunctionSetLength(ToLocaleLowerCaseI18N, 0); 2081bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2082bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfunction ToLocaleUpperCaseI18N(locales) { 2083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase"); 2084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return LocaleConvertCase(TO_STRING(this), locales, true); 2085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch%FunctionSetLength(ToLocaleUpperCaseI18N, 0); 2088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Number object (this) using locale and options values. 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used. 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalNumber.prototype, 'toLocaleString', function() { 2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!(this instanceof GlobalNumber) && typeof(this) !== 'number') { 2096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kMethodInvokedOnWrongType, "Number"); 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2099109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var locales = arguments[0]; 2100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var options = arguments[1]; 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var numberFormat = cachedOrNewService('numberformat', locales, options); 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return formatNumber(numberFormat, this); 2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns actual formatted date or fails if date parameter is invalid. 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toLocaleDateTime(date, locales, options, required, defaults, service) { 2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!(date instanceof GlobalDate)) { 2112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch throw %make_type_error(kMethodInvokedOnWrongType, "Date"); 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch var dateValue = TO_NUMBER(date); 2116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (NUMBER_IS_NAN(dateValue)) return 'Invalid Date'; 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = toDateTimeOptions(options, required, defaults); 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var dateFormat = 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cachedOrNewService(service, locales, options, internalOptions); 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return formatDate(dateFormat, date); 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Date object (this) using locale and options values. 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used - both date and time are 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * present in the output. 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalDate.prototype, 'toLocaleString', function() { 2133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var locales = arguments[0]; 2134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var options = arguments[1]; 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return toLocaleDateTime( 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, locales, options, 'any', 'all', 'dateformatall'); 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Date object (this) using locale and options values. 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used - only date is present 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * in the output. 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalDate.prototype, 'toLocaleDateString', function() { 2147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var locales = arguments[0]; 2148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var options = arguments[1]; 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return toLocaleDateTime( 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, locales, options, 'date', 'date', 'dateformatdate'); 2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Date object (this) using locale and options values. 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used - only time is present 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * in the output. 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalDate.prototype, 'toLocaleTimeString', function() { 2161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var locales = arguments[0]; 2162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch var options = arguments[1]; 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return toLocaleDateTime( 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, locales, options, 'time', 'time', 'dateformattime'); 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2168f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch%FunctionRemovePrototype(FormatDateToParts); 216962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%FunctionRemovePrototype(ToLowerCaseI18N); 217062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%FunctionRemovePrototype(ToUpperCaseI18N); 217162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%FunctionRemovePrototype(ToLocaleLowerCaseI18N); 217262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch%FunctionRemovePrototype(ToLocaleUpperCaseI18N); 217362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 217462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochutils.SetFunctionName(FormatDateToParts, "formatToParts"); 217562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochutils.SetFunctionName(ToLowerCaseI18N, "toLowerCase"); 217662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochutils.SetFunctionName(ToUpperCaseI18N, "toUpperCase"); 217762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochutils.SetFunctionName(ToLocaleLowerCaseI18N, "toLocaleLowerCase"); 217862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochutils.SetFunctionName(ToLocaleUpperCaseI18N, "toLocaleUpperCase"); 2179f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochutils.Export(function(to) { 2181f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch to.FormatDateToParts = FormatDateToParts; 218262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch to.ToLowerCaseI18N = ToLowerCaseI18N; 218362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch to.ToUpperCaseI18N = ToUpperCaseI18N; 218462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N; 218562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N; 2186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}); 2187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}) 2189