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 ArrayIndexOf; 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar ArrayJoin; 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar ArrayPush; 23537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochvar FLAG_intl_extra; 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalDate = global.Date; 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalNumber = global.Number; 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalRegExp = global.RegExp; 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar GlobalString = global.String; 281b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar InstallFunctions = utils.InstallFunctions; 291b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar InstallGetter = utils.InstallGetter; 30537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochvar InternalArray = utils.InternalArray; 311b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar InternalRegExpMatch; 321b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar InternalRegExpReplace 331b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar IsNaN; 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar MakeError; 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar MakeRangeError; 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar MakeTypeError; 371b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); 381b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar OverrideFunction = utils.OverrideFunction; 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar patternSymbol = utils.ImportNow("intl_pattern_symbol"); 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); 411b268ca467c924004286c97bac133db489cf43d0Ben Murdochvar SetFunctionName = utils.SetFunctionName; 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar StringIndexOf; 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar StringLastIndexOf; 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar StringSplit; 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar StringSubstr; 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar StringSubstring; 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochutils.Import(function(from) { 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ArrayIndexOf = from.ArrayIndexOf; 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ArrayJoin = from.ArrayJoin; 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ArrayPush = from.ArrayPush; 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IsNaN = from.IsNaN; 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MakeError = from.MakeError; 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MakeRangeError = from.MakeRangeError; 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MakeTypeError = from.MakeTypeError; 561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch InternalRegExpMatch = from.InternalRegExpMatch; 571b268ca467c924004286c97bac133db489cf43d0Ben Murdoch InternalRegExpReplace = from.InternalRegExpReplace; 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StringIndexOf = from.StringIndexOf; 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StringLastIndexOf = from.StringLastIndexOf; 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StringSplit = from.StringSplit; 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StringSubstr = from.StringSubstr; 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StringSubstring = from.StringSubstring; 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}); 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 65537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochutils.ImportFromExperimental(function(from) { 66537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch FLAG_intl_extra = from.FLAG_intl_extra; 67537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch}); 68537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 691b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// Utilities for definitions 701b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 711b268ca467c924004286c97bac133db489cf43d0Ben Murdochfunction InstallFunction(object, name, func) { 721b268ca467c924004286c97bac133db489cf43d0Ben Murdoch InstallFunctions(object, DONT_ENUM, [name, func]); 731b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 741b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 751b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 761b268ca467c924004286c97bac133db489cf43d0Ben Murdochfunction InstallConstructor(object, name, func) { 771b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %CheckIsBootstrapping(); 781b268ca467c924004286c97bac133db489cf43d0Ben Murdoch SetFunctionName(func, name); 791b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %AddNamedProperty(object, name, func, DONT_ENUM); 801b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %SetNativeFlag(func); 811b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %ToFastProperties(object); 821b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 831b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 841b268ca467c924004286c97bac133db489cf43d0Ben Murdoch/** 851b268ca467c924004286c97bac133db489cf43d0Ben Murdoch * Adds bound method to the prototype of the given object. 861b268ca467c924004286c97bac133db489cf43d0Ben Murdoch */ 87537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction AddBoundMethod(obj, methodName, implementation, length, type) { 881b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %CheckIsBootstrapping(); 891b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var internalName = %CreatePrivateSymbol(methodName); 901b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var getter = function() { 91537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (!%IsInitializedIntlObjectOfType(this, type)) { 921b268ca467c924004286c97bac133db489cf43d0Ben Murdoch throw MakeTypeError(kMethodCalledOnWrongObject, methodName); 931b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 941b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (IS_UNDEFINED(this[internalName])) { 951b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var boundMethod; 961b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (IS_UNDEFINED(length) || length === 2) { 971b268ca467c924004286c97bac133db489cf43d0Ben Murdoch boundMethod = (x, y) => implementation(this, x, y); 981b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } else if (length === 1) { 991b268ca467c924004286c97bac133db489cf43d0Ben Murdoch boundMethod = x => implementation(this, x); 1001b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } else { 1011b268ca467c924004286c97bac133db489cf43d0Ben Murdoch boundMethod = (...args) => { 1021b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // DateTimeFormat.format needs to be 0 arg method, but can stil 1031b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // receive optional dateValue param. If one was provided, pass it 1041b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // along. 1051b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (args.length > 0) { 1061b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return implementation(this, args[0]); 1071b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } else { 1081b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return implementation(this); 1091b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1101b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1111b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1121b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // TODO(littledan): Once function name reform is shipped, remove the 1131b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // following line and wrap the boundMethod definition in an anonymous 1141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // function macro. 1151b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %FunctionSetName(boundMethod, '__bound' + methodName + '__'); 1161b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %FunctionRemovePrototype(boundMethod); 1171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch %SetNativeFlag(boundMethod); 1181b268ca467c924004286c97bac133db489cf43d0Ben Murdoch this[internalName] = boundMethod; 1191b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return this[internalName]; 1211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch }; 1221b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1231b268ca467c924004286c97bac133db489cf43d0Ben Murdoch InstallGetter(obj.prototype, methodName, getter, DONT_ENUM); 1241b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 1251b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ------------------------------------------------------------------- 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar Intl = {}; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch%AddNamedProperty(global, "Intl", Intl, DONT_ENUM); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Caches available locales for each service. 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar AVAILABLE_LOCALES = { 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'collator': UNDEFINED, 137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'numberformat': UNDEFINED, 138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformat': UNDEFINED, 139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'breakiterator': UNDEFINED 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Caches default ICU locale. 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar DEFAULT_ICU_LOCALE = UNDEFINED; 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction GetDefaultICULocaleJS() { 148537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { 149537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); 150537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 151537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return DEFAULT_ICU_LOCALE; 152537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch} 153537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Unicode extension regular expression. 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar UNICODE_EXTENSION_RE = UNDEFINED; 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetUnicodeExtensionRE() { 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(UNDEFINED)) { 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UNICODE_EXTENSION_RE = new GlobalRegExp('-u(-[a-z0-9]{2,8})+', 'g'); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return UNICODE_EXTENSION_RE; 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Matches any Unicode extension. 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar ANY_EXTENSION_RE = UNDEFINED; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetAnyExtensionRE() { 172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(ANY_EXTENSION_RE)) { 173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ANY_EXTENSION_RE = new GlobalRegExp('-[a-z0-9]{1}-.*', 'g'); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ANY_EXTENSION_RE; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Replace quoted text (single quote, anything but the quote and quote again). 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar QUOTED_STRING_RE = UNDEFINED; 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetQuotedStringRE() { 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(QUOTED_STRING_RE)) { 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch QUOTED_STRING_RE = new GlobalRegExp("'[^']+'", 'g'); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return QUOTED_STRING_RE; 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Matches valid service name. 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar SERVICE_RE = UNDEFINED; 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetServiceRE() { 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(SERVICE_RE)) { 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SERVICE_RE = 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch new GlobalRegExp('^(collator|numberformat|dateformat|breakiterator)$'); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return SERVICE_RE; 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Validates a language tag against bcp47 spec. 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Actual value is assigned on first run. 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar LANGUAGE_TAG_RE = UNDEFINED; 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetLanguageTagRE() { 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(LANGUAGE_TAG_RE)) { 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildLanguageTagREs(); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LANGUAGE_TAG_RE; 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Helps find duplicate variants in the language tag. 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar LANGUAGE_VARIANT_RE = UNDEFINED; 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetLanguageVariantRE() { 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(LANGUAGE_VARIANT_RE)) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildLanguageTagREs(); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LANGUAGE_VARIANT_RE; 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Helps find duplicate singletons in the language tag. 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar LANGUAGE_SINGLETON_RE = UNDEFINED; 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetLanguageSingletonRE() { 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(LANGUAGE_SINGLETON_RE)) { 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildLanguageTagREs(); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LANGUAGE_SINGLETON_RE; 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Matches valid IANA time zone names. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar TIMEZONE_NAME_CHECK_RE = UNDEFINED; 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction GetTimezoneNameCheckRE() { 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(TIMEZONE_NAME_CHECK_RE)) { 247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TIMEZONE_NAME_CHECK_RE = new GlobalRegExp( 248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch '^([A-Za-z]+)/([A-Za-z_-]+)((?:\/[A-Za-z_-]+)+)*$'); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return TIMEZONE_NAME_CHECK_RE; 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Matches valid location parts of IANA time zone names. 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar TIMEZONE_NAME_LOCATION_PART_RE = UNDEFINED; 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction GetTimezoneNameLocationPartRE() { 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(TIMEZONE_NAME_LOCATION_PART_RE)) { 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TIMEZONE_NAME_LOCATION_PART_RE = 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch new GlobalRegExp('^([A-Za-z]+)((?:[_-][A-Za-z]+)+)*$'); 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return TIMEZONE_NAME_LOCATION_PART_RE; 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns an intersection of locales and service supported locales. 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Parameter locales is treated as a priority list. 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction supportedLocalesOf(service, locales, options) { 2721b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeError(kWrongServiceType, service); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Provide defaults if matcher was not specified. 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch options = TO_OBJECT(options); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var matcher = options.localeMatcher; 284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(matcher)) { 28521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch matcher = TO_STRING(matcher); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (matcher !== 'lookup' && matcher !== 'best fit') { 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kLocaleMatcher, matcher); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch matcher = 'best fit'; 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocales = initializeLocaleList(locales); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Cache these, they don't ever change per service. 296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use either best fit or lookup algorithm to match locales. 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (matcher === 'best fit') { 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return initializeLocaleList(bestFitSupportedLocalesOf( 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocales, AVAILABLE_LOCALES[service])); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return initializeLocaleList(lookupSupportedLocalesOf( 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocales, AVAILABLE_LOCALES[service])); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the provided BCP 47 language priority list for which 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * this service has a matching locale when using the BCP 47 Lookup algorithm. 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Locales appear in the same order in the returned list as in the input list. 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction lookupSupportedLocalesOf(requestedLocales, availableLocales) { 317537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var matchedLocales = new InternalArray(); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 0; i < requestedLocales.length; ++i) { 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove -u- extension. 3201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var locale = InternalRegExpReplace( 3211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch GetUnicodeExtensionRE(), requestedLocales[i], ''); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(availableLocales[locale])) { 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push requested locale not the resolved one. 325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, matchedLocales, requestedLocales[i]); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Truncate locale if possible, if not break. 329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var pos = %_Call(StringLastIndexOf, locale, '-'); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pos === -1) { 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch locale = %_Call(StringSubstring, locale, 0, pos); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (true); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return matchedLocales; 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the provided BCP 47 language priority list for which 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * this service has a matching locale when using the implementation 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * dependent algorithm. 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Locales appear in the same order in the returned list as in the input list. 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction bestFitSupportedLocalesOf(requestedLocales, availableLocales) { 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(cira): implement better best fit algorithm. 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return lookupSupportedLocalesOf(requestedLocales, availableLocales); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a getOption function that extracts property value for given 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * options object. If property is missing it returns defaultValue. If value 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * is out of range for that property it throws RangeError. 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getGetOption(options, caller) { 359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) throw MakeError(kDefaultOptionsMissing, caller); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = function getOption(property, type, values, defaultValue) { 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(options[property])) { 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = options[property]; 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (type) { 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 'boolean': 36621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch value = TO_BOOLEAN(value); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 'string': 36921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch value = TO_STRING(value); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 'number': 37221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch value = TO_NUMBER(value); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeError(kWrongValueType); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(values) && %_Call(ArrayIndexOf, values, value) === -1) { 379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kValueOutOfRange, value, caller, property); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value; 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return defaultValue; 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return getOption; 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Compares a BCP 47 language priority list requestedLocales against the locales 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * in availableLocales and determines the best available language to meet the 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * request. Two algorithms are available to match the locales: the Lookup 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * algorithm described in RFC 4647 section 3.4, and an implementation dependent 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * best-fit algorithm. Independent of the locale matching algorithm, options 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * specified through Unicode locale extension sequences are negotiated 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * separately, taking the caller's relevant extension keys and locale data as 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * well as client-provided options into consideration. Returns an object with 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * a locale property whose value is the language tag of the selected locale, 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * and properties for each key in relevantExtensionKeys providing the selected 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * value for that key. 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction resolveLocale(service, requestedLocales, options) { 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocales = initializeLocaleList(requestedLocales); 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, service); 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var matcher = getOption('localeMatcher', 'string', 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['lookup', 'best fit'], 'best fit'); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var resolved; 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (matcher === 'lookup') { 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved = lookupMatcher(service, requestedLocales); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved = bestFitMatcher(service, requestedLocales); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return resolved; 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns best matched supported locale and extension info using basic 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * lookup algorithm. 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction lookupMatcher(service, requestedLocales) { 4271b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { 428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeError(kWrongServiceType, service); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Cache these, they don't ever change per service. 432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 0; i < requestedLocales.length; ++i) { 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove all extensions. 4381b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var locale = InternalRegExpReplace( 4391b268ca467c924004286c97bac133db489cf43d0Ben Murdoch GetAnyExtensionRE(), requestedLocales[i], ''); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the resolved locale and extension. 4431b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var extensionMatch = InternalRegExpMatch( 4441b268ca467c924004286c97bac133db489cf43d0Ben Murdoch GetUnicodeExtensionRE(), requestedLocales[i]); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {'locale': locale, 'extension': extension, 'position': i}; 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Truncate locale if possible. 449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var pos = %_Call(StringLastIndexOf, locale, '-'); 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pos === -1) { 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch locale = %_Call(StringSubstring, locale, 0, pos); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (true); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Didn't find a match, return default. 458537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return {'locale': GetDefaultICULocaleJS(), 'extension': '', 'position': -1}; 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns best matched supported locale and extension info using 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * implementation dependend algorithm. 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction bestFitMatcher(service, requestedLocales) { 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(cira): implement better best fit algorithm. 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return lookupMatcher(service, requestedLocales); 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Parses Unicode extension into key - value map. 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns empty object if the extension string is invalid. 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * We are not concerned with the validity of the values at this point. 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction parseExtension(extension) { 478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var extensionSplit = %_Call(StringSplit, extension, '-'); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assume ['', 'u', ...] input, but don't throw. 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (extensionSplit.length <= 2 || 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {}; 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Key is {2}alphanum, value is {3,8}alphanum. 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Some keys may not have explicit values (booleans). 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = {}; 489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var previousKey = UNDEFINED; 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 2; i < extensionSplit.length; ++i) { 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var length = extensionSplit[i].length; 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var element = extensionSplit[i]; 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (length === 2) { 494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch extensionMap[element] = UNDEFINED; 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previousKey = element; 496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (length >= 3 && length <=8 && !IS_UNDEFINED(previousKey)) { 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extensionMap[previousKey] = element; 498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch previousKey = UNDEFINED; 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There is a value that's too long, or that doesn't have a key. 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return {}; 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return extensionMap; 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Populates internalOptions object with boolean key-value pairs 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * from extensionMap and options. 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns filtered extension (number and date format constructors use 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Unicode extensions for passing parameters to ICU). 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * It's used for extension-option pairs only, e.g. kn-normalization, but not 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * for 'sensitivity' since it doesn't have extension equivalent. 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Extensions like nu and ca don't have options equivalent, so we place 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * undefined in the map.property to denote that. 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) { 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = ''; 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var updateExtension = function updateExtension(key, value) { 52321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch return '-' + key + '-' + TO_STRING(value); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var updateProperty = function updateProperty(property, type, value) { 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type === 'boolean' && (typeof value === 'string')) { 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = (value === 'true') ? true : false; 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(property)) { 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(outOptions, property, value); 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var key in keyValues) { 5371b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(keyValues, key)) { 538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var value = UNDEFINED; 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var map = keyValues[key]; 540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(map.property)) { 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This may return true if user specifies numeric: 'false', since 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Boolean('nonempty') === true. 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = getOption(map.property, map.type, map.values); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch updateProperty(map.property, map.type, value); 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension += updateExtension(key, value); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // User options didn't have it, check Unicode extension. 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Here we want to convert strings 'true', 'false' into proper Boolean 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values (not a user error). 5531b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(extensionMap, key)) { 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = extensionMap[key]; 555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch updateProperty(map.property, map.type, value); 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension += updateExtension(key, value); 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (map.type === 'boolean') { 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Boolean keys are allowed not to have values in Unicode extension. 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Those default to true. 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch updateProperty(map.property, map.type, true); 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension += updateExtension(key, true); 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return extension === ''? '' : '-u' + extension; 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 573537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch * Given an array-like, outputs an Array with the numbered 574537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch * properties copied over and defined 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * configurable: false, writable: false, enumerable: true. 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 577537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction freezeArray(input) { 578537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var array = []; 579537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var l = input.length; 580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var i = 0; i < l; i++) { 581537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (i in input) { 582537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(array, i, {value: input[i], 583537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: false, 584537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: false, 585537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true}); 586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 589537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(array, 'length', {value: l, writable: false}); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return array; 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * It's sometimes desireable to leave user requested locale instead of ICU 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * one, if that was what user requested). 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * This function returns user specified tag if its maximized form matches ICU 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * resolved locale. If not we return ICU result. 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getOptimalLanguageTag(original, resolved) { 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns Array<Object>, where each object has maximized and base properties. 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Maximized: zh -> zh-Hans-CN 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Base: zh-CN-u-ca-gregory -> zh-CN 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Take care of grandfathered or simple cases. 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (original === resolved) { 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return original; 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locales = %GetLanguageTagVariants([original, resolved]); 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locales[0].maximized !== locales[1].maximized) { 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return resolved; 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve extensions of resolved locale, but swap base tags with original. 6161b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); 6171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return InternalRegExpReplace(resolvedBase, resolved, locales[0].base); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns an Object that contains all of supported locales for a given 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * service. 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * that is supported. This is required by the spec. 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getAvailableLocalesOf(service) { 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var available = %AvailableLocalesOf(service); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i in available) { 6311b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(available, i)) { 6321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var parts = InternalRegExpMatch( 6331b268ca467c924004286c97bac133db489cf43d0Ben Murdoch /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); 6341b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (!IS_NULL(parts)) { 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build xx-ZZ. We don't care about the actual value, 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as long it's not undefined. 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch available[parts[1] + '-' + parts[3]] = null; 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return available; 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Defines a property and sets writable and enumerable to true. 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Configurable is false by default. 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction defineWEProperty(object, property, value) { 651537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(object, property, 652537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch {value: value, writable: true, enumerable: true}); 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Adds property to an object if the value is not undefined. 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Sets configurable descriptor to false. 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction addWEPropertyIfDefined(object, property, value) { 661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(object, property, value); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Defines a property and sets writable, enumerable and configurable to true. 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction defineWECProperty(object, property, value) { 671537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(object, property, {value: value, 672537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: true, 673537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true, 674537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: true}); 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Adds property to an object if the value is not undefined. 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Sets all descriptors to true. 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction addWECPropertyIfDefined(object, property, value) { 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(object, property, value); 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns titlecased word, aMeRricA -> America. 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toTitleCaseWord(word) { 693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return %StringToUpperCase(%_Call(StringSubstr, word, 0, 1)) + 694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %StringToLowerCase(%_Call(StringSubstr, word, 1)); 695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch/** 698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Returns titlecased location, bueNos_airES -> Buenos_Aires 699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only 700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * deals with ASCII only characters. 701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * 'of', 'au' and 'es' are special-cased and lowercased. 702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfunction toTitleCaseTimezoneLocation(location) { 7041b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var match = InternalRegExpMatch(GetTimezoneNameLocationPartRE(), location) 705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); 706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var result = toTitleCaseWord(match[1]); 708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(match[2]) && 2 < match.length) { 709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The first character is a separator, '_' or '-'. 710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // None of IANA zone names has both '_' and '-'. 711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var separator = %_Call(StringSubstring, match[2], 0, 1); 712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var parts = %_Call(StringSplit, match[2], separator); 713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var i = 1; i < parts.length; i++) { 714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var part = parts[i] 715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var lowercasedPart = %StringToLowerCase(part); 716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = result + separator + 717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ((lowercasedPart !== 'es' && 718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch lowercasedPart !== 'of' && lowercasedPart !== 'au') ? 719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch toTitleCaseWord(part) : lowercasedPart); 720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return result; 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Canonicalizes the language tag, or throws in case the tag is invalid. 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction canonicalizeLanguageTag(localeID) { 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // null is typeof 'object' so we have to do extra check. 730537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IS_NULL(localeID)) { 732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kLanguageID); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 735537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // Optimize for the most common case; a language code alone in 736537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // the canonical form/lowercase (e.g. "en", "fil"). 737537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (IS_STRING(localeID) && 738537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) { 739537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return localeID; 740537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 741537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 74221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch var localeString = TO_STRING(localeID); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isValidLanguageTag(localeString) === false) { 745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kInvalidLanguageTag, localeString); 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var tag = %CanonicalizeLanguageTag(localeString); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (tag === 'invalid-tag') { 750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kInvalidLanguageTag, localeString); 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return tag; 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns an array where all locales are canonicalized and duplicates removed. 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Throws on locales that are not well formed BCP47 tags. 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction initializeLocaleList(locales) { 762537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var seen = new InternalArray(); 763537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (!IS_UNDEFINED(locales)) { 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We allow single string localeID. 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (typeof locales === 'string') { 766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales)); 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return freezeArray(seen); 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var o = TO_OBJECT(locales); 771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var len = TO_UINT32(o.length); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var k = 0; k < len; k++) { 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (k in o) { 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = o[k]; 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var tag = canonicalizeLanguageTag(value); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (%_Call(ArrayIndexOf, seen, tag) === -1) { 780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, seen, tag); 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return freezeArray(seen); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Validates the language tag. Section 2.2.9 of the bcp47 spec 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * defines a valid tag. 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * ICU is too permissible and lets invalid tags, like 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * hant-cmn-cn, through. 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns false if the language tag is invalid. 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction isValidLanguageTag(locale) { 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if it's well-formed, including grandfadered tags. 8011b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) { 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Just return if it's a x- form. It's all private. 806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (%_Call(StringIndexOf, locale, 'x-') === 0) { 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if there are any duplicate variants or singletons (extensions). 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove private use section. 8131b268ca467c924004286c97bac133db489cf43d0Ben Murdoch locale = %_Call(StringSplit, locale, '-x-')[0]; 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip language since it can match variant regex, so we start from 1. 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We are matching i-klingon here, but that's ok, since i-klingon-klingon 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is not valid and would fail LANGUAGE_TAG_RE test. 818537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var variants = new InternalArray(); 819537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var extensions = new InternalArray(); 8201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var parts = %_Call(StringSplit, locale, '-'); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (var i = 1; i < parts.length; i++) { 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = parts[i]; 8231b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (!IS_NULL(InternalRegExpMatch(GetLanguageVariantRE(), value)) && 824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch extensions.length === 0) { 825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (%_Call(ArrayIndexOf, variants, value) === -1) { 826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, variants, value); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (!IS_NULL(InternalRegExpMatch(GetLanguageSingletonRE(), value))) { 833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (%_Call(ArrayIndexOf, extensions, value) === -1) { 834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayPush, extensions, value); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Builds a regular expresion that validates the language tag 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * against bcp47 spec. 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Uses http://tools.ietf.org/html/bcp47, section 2.1, ABNF. 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Runs on load and initializes the global REs. 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction BuildLanguageTagREs() { 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var alpha = '[a-zA-Z]'; 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var digit = '[0-9]'; 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var alphanum = '(' + alpha + '|' + digit + ')'; 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var regular = '(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|' + 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'zh-min|zh-min-nan|zh-xiang)'; 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var irregular = '(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|' + 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|' + 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)'; 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var grandfathered = '(' + irregular + '|' + regular + ')'; 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var privateUse = '(x(-' + alphanum + '{1,8})+)'; 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var singleton = '(' + digit + '|[A-WY-Za-wy-z])'; 864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LANGUAGE_SINGLETON_RE = new GlobalRegExp('^' + singleton + '$', 'i'); 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = '(' + singleton + '(-' + alphanum + '{2,8})+)'; 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var variant = '(' + alphanum + '{5,8}|(' + digit + alphanum + '{3}))'; 869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LANGUAGE_VARIANT_RE = new GlobalRegExp('^' + variant + '$', 'i'); 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var region = '(' + alpha + '{2}|' + digit + '{3})'; 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var script = '(' + alpha + '{4})'; 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extLang = '(' + alpha + '{3}(-' + alpha + '{3}){0,2})'; 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' + 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch alpha + '{5,8})'; 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var langTag = language + '(-' + script + ')?(-' + region + ')?(-' + 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch variant + ')*(-' + extension + ')*(-' + privateUse + ')?'; 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var languageTag = 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$'; 881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LANGUAGE_TAG_RE = new GlobalRegExp(languageTag, 'i'); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar resolvedAccessor = { 885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch get() { 886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %IncrementUseCounter(kIntlResolved); 887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this[resolvedSymbol]; 888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }, 889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set(value) { 890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch this[resolvedSymbol] = value; 891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid Collator instance. 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction initializeCollator(collator, locales, options) { 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (%IsInitializedIntlObject(collator)) { 900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kReinitializeIntl, "Collator"); 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'collator'); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'usage', getOption( 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'usage', 'string', ['sort', 'search'], 'sort')); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var sensitivity = getOption('sensitivity', 'string', 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['base', 'accent', 'case', 'variant']); 916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') { 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sensitivity = 'variant'; 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'sensitivity', sensitivity); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'ignorePunctuation', getOption( 922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ignorePunctuation', 'boolean', UNDEFINED, false)); 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('collator', locales, options); 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU can't take kb, kc... parameters through localeID, so we need to pass 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // them as options. 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One exception is -co- which has to be part of the extension, but only for 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // usage: sort, and its value can't be 'standard' or 'search'. 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = parseExtension(locale.extension); 931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Map of Unicode extensions to option properties, and their values and types, 934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * for a collator. 935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var COLLATOR_KEY_MAP = { 937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'kn': {'property': 'numeric', 'type': 'boolean'}, 938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'kf': {'property': 'caseFirst', 'type': 'string', 939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'values': ['false', 'lower', 'upper']} 940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch setOptions( 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions); 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var collation = 'default'; 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = ''; 9471b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(extensionMap, 'co') && internalOptions.usage === 'sort') { 948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Allowed -u-co- values. List taken from: 951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml 952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var ALLOWED_CO_VALUES = [ 954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', 955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' 956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ]; 957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (%_Call(ArrayIndexOf, ALLOWED_CO_VALUES, extensionMap.co) !== -1) { 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension = '-u-co-' + extensionMap.co; 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU can't tell us what the collation is, so save user's input. 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch collation = extensionMap.co; 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (internalOptions.usage === 'search') { 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extension = '-u-co-search'; 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'collation', collation); 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocale = locale.locale + extension; 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We define all properties C++ code may produce, to prevent security 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // problems. If malicious user decides to redefine Object.prototype.locale 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can't just use plain x.locale = 'us' or in C++ Set("locale", "us"). 973537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // %object_define_properties will either succeed defining or throw an error. 974537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var resolved = %object_define_properties({}, { 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch caseFirst: {writable: true}, 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch collation: {value: internalOptions.collation, writable: true}, 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ignorePunctuation: {writable: true}, 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true}, 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch numeric: {writable: true}, 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: requestedLocale, writable: true}, 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sensitivity: {writable: true}, 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch strength: {writable: true}, 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch usage: {value: internalOptions.usage, writable: true} 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalCollator = %CreateCollator(requestedLocale, 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch internalOptions, 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved); 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Writable, configurable and enumerable are set to false by default. 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch %MarkAsInitializedIntlObjectOfType(collator, 'collator', internalCollator); 992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch collator[resolvedSymbol] = resolved; 993537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (FLAG_intl_extra) { 994537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(collator, 'resolved', resolvedAccessor); 995537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return collator; 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.Collator object given optional locales and options 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 10071b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallConstructor(Intl, 'Collator', function() { 1008342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 1009342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!this || this === Intl) { 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constructor is called as a function. 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new Intl.Collator(locales, options); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return initializeCollator(TO_OBJECT(this), locales, options); 10171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Collator resolvedOptions method. 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 10241b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.Collator.prototype, 'resolvedOptions', function() { 1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!%IsInitializedIntlObjectOfType(this, 'collator')) { 1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kResolvedOptionsCalledOnNonObject, "Collator"); 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var coll = this; 1034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = getOptimalLanguageTag(coll[resolvedSymbol].requestedLocale, 1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch coll[resolvedSymbol].locale); 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return { 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch usage: coll[resolvedSymbol].usage, 1040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch sensitivity: coll[resolvedSymbol].sensitivity, 1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ignorePunctuation: coll[resolvedSymbol].ignorePunctuation, 1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numeric: coll[resolvedSymbol].numeric, 1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch caseFirst: coll[resolvedSymbol].caseFirst, 1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch collation: coll[resolvedSymbol].collation 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 10461b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 10561b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.Collator, 'supportedLocalesOf', function(locales) { 1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1061342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return supportedLocalesOf('collator', locales, arguments[1]); 10621b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * When the compare method is called with two arguments x and y, it returns a 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Number other than NaN that represents the result of a locale-sensitive 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * String comparison of x with y. 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * The result is intended to order String values in the sort order specified 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * by the effective locale and collation options computed during construction 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * of this Collator object, and will be negative, zero, or positive, depending 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * on whether x comes before y in the sort order, the Strings are equal under 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * the sort order, or x comes after y in the sort order, respectively. 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction compare(collator, x, y) { 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %InternalCompare(%GetImplFromInitializedIntlObject(collator), 107821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch TO_STRING(x), TO_STRING(y)); 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1082537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Verifies that the input is a well-formed ISO 4217 currency code. 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Don't uppercase to test. It could convert invalid code into a valid one. 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * For example \u00DFP (Eszett+P) becomes SSP. 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction isWellFormedCurrencyCode(currency) { 10901b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return typeof currency == "string" && currency.length == 3 && 10911b268ca467c924004286c97bac133db489cf43d0Ben Murdoch IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency)); 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the valid digit count for a property, or throws RangeError on 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * a value out of the range. 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction getNumberOption(options, property, min, max, fallback) { 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var value = options[property]; 1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(value)) { 110221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch value = TO_NUMBER(value); 110321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch if (NUMBER_IS_NAN(value) || value < min || value > max) { 1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kPropertyValueOutOfRange, property); 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 11061b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return %math_floor(value); 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fallback; 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar patternAccessor = { 1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch get() { 1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %IncrementUseCounter(kIntlPattern); 1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this[patternSymbol]; 1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }, 1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set(value) { 1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch this[patternSymbol] = value; 1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid NumberFormat instance. 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction initializeNumberFormat(numberFormat, locales, options) { 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (%IsInitializedIntlObject(numberFormat)) { 1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kReinitializeIntl, "NumberFormat"); 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'numberformat'); 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('numberformat', locales, options); 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'style', getOption( 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal')); 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var currency = getOption('currency', 'string'); 1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) { 1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kInvalidCurrencyCode, currency); 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { 1149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kCurrencyCode); 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var currencyDisplay = getOption( 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (internalOptions.style === 'currency') { 1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(internalOptions, 'currency', %StringToUpperCase(currency)); 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Digit ranges. 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid); 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var mnfd = options['minimumFractionDigits']; 1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var mxfd = options['maximumFractionDigits']; 1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(mnfd) || internalOptions.style !== 'currency') { 1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); 1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); 1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(mxfd) || internalOptions.style !== 'currency') { 1171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var min_mxfd = internalOptions.style === 'percent' ? 0 : 3; 1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mnfd = IS_UNDEFINED(mnfd) ? 0 : mnfd; 1173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var fallback_limit = (mnfd > min_mxfd) ? mnfd : min_mxfd; 1174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, fallback_limit); 1175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd); 1176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var mnsd = options['minimumSignificantDigits']; 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var mxsd = options['maximumSignificantDigits']; 1180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) { 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 0); 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd); 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd); 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Grouping. 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'useGrouping', getOption( 1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'useGrouping', 'boolean', UNDEFINED, true)); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU prefers options to be passed using -u- extension key/values for 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // number format, so we need to build that. 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = parseExtension(locale.extension); 1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Map of Unicode extensions to option properties, and their values and types, 1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * for a number format. 1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var NUMBER_FORMAT_KEY_MAP = { 1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'nu': {'property': UNDEFINED, 'type': 'string'} 1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP, 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch getOption, internalOptions); 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocale = locale.locale + extension; 1208537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var resolved = %object_define_properties({}, { 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch currency: {writable: true}, 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch currencyDisplay: {writable: true}, 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true}, 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch maximumFractionDigits: {writable: true}, 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minimumFractionDigits: {writable: true}, 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minimumIntegerDigits: {writable: true}, 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch numberingSystem: {writable: true}, 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: requestedLocale, writable: true}, 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch style: {value: internalOptions.style, writable: true}, 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch useGrouping: {writable: true} 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 12201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(internalOptions, 'minimumSignificantDigits')) { 1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(resolved, 'minimumSignificantDigits', UNDEFINED); 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 12231b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(internalOptions, 'maximumSignificantDigits')) { 1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(resolved, 'maximumSignificantDigits', UNDEFINED); 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var formatter = %CreateNumberFormat(requestedLocale, 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch internalOptions, 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved); 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (internalOptions.style === 'currency') { 1231537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(resolved, 'currencyDisplay', 1232537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch {value: currencyDisplay, writable: true}); 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch %MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat', formatter); 1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numberFormat[resolvedSymbol] = resolved; 1237537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (FLAG_intl_extra) { 1238537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(resolved, 'pattern', patternAccessor); 1239537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(numberFormat, 'resolved', resolvedAccessor); 1240537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return numberFormat; 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.NumberFormat object given optional locales and options 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 12521b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallConstructor(Intl, 'NumberFormat', function() { 1253342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 1254342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!this || this === Intl) { 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constructor is called as a function. 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new Intl.NumberFormat(locales, options); 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return initializeNumberFormat(TO_OBJECT(this), locales, options); 12621b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * NumberFormat resolvedOptions method. 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 12691b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.NumberFormat.prototype, 'resolvedOptions', function() { 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!%IsInitializedIntlObjectOfType(this, 'numberformat')) { 1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kResolvedOptionsCalledOnNonObject, "NumberFormat"); 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var format = this; 1279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, 1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].locale); 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var result = { 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numberingSystem: format[resolvedSymbol].numberingSystem, 1285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch style: format[resolvedSymbol].style, 1286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch useGrouping: format[resolvedSymbol].useGrouping, 1287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch minimumIntegerDigits: format[resolvedSymbol].minimumIntegerDigits, 1288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch minimumFractionDigits: format[resolvedSymbol].minimumFractionDigits, 1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch maximumFractionDigits: format[resolvedSymbol].maximumFractionDigits, 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result.style === 'currency') { 1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWECProperty(result, 'currency', format[resolvedSymbol].currency); 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(result, 'currencyDisplay', 1295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].currencyDisplay); 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12981b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(format[resolvedSymbol], 'minimumSignificantDigits')) { 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(result, 'minimumSignificantDigits', 1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].minimumSignificantDigits); 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13031b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (HAS_OWN_PROPERTY(format[resolvedSymbol], 'maximumSignificantDigits')) { 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWECProperty(result, 'maximumSignificantDigits', 1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].maximumSignificantDigits); 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 13091b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 13191b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.NumberFormat, 'supportedLocalesOf', function(locales) { 1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1324342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return supportedLocalesOf('numberformat', locales, arguments[1]); 13251b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a String value representing the result of calling ToNumber(value) 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * according to the effective locale and the formatting options of this 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * NumberFormat. 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction formatNumber(formatter, value) { 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Spec treats -0 and +0 as 0. 1336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var number = TO_NUMBER(value) + 0; 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %InternalNumberFormat(%GetImplFromInitializedIntlObject(formatter), 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch number); 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a Number that represents string value that was passed in. 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1346537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction IntlParseNumber(formatter, value) { 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %InternalNumberParse(%GetImplFromInitializedIntlObject(formatter), 134821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch TO_STRING(value)); 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1351537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1, 'numberformat'); 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a string that matches LDML representation of the options object. 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toLDMLString(options) { 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'dateformat'); 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var ldmlString = ''; 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var option = getOption('weekday', 'string', ['narrow', 'short', 'long']); 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString( 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option, {narrow: 'EEEEE', short: 'EEE', long: 'EEEE'}); 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('era', 'string', ['narrow', 'short', 'long']); 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString( 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option, {narrow: 'GGGGG', short: 'GGG', long: 'GGGG'}); 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('year', 'string', ['2-digit', 'numeric']); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'yy', 'numeric': 'y'}); 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('month', 'string', 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['2-digit', 'numeric', 'narrow', 'short', 'long']); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'MM', 'numeric': 'M', 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'narrow': 'MMMMM', 'short': 'MMM', 'long': 'MMMM'}); 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('day', 'string', ['2-digit', 'numeric']); 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString( 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option, {'2-digit': 'dd', 'numeric': 'd'}); 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var hr12 = getOption('hour12', 'boolean'); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('hour', 'string', ['2-digit', 'numeric']); 1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(hr12)) { 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'jj', 'numeric': 'j'}); 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (hr12 === true) { 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'hh', 'numeric': 'h'}); 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'HH', 'numeric': 'H'}); 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('minute', 'string', ['2-digit', 'numeric']); 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'mm', 'numeric': 'm'}); 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('second', 'string', ['2-digit', 'numeric']); 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {'2-digit': 'ss', 'numeric': 's'}); 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch option = getOption('timeZoneName', 'string', ['short', 'long']); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldmlString += appendToLDMLString(option, {short: 'z', long: 'zzzz'}); 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ldmlString; 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns either LDML equivalent of the current option or empty string. 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction appendToLDMLString(option, pairs) { 1408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(option)) { 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return pairs[option]; 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ''; 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns object that matches LDML representation of the date. 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction fromLDMLString(ldmlString) { 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // First remove '' quoted text, so we lose 'Uhr' strings. 14211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch ldmlString = InternalRegExpReplace(GetQuotedStringRE(), ldmlString, ''); 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var options = {}; 14241b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var match = InternalRegExpMatch(/E{3,5}/, ldmlString); 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14281b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/G{3,5}/, ldmlString); 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/y{1,2}/, ldmlString); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'year', match, {y: 'numeric', yy: '2-digit'}); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14361b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/M{1,5}/, ldmlString); 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sometimes we get L instead of M for month - standalone name. 14411b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/L{1,5}/, ldmlString); 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14451b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/d{1,2}/, ldmlString); 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'day', match, {d: 'numeric', dd: '2-digit'}); 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14491b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/h{1,2}/, ldmlString); 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (match !== null) { 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options['hour12'] = true; 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'hour', match, {h: 'numeric', hh: '2-digit'}); 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/H{1,2}/, ldmlString); 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (match !== null) { 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options['hour12'] = false; 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'hour', match, {H: 'numeric', HH: '2-digit'}); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14631b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/m{1,2}/, ldmlString); 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'minute', match, {m: 'numeric', mm: '2-digit'}); 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14671b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/s{1,2}/, ldmlString); 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'second', match, {s: 'numeric', ss: '2-digit'}); 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14711b268ca467c924004286c97bac133db489cf43d0Ben Murdoch match = InternalRegExpMatch(/z|zzzz/, ldmlString); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = appendToDateTimeObject( 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction appendToDateTimeObject(options, option, match, pairs) { 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IS_NULL(match)) { 14811b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (!HAS_OWN_PROPERTY(options, option)) { 1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineWEProperty(options, option, UNDEFINED); 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var property = match[0]; 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(options, option, pairs[property]); 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns options with at least default values in it. 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toDateTimeOptions(options, required, defaults) { 1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch options = TO_OBJECT(options); 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var needsDefault = true; 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((required === 'date' || required === 'any') && 1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (!IS_UNDEFINED(options.weekday) || !IS_UNDEFINED(options.year) || 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch !IS_UNDEFINED(options.month) || !IS_UNDEFINED(options.day))) { 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needsDefault = false; 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((required === 'time' || required === 'any') && 1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (!IS_UNDEFINED(options.hour) || !IS_UNDEFINED(options.minute) || 1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch !IS_UNDEFINED(options.second))) { 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needsDefault = false; 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needsDefault && (defaults === 'date' || defaults === 'all')) { 1518537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(options, 'year', {value: 'numeric', 1519537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: true, 1520537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true, 1521537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: true}); 1522537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(options, 'month', {value: 'numeric', 1523537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: true, 1524537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true, 1525537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: true}); 1526537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(options, 'day', {value: 'numeric', 1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writable: true, 1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch enumerable: true, 1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch configurable: true}); 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1532537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (needsDefault && (defaults === 'time' || defaults === 'all')) { 1533537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(options, 'hour', {value: 'numeric', 1534537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: true, 1535537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true, 1536537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: true}); 1537537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(options, 'minute', {value: 'numeric', 1538537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: true, 1539537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true, 1540537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: true}); 1541537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(options, 'second', {value: 'numeric', 1542537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch writable: true, 1543537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch enumerable: true, 1544537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch configurable: true}); 1545537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 1546537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return options; 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid DateTimeFormat instance. 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction initializeDateTimeFormat(dateFormat, locales, options) { 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (%IsInitializedIntlObject(dateFormat)) { 1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kReinitializeIntl, "DateTimeFormat"); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('dateformat', locales, options); 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = toDateTimeOptions(options, 'any', 'date'); 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'dateformat'); 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We implement only best fit algorithm, but still need to check 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if the formatMatcher values are in range. 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var matcher = getOption('formatMatcher', 'string', 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ['basic', 'best fit'], 'best fit'); 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build LDML string for the skeleton that we pass to the formatter. 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var ldmlString = toLDMLString(options); 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Filter out supported extension keys so we know what to put in resolved 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // section later on. 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need to pass calendar and number system to the method. 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var tz = canonicalizeTimeZoneID(options.timeZone); 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICU prefers options to be passed using -u- extension key/values, so 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we need to build that. 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extensionMap = parseExtension(locale.extension); 1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Map of Unicode extensions to option properties, and their values and types, 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * for a date/time format. 1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var DATETIME_FORMAT_KEY_MAP = { 1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ca': {'property': UNDEFINED, 'type': 'string'}, 1595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'nu': {'property': UNDEFINED, 'type': 'string'} 1596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP, 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch getOption, internalOptions); 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var requestedLocale = locale.locale + extension; 1602537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var resolved = %object_define_properties({}, { 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch calendar: {writable: true}, 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch day: {writable: true}, 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch era: {writable: true}, 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hour12: {writable: true}, 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hour: {writable: true}, 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true}, 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch minute: {writable: true}, 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch month: {writable: true}, 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch numberingSystem: {writable: true}, 1612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch [patternSymbol]: {writable: true}, 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: requestedLocale, writable: true}, 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch second: {writable: true}, 1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch timeZone: {writable: true}, 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch timeZoneName: {writable: true}, 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tz: {value: tz, writable: true}, 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weekday: {writable: true}, 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch year: {writable: true} 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var formatter = %CreateDateTimeFormat( 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved); 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (resolved.timeZone === "Etc/Unknown") { 1626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kUnsupportedTimeZone, tz); 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter); 1630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dateFormat[resolvedSymbol] = resolved; 1631537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (FLAG_intl_extra) { 1632537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(resolved, 'pattern', patternAccessor); 1633537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(dateFormat, 'resolved', resolvedAccessor); 1634537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return dateFormat; 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.DateTimeFormat object given optional locales and options 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 16461b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallConstructor(Intl, 'DateTimeFormat', function() { 1647342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 1648342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!this || this === Intl) { 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constructor is called as a function. 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new Intl.DateTimeFormat(locales, options); 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return initializeDateTimeFormat(TO_OBJECT(this), locales, options); 16561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * DateTimeFormat resolvedOptions method. 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 16631b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() { 1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) { 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kResolvedOptionsCalledOnNonObject, "DateTimeFormat"); 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch /** 1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Maps ICU calendar names into LDML type. 1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch */ 1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var ICU_CALENDAR_MAP = { 1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'gregorian': 'gregory', 1677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'japanese': 'japanese', 1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'buddhist': 'buddhist', 1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'roc': 'roc', 1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'persian': 'persian', 1681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'islamic-civil': 'islamicc', 1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'islamic': 'islamic', 1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'hebrew': 'hebrew', 1684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'chinese': 'chinese', 1685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'indian': 'indian', 1686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'coptic': 'coptic', 1687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ethiopic': 'ethiopic', 1688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'ethiopic-amete-alem': 'ethioaa' 1689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 1690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var format = this; 1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var fromPattern = fromLDMLString(format[resolvedSymbol][patternSymbol]); 1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var userCalendar = ICU_CALENDAR_MAP[format[resolvedSymbol].calendar]; 1694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(userCalendar)) { 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use ICU name if we don't have a match. It shouldn't happen, but 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it would be too strict to throw for this. 1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch userCalendar = format[resolvedSymbol].calendar; 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, 1701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch format[resolvedSymbol].locale); 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var result = { 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch numberingSystem: format[resolvedSymbol].numberingSystem, 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch calendar: userCalendar, 1707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch timeZone: format[resolvedSymbol].timeZone 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'timeZoneName', fromPattern.timeZoneName); 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'era', fromPattern.era); 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'year', fromPattern.year); 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'month', fromPattern.month); 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'day', fromPattern.day); 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'weekday', fromPattern.weekday); 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'hour12', fromPattern.hour12); 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'hour', fromPattern.hour); 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'minute', fromPattern.minute); 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addWECPropertyIfDefined(result, 'second', fromPattern.second); 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 17221b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 17321b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.DateTimeFormat, 'supportedLocalesOf', function(locales) { 1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1737342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return supportedLocalesOf('dateformat', locales, arguments[1]); 17381b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a String value representing the result of calling ToNumber(date) 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * according to the effective locale and the formatting options of this 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * DateTimeFormat. 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction formatDate(formatter, dateValue) { 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var dateMs; 1749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(dateValue)) { 1750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dateMs = %DateCurrentTime(); 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dateMs = TO_NUMBER(dateValue); 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 175521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch if (!NUMBER_IS_FINITE(dateMs)) throw MakeRangeError(kDateRange); 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter), 1758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch new GlobalDate(dateMs)); 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns a Date object representing the result of calling ToString(value) 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * according to the effective locale and the formatting options of this 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * DateTimeFormat. 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns undefined if date string cannot be parsed. 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1768537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction IntlParseDate(formatter, value) { 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %InternalDateParse(%GetImplFromInitializedIntlObject(formatter), 177021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch TO_STRING(value)); 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 0 because date is optional argument. 1775537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0, 'dateformat'); 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * Returns canonical Area/Location(/Location) name, or throws an exception 1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * if the zone name is invalid IANA name. 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction canonicalizeTimeZoneID(tzID) { 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip undefined zones. 1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(tzID)) { 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return tzID; 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Special case handling (UTC, GMT). 1789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var upperID = %StringToUpperCase(tzID); 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (upperID === 'UTC' || upperID === 'GMT' || 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 'UTC'; 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) 1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We expect only _, '-' and / beside ASCII letters. 1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // All inputs should conform to Area/Location(/Location)* from now on. 17991b268ca467c924004286c97bac133db489cf43d0Ben Murdoch var match = InternalRegExpMatch(GetTimezoneNameCheckRE(), tzID); 1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var result = toTitleCaseTimezoneLocation(match[1]) + '/' + 1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch toTitleCaseTimezoneLocation(match[2]); 1804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(match[3]) && 3 < match.length) { 1806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locations = %_Call(StringSplit, match[3], '/'); 1807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The 1st element is empty. Starts with i=1. 1808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (var i = 1; i < locations.length; i++) { 1809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); 1810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Initializes the given object so it's a valid BreakIterator instance. 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Useful for subclassing. 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction initializeBreakIterator(iterator, locales, options) { 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (%IsInitializedIntlObject(iterator)) { 1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kReinitializeIntl, "v8BreakIterator"); 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(options)) { 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = {}; 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var getOption = getGetOption(options, 'breakiterator'); 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = {}; 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defineWEProperty(internalOptions, 'type', getOption( 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'type', 'string', ['character', 'word', 'sentence', 'line'], 'word')); 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var locale = resolveLocale('breakiterator', locales, options); 1837537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var resolved = %object_define_properties({}, { 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch requestedLocale: {value: locale.locale, writable: true}, 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type: {value: internalOptions.type, writable: true}, 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: {writable: true} 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }); 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalIterator = %CreateBreakIterator(locale.locale, 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch internalOptions, 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolved); 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch %MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator', 1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch internalIterator); 1849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch iterator[resolvedSymbol] = resolved; 1850537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (FLAG_intl_extra) { 1851537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch %object_define_property(iterator, 'resolved', resolvedAccessor); 1852537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return iterator; 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Constructs Intl.v8BreakIterator object given optional locales and options 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * parameters. 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * @constructor 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 18641b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallConstructor(Intl, 'v8BreakIterator', function() { 1865342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 1866342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!this || this === Intl) { 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constructor is called as a function. 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new Intl.v8BreakIterator(locales, options); 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return initializeBreakIterator(TO_OBJECT(this), locales, options); 18741b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * BreakIterator resolvedOptions method. 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 18811b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.v8BreakIterator.prototype, 'resolvedOptions', 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function() { 1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!%IsInitializedIntlObjectOfType(this, 'breakiterator')) { 1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kResolvedOptionsCalledOnNonObject, "v8BreakIterator"); 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var segmenter = this; 1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var locale = 1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch getOptimalLanguageTag(segmenter[resolvedSymbol].requestedLocale, 1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch segmenter[resolvedSymbol].locale); 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return { 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch locale: locale, 1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch type: segmenter[resolvedSymbol].type 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 19001b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the subset of the given locale list for which this locale list 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * has a matching (possibly fallback) locale. Locales appear in the same 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * order in the returned list as in the input list. 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Options are optional parameter. 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 19101b268ca467c924004286c97bac133db489cf43d0Ben MurdochInstallFunction(Intl.v8BreakIterator, 'supportedLocalesOf', 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function(locales) { 1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1916342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return supportedLocalesOf('breakiterator', locales, arguments[1]); 19171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch); 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Adopts text to segment using the iterator. Old text, if present, 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * gets discarded. 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction adoptText(iterator, text) { 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch %BreakIteratorAdoptText(%GetImplFromInitializedIntlObject(iterator), 192721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch TO_STRING(text)); 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns index of the first break in the string and moves current pointer. 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction first(iterator) { 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %BreakIteratorFirst(%GetImplFromInitializedIntlObject(iterator)); 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns the index of the next break and moves the pointer. 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction next(iterator) { 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %BreakIteratorNext(%GetImplFromInitializedIntlObject(iterator)); 1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns index of the current break. 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction current(iterator) { 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %BreakIteratorCurrent(%GetImplFromInitializedIntlObject(iterator)); 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns type of the current break. 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction breakType(iterator) { 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return %BreakIteratorBreakType(%GetImplFromInitializedIntlObject(iterator)); 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1963537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.v8BreakIterator, 'adoptText', adoptText, 1, 1964537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 'breakiterator'); 1965537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.v8BreakIterator, 'first', first, 0, 'breakiterator'); 1966537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.v8BreakIterator, 'next', next, 0, 'breakiterator'); 1967537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.v8BreakIterator, 'current', current, 0, 'breakiterator'); 1968537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben MurdochAddBoundMethod(Intl.v8BreakIterator, 'breakType', breakType, 0, 1969537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 'breakiterator'); 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Save references to Intl objects and methods we use, for added security. 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar savedObjects = { 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'collator': Intl.Collator, 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'numberformat': Intl.NumberFormat, 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'dateformatall': Intl.DateTimeFormat, 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'dateformatdate': Intl.DateTimeFormat, 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 'dateformattime': Intl.DateTimeFormat 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Default (created with undefined locales and options parameters) collator, 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// number and date format instances. They'll be created as needed. 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvar defaultObjects = { 1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'collator': UNDEFINED, 1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'numberformat': UNDEFINED, 1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformatall': UNDEFINED, 1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformatdate': UNDEFINED, 1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 'dateformattime': UNDEFINED, 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 199121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdochfunction clearDefaultObjects() { 199221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch defaultObjects['dateformatall'] = UNDEFINED; 199321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch defaultObjects['dateformatdate'] = UNDEFINED; 199421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch defaultObjects['dateformattime'] = UNDEFINED; 199521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch} 199621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch 199721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdochvar date_cache_version = 0; 199821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch 199921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdochfunction checkDateCacheCurrent() { 200021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch var new_date_cache_version = %DateCacheVersion(); 200121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch if (new_date_cache_version == date_cache_version) { 200221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch return; 200321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch } 200421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch date_cache_version = new_date_cache_version; 200521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch 200621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch clearDefaultObjects(); 200721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch} 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns cached or newly created instance of a given service. 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * We cache only default instances (where no locales or options are provided). 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction cachedOrNewService(service, locales, options, defaults) { 2014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults; 2015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) { 201621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch checkDateCacheCurrent(); 2017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IS_UNDEFINED(defaultObjects[service])) { 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch defaultObjects[service] = new savedObjects[service](locales, useOptions); 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return defaultObjects[service]; 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new savedObjects[service](locales, useOptions); 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2025537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction LocaleConvertCase(s, locales, isToUpper) { 2026537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // ECMA 402 section 13.1.2 steps 1 through 12. 2027537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var language; 2028537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // Optimize for the most common two cases. initializeLocaleList() can handle 2029537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // them as well, but it's rather slow accounting for over 60% of 2030537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // toLocale{U,L}Case() and about 40% of toLocale{U,L}Case("<locale>"). 2031537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (IS_UNDEFINED(locales)) { 2032537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch language = GetDefaultICULocaleJS(); 2033537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } else if (IS_STRING(locales)) { 2034537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch language = canonicalizeLanguageTag(locales); 2035537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } else { 2036537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var locales = initializeLocaleList(locales); 2037537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch language = locales.length > 0 ? locales[0] : GetDefaultICULocaleJS(); 2038537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2039537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2040537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // StringSplit is slower than this. 2041537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var pos = %_Call(StringIndexOf, language, '-'); 2042537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (pos != -1) { 2043537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch language = %_Call(StringSubstring, language, 0, pos); 2044537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2045537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2046537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr']; 2047537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var langIndex = %_Call(ArrayIndexOf, CUSTOM_CASE_LANGUAGES, language); 2048537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (langIndex == -1) { 2049537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch // language-independent case conversion. 2050537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return isToUpper ? %StringToUpperCaseI18N(s) : %StringToLowerCaseI18N(s); 2051537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2052537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return %StringLocaleConvertCase(s, isToUpper, 2053537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch CUSTOM_CASE_LANGUAGES[langIndex]); 2054537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch} 2055537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Compares this and that, and returns less than 0, 0 or greater than 0 value. 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Overrides the built-in method. 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalString.prototype, 'localeCompare', function(that) { 2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IS_NULL_OR_UNDEFINED(this)) { 2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kMethodInvokedOnNullOrUndefined); 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2069342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[1]; 2070342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[2]; 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var collator = cachedOrNewService('collator', locales, options); 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return compare(collator, this, that); 2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Unicode normalization. This method is called with one argument that 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * specifies the normalization form. 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If none is specified, "NFC" is assumed. 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If the form is not one of "NFC", "NFD", "NFKC", or "NFKD", then throw 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * a RangeError Exception. 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalString.prototype, 'normalize', function() { 2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); 2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var s = TO_STRING(this); 2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2093342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var formArg = arguments[0]; 2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var form = IS_UNDEFINED(formArg) ? 'NFC' : TO_STRING(formArg); 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var normalizationForm = %_Call(ArrayIndexOf, NORMALIZATION_FORMS, form); 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (normalizationForm === -1) { 2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeRangeError(kNormalizationForm, 2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch %_Call(ArrayJoin, NORMALIZATION_FORMS, ', ')); 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return %StringNormalize(s, normalizationForm); 2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2108537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction ToLowerCaseI18N() { 2109537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2110537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2111537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2112537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase"); 2113537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var s = TO_STRING(this); 2114537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return %StringToLowerCaseI18N(s); 2115537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch} 2116537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2117537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction ToUpperCaseI18N() { 2118537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2119537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2120537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2121537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toUpperCase"); 2122537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch var s = TO_STRING(this); 2123537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return %StringToUpperCaseI18N(s); 2124537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch} 2125537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2126537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction ToLocaleLowerCaseI18N(locales) { 2127537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2128537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2129537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2130537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase"); 2131537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return LocaleConvertCase(TO_STRING(this), locales, false); 2132537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch} 2133537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2134537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch%FunctionSetLength(ToLocaleLowerCaseI18N, 0); 2135537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2136537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochfunction ToLocaleUpperCaseI18N(locales) { 2137537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2138537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2139537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch } 2140537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase"); 2141537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch return LocaleConvertCase(TO_STRING(this), locales, true); 2142537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch} 2143537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2144537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch%FunctionSetLength(ToLocaleUpperCaseI18N, 0); 2145537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2146537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch%FunctionRemovePrototype(ToLowerCaseI18N); 2147537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch%FunctionRemovePrototype(ToUpperCaseI18N); 2148537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch%FunctionRemovePrototype(ToLocaleLowerCaseI18N); 2149537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch%FunctionRemovePrototype(ToLocaleUpperCaseI18N); 2150537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2151537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochutils.Export(function(to) { 2152537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.ToLowerCaseI18N = ToLowerCaseI18N; 2153537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.ToUpperCaseI18N = ToUpperCaseI18N; 2154537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N; 2155537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N; 2156537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch}); 2157537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Number object (this) using locale and options values. 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used. 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalNumber.prototype, 'toLocaleString', function() { 2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!(this instanceof GlobalNumber) && typeof(this) !== 'number') { 2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kMethodInvokedOnWrongType, "Number"); 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2172342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 2173342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var numberFormat = cachedOrNewService('numberformat', locales, options); 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return formatNumber(numberFormat, this); 2176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Returns actual formatted date or fails if date parameter is invalid. 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfunction toLocaleDateTime(date, locales, options, required, defaults, service) { 2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!(date instanceof GlobalDate)) { 2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kMethodInvokedOnWrongType, "Date"); 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IsNaN(date)) return 'Invalid Date'; 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var internalOptions = toDateTimeOptions(options, required, defaults); 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var dateFormat = 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cachedOrNewService(service, locales, options, internalOptions); 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return formatDate(dateFormat, date); 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Date object (this) using locale and options values. 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used - both date and time are 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * present in the output. 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalDate.prototype, 'toLocaleString', function() { 2205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2209342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 2210342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return toLocaleDateTime( 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, locales, options, 'any', 'all', 'dateformatall'); 2213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Date object (this) using locale and options values. 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used - only date is present 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * in the output. 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalDate.prototype, 'toLocaleDateString', function() { 2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2227342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 2228342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return toLocaleDateTime( 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, locales, options, 'date', 'date', 'dateformatdate'); 2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch/** 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * Formats a Date object (this) using locale and options values. 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * If locale or options are omitted, defaults are used - only time is present 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * in the output. 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch */ 2240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOverrideFunction(GlobalDate.prototype, 'toLocaleTimeString', function() { 2241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!IS_UNDEFINED(new.target)) { 2242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2245342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var locales = arguments[0]; 2246342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch var options = arguments[1]; 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return toLocaleDateTime( 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, locales, options, 'time', 'time', 'dateformattime'); 2249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch); 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2252537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdochutils.Export(function(to) { 2253537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.AddBoundMethod = AddBoundMethod; 2254537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.IntlParseDate = IntlParseDate; 2255537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch to.IntlParseNumber = IntlParseNumber; 2256537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch}); 2257537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch 2258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}) 2259