RelativeTimeFormat.js (7631B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * RelativeTimeFormat internal properties. 7 * 8 * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.3.3. 9 */ 10 var relativeTimeFormatInternalProperties = { 11 localeData: relativeTimeFormatLocaleData, 12 relevantExtensionKeys: ["nu"], 13 }; 14 15 function relativeTimeFormatLocaleData() { 16 return { 17 nu: getNumberingSystems, 18 default: { 19 nu: intl_numberingSystem, 20 }, 21 }; 22 } 23 24 /** 25 * Compute an internal properties object from |lazyRelativeTimeFormatData|. 26 */ 27 function resolveRelativeTimeFormatInternals(lazyRelativeTimeFormatData) { 28 assert(IsObject(lazyRelativeTimeFormatData), "lazy data not an object?"); 29 30 var internalProps = std_Object_create(null); 31 32 var RelativeTimeFormat = relativeTimeFormatInternalProperties; 33 34 // Steps 10-11. 35 var r = ResolveLocale( 36 "RelativeTimeFormat", 37 lazyRelativeTimeFormatData.requestedLocales, 38 lazyRelativeTimeFormatData.opt, 39 RelativeTimeFormat.relevantExtensionKeys, 40 RelativeTimeFormat.localeData 41 ); 42 43 // Steps 12-13. 44 internalProps.locale = r.locale; 45 46 // Step 14. 47 internalProps.numberingSystem = r.nu; 48 49 // Step 15 (Not relevant in our implementation). 50 51 // Step 17. 52 internalProps.style = lazyRelativeTimeFormatData.style; 53 54 // Step 19. 55 internalProps.numeric = lazyRelativeTimeFormatData.numeric; 56 57 // Steps 20-24 (Not relevant in our implementation). 58 59 return internalProps; 60 } 61 62 /** 63 * Returns an object containing the RelativeTimeFormat internal properties of |obj|. 64 */ 65 function getRelativeTimeFormatInternals(obj) { 66 assert( 67 IsObject(obj), 68 "getRelativeTimeFormatInternals called with non-object" 69 ); 70 assert( 71 intl_GuardToRelativeTimeFormat(obj) !== null, 72 "getRelativeTimeFormatInternals called with non-RelativeTimeFormat" 73 ); 74 75 var internals = getIntlObjectInternals(obj); 76 assert( 77 internals.type === "RelativeTimeFormat", 78 "bad type escaped getIntlObjectInternals" 79 ); 80 81 var internalProps = maybeInternalProperties(internals); 82 if (internalProps) { 83 return internalProps; 84 } 85 86 internalProps = resolveRelativeTimeFormatInternals(internals.lazyData); 87 setInternalProperties(internals, internalProps); 88 return internalProps; 89 } 90 91 /** 92 * Initializes an object as a RelativeTimeFormat. 93 * 94 * This method is complicated a moderate bit by its implementing initialization 95 * as a *lazy* concept. Everything that must happen now, does -- but we defer 96 * all the work we can until the object is actually used as a RelativeTimeFormat. 97 * This later work occurs in |resolveRelativeTimeFormatInternals|; steps not noted 98 * here occur there. 99 * 100 * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.1.1. 101 */ 102 function InitializeRelativeTimeFormat(relativeTimeFormat, locales, options) { 103 assert( 104 IsObject(relativeTimeFormat), 105 "InitializeRelativeimeFormat called with non-object" 106 ); 107 assert( 108 intl_GuardToRelativeTimeFormat(relativeTimeFormat) !== null, 109 "InitializeRelativeTimeFormat called with non-RelativeTimeFormat" 110 ); 111 112 // Lazy RelativeTimeFormat data has the following structure: 113 // 114 // { 115 // requestedLocales: List of locales, 116 // style: "long" / "short" / "narrow", 117 // numeric: "always" / "auto", 118 // 119 // opt: // opt object computed in InitializeRelativeTimeFormat 120 // { 121 // localeMatcher: "lookup" / "best fit", 122 // } 123 // } 124 // 125 // Note that lazy data is only installed as a final step of initialization, 126 // so every RelativeTimeFormat lazy data object has *all* these properties, never a 127 // subset of them. 128 var lazyRelativeTimeFormatData = std_Object_create(null); 129 130 // Step 1. 131 var requestedLocales = CanonicalizeLocaleList(locales); 132 lazyRelativeTimeFormatData.requestedLocales = requestedLocales; 133 134 // Steps 2-3. 135 if (options === undefined) { 136 options = std_Object_create(null); 137 } else { 138 options = ToObject(options); 139 } 140 141 // Step 4. 142 var opt = NEW_RECORD(); 143 144 // Steps 5-6. 145 var matcher = GetOption( 146 options, 147 "localeMatcher", 148 "string", 149 ["lookup", "best fit"], 150 "best fit" 151 ); 152 opt.localeMatcher = matcher; 153 154 // Steps 7-9. 155 var numberingSystem = GetOption( 156 options, 157 "numberingSystem", 158 "string", 159 undefined, 160 undefined 161 ); 162 if (numberingSystem !== undefined) { 163 numberingSystem = intl_ValidateAndCanonicalizeUnicodeExtensionType( 164 numberingSystem, 165 "numberingSystem", 166 "nu" 167 ); 168 } 169 opt.nu = numberingSystem; 170 171 lazyRelativeTimeFormatData.opt = opt; 172 173 // Steps 16-17. 174 var style = GetOption( 175 options, 176 "style", 177 "string", 178 ["long", "short", "narrow"], 179 "long" 180 ); 181 lazyRelativeTimeFormatData.style = style; 182 183 // Steps 18-19. 184 var numeric = GetOption( 185 options, 186 "numeric", 187 "string", 188 ["always", "auto"], 189 "always" 190 ); 191 lazyRelativeTimeFormatData.numeric = numeric; 192 193 initializeIntlObject( 194 relativeTimeFormat, 195 "RelativeTimeFormat", 196 lazyRelativeTimeFormatData 197 ); 198 } 199 200 /** 201 * Returns a String value representing the written form of a relative date 202 * formatted according to the effective locale and the formatting options 203 * of this RelativeTimeFormat object. 204 * 205 * Spec: ECMAScript 402 API, RelativeTImeFormat, 1.4.3. 206 */ 207 function Intl_RelativeTimeFormat_format(value, unit) { 208 // Step 1. 209 var relativeTimeFormat = this; 210 211 // Step 2. 212 if ( 213 !IsObject(relativeTimeFormat) || 214 (relativeTimeFormat = intl_GuardToRelativeTimeFormat( 215 relativeTimeFormat 216 )) === null 217 ) { 218 return callFunction( 219 intl_CallRelativeTimeFormatMethodIfWrapped, 220 this, 221 value, 222 unit, 223 "Intl_RelativeTimeFormat_format" 224 ); 225 } 226 227 // Step 3. 228 var t = TO_NUMBER(value); 229 230 // Step 4. 231 var u = ToString(unit); 232 233 // Step 5. 234 return intl_FormatRelativeTime(relativeTimeFormat, t, u, false); 235 } 236 237 /** 238 * Returns an Array composed of the components of a relative date formatted 239 * according to the effective locale and the formatting options of this 240 * RelativeTimeFormat object. 241 * 242 * Spec: ECMAScript 402 API, RelativeTImeFormat, 1.4.4. 243 */ 244 function Intl_RelativeTimeFormat_formatToParts(value, unit) { 245 // Step 1. 246 var relativeTimeFormat = this; 247 248 // Step 2. 249 if ( 250 !IsObject(relativeTimeFormat) || 251 (relativeTimeFormat = intl_GuardToRelativeTimeFormat( 252 relativeTimeFormat 253 )) === null 254 ) { 255 return callFunction( 256 intl_CallRelativeTimeFormatMethodIfWrapped, 257 this, 258 value, 259 unit, 260 "Intl_RelativeTimeFormat_formatToParts" 261 ); 262 } 263 264 // Step 3. 265 var t = TO_NUMBER(value); 266 267 // Step 4. 268 var u = ToString(unit); 269 270 // Step 5. 271 return intl_FormatRelativeTime(relativeTimeFormat, t, u, true); 272 } 273 274 /** 275 * Returns the resolved options for a RelativeTimeFormat object. 276 * 277 * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.4.5. 278 */ 279 function Intl_RelativeTimeFormat_resolvedOptions() { 280 // Step 1. 281 var relativeTimeFormat = this; 282 283 // Steps 2-3. 284 if ( 285 !IsObject(relativeTimeFormat) || 286 (relativeTimeFormat = intl_GuardToRelativeTimeFormat( 287 relativeTimeFormat 288 )) === null 289 ) { 290 return callFunction( 291 intl_CallRelativeTimeFormatMethodIfWrapped, 292 this, 293 "Intl_RelativeTimeFormat_resolvedOptions" 294 ); 295 } 296 297 var internals = getRelativeTimeFormatInternals(relativeTimeFormat); 298 299 // Steps 4-5. 300 var result = { 301 locale: internals.locale, 302 style: internals.style, 303 numeric: internals.numeric, 304 numberingSystem: internals.numberingSystem, 305 }; 306 307 // Step 6. 308 return result; 309 }