tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DurationFormat.js (16305B)


      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 * DurationFormat internal properties.
      7 */
      8 function durationFormatLocaleData() {
      9  return {
     10    nu: getNumberingSystems,
     11    default: {
     12      nu: intl_numberingSystem,
     13    },
     14  };
     15 }
     16 var durationFormatInternalProperties = {
     17  localeData: durationFormatLocaleData,
     18  relevantExtensionKeys: ["nu"],
     19 };
     20 
     21 /**
     22 * Intl.DurationFormat ( [ locales [ , options ] ] )
     23 *
     24 * Compute an internal properties object from |lazyDurationFormatData|.
     25 */
     26 function resolveDurationFormatInternals(lazyDurationFormatData) {
     27  assert(IsObject(lazyDurationFormatData), "lazy data not an object?");
     28 
     29  var internalProps = std_Object_create(null);
     30 
     31  var DurationFormat = durationFormatInternalProperties;
     32 
     33  // Compute effective locale.
     34 
     35  // Step 9.
     36  var r = ResolveLocale(
     37    "DurationFormat",
     38    lazyDurationFormatData.requestedLocales,
     39    lazyDurationFormatData.opt,
     40    DurationFormat.relevantExtensionKeys,
     41    DurationFormat.localeData
     42  );
     43 
     44  // Steps 10-11.
     45  internalProps.locale = r.locale;
     46 
     47  // Steps 12-21. (Not applicable in our implementation.)
     48 
     49  // Step 22.
     50  internalProps.numberingSystem = r.nu;
     51 
     52  // Step 24.
     53  internalProps.style = lazyDurationFormatData.style;
     54 
     55  // Step 26.
     56  internalProps.yearsStyle = lazyDurationFormatData.yearsStyle;
     57  internalProps.yearsDisplay = lazyDurationFormatData.yearsDisplay;
     58 
     59  internalProps.weeksStyle = lazyDurationFormatData.weeksStyle;
     60  internalProps.weeksDisplay = lazyDurationFormatData.weeksDisplay;
     61 
     62  internalProps.monthsStyle = lazyDurationFormatData.monthsStyle;
     63  internalProps.monthsDisplay = lazyDurationFormatData.monthsDisplay;
     64 
     65  internalProps.daysStyle = lazyDurationFormatData.daysStyle;
     66  internalProps.daysDisplay = lazyDurationFormatData.daysDisplay;
     67 
     68  internalProps.hoursStyle = lazyDurationFormatData.hoursStyle;
     69  internalProps.hoursDisplay = lazyDurationFormatData.hoursDisplay;
     70 
     71  internalProps.minutesStyle = lazyDurationFormatData.minutesStyle;
     72  internalProps.minutesDisplay = lazyDurationFormatData.minutesDisplay;
     73 
     74  internalProps.secondsStyle = lazyDurationFormatData.secondsStyle;
     75  internalProps.secondsDisplay = lazyDurationFormatData.secondsDisplay;
     76 
     77  internalProps.millisecondsStyle = lazyDurationFormatData.millisecondsStyle;
     78  internalProps.millisecondsDisplay =
     79    lazyDurationFormatData.millisecondsDisplay;
     80 
     81  internalProps.microsecondsStyle = lazyDurationFormatData.microsecondsStyle;
     82  internalProps.microsecondsDisplay =
     83    lazyDurationFormatData.microsecondsDisplay;
     84 
     85  internalProps.nanosecondsStyle = lazyDurationFormatData.nanosecondsStyle;
     86  internalProps.nanosecondsDisplay = lazyDurationFormatData.nanosecondsDisplay;
     87 
     88  // Step 27.
     89  internalProps.fractionalDigits = lazyDurationFormatData.fractionalDigits;
     90 
     91  // The caller is responsible for associating |internalProps| with the right
     92  // object using |setInternalProperties|.
     93  return internalProps;
     94 }
     95 
     96 /**
     97 * Returns an object containing the DurationFormat internal properties of |obj|.
     98 */
     99 function getDurationFormatInternals(obj) {
    100  assert(IsObject(obj), "getDurationFormatInternals called with non-object");
    101  assert(
    102    intl_GuardToDurationFormat(obj) !== null,
    103    "getDurationFormatInternals called with non-DurationFormat"
    104  );
    105 
    106  var internals = getIntlObjectInternals(obj);
    107  assert(
    108    internals.type === "DurationFormat",
    109    "bad type escaped getIntlObjectInternals"
    110  );
    111 
    112  // If internal properties have already been computed, use them.
    113  var internalProps = maybeInternalProperties(internals);
    114  if (internalProps) {
    115    return internalProps;
    116  }
    117 
    118  // Otherwise it's time to fully create them.
    119  internalProps = resolveDurationFormatInternals(internals.lazyData);
    120  setInternalProperties(internals, internalProps);
    121  return internalProps;
    122 }
    123 
    124 /**
    125 * Intl.DurationFormat ( [ locales [ , options ] ] )
    126 *
    127 * Initializes an object as a DurationFormat.
    128 *
    129 * This method is complicated a moderate bit by its implementing initialization
    130 * as a *lazy* concept.  Everything that must happen now, does -- but we defer
    131 * all the work we can until the object is actually used as a DurationFormat.
    132 * This later work occurs in |resolveDurationFormatInternals|; steps not noted
    133 * here occur there.
    134 */
    135 function InitializeDurationFormat(durationFormat, locales, options) {
    136  assert(
    137    IsObject(durationFormat),
    138    "InitializeDurationFormat called with non-object"
    139  );
    140  assert(
    141    intl_GuardToDurationFormat(durationFormat) !== null,
    142    "InitializeDurationFormat called with non-DurationFormat"
    143  );
    144 
    145  // Lazy DurationFormat data has the following structure:
    146  //
    147  //   {
    148  //     requestedLocales: List of locales,
    149  //     style: "long" / "short" / "narrow" / "digital",
    150  //
    151  //     yearsStyle: "long" / "short" / "narrow",
    152  //     yearsDisplay: "auto" / "always",
    153  //
    154  //     monthsStyle: "long" / "short" / "narrow",
    155  //     monthsDisplay: "auto" / "always",
    156  //
    157  //     weeksStyle: "long" / "short" / "narrow",
    158  //     weeksDisplay: "auto" / "always",
    159  //
    160  //     daysStyle: "long" / "short" / "narrow",
    161  //     daysDisplay: "auto" / "always",
    162  //
    163  //     hoursStyle: "long" / "short" / "narrow" / "numeric" / "2-digit",
    164  //     hoursDisplay: "auto" / "always",
    165  //
    166  //     minutesStyle: "long" / "short" / "narrow" / "numeric" / "2-digit",
    167  //     minutesDisplay: "auto" / "always",
    168  //
    169  //     secondsStyle: "long" / "short" / "narrow" / "numeric" / "2-digit",
    170  //     secondsDisplay: "auto" / "always",
    171  //
    172  //     millisecondsStyle: "long" / "short" / "narrow" / "numeric",
    173  //     millisecondsDisplay: "auto" / "always",
    174  //
    175  //     microsecondsStyle: "long" / "short" / "narrow" / "numeric",
    176  //     microsecondsDisplay: "auto" / "always",
    177  //
    178  //     nanosecondsStyle: "long" / "short" / "narrow" / "numeric",
    179  //     nanosecondsDisplay: "auto" / "always",
    180  //
    181  //     fractionalDigits: integer ∈ [0, 9] / undefined,
    182  //
    183  //     opt: // opt object computed in InitializeDurationFormat
    184  //       {
    185  //         localeMatcher: "lookup" / "best fit",
    186  //
    187  //         nu: string matching a Unicode extension type, // optional
    188  //       }
    189  //   }
    190  //
    191  // Note that lazy data is only installed as a final step of initialization,
    192  // so every DurationFormat lazy data object has *all* these properties,
    193  // never a subset of them.
    194  var lazyDurationFormatData = std_Object_create(null);
    195 
    196  // Step 3.
    197  var requestedLocales = CanonicalizeLocaleList(locales);
    198  lazyDurationFormatData.requestedLocales = requestedLocales;
    199 
    200  // Step 4.
    201  if (options === undefined) {
    202    options = std_Object_create(null);
    203  } else if (!IsObject(options)) {
    204    ThrowTypeError(
    205      JSMSG_OBJECT_REQUIRED,
    206      options === null ? "null" : typeof options
    207    );
    208  }
    209 
    210  // Step 5.
    211  var matcher = GetOption(
    212    options,
    213    "localeMatcher",
    214    "string",
    215    ["lookup", "best fit"],
    216    "best fit"
    217  );
    218 
    219  // Step 6.
    220  var numberingSystem = GetOption(
    221    options,
    222    "numberingSystem",
    223    "string",
    224    undefined,
    225    undefined
    226  );
    227 
    228  // Step 7.
    229  if (numberingSystem !== undefined) {
    230    numberingSystem = intl_ValidateAndCanonicalizeUnicodeExtensionType(
    231      numberingSystem,
    232      "numberingSystem",
    233      "nu"
    234    );
    235  }
    236 
    237  // Step 8.
    238  var opt = NEW_RECORD();
    239  opt.localeMatcher = matcher;
    240  opt.nu = numberingSystem;
    241 
    242  lazyDurationFormatData.opt = opt;
    243 
    244  // Compute formatting options.
    245 
    246  // Steps 23-24.
    247  var style = GetOption(
    248    options,
    249    "style",
    250    "string",
    251    ["long", "short", "narrow", "digital"],
    252    "short"
    253  );
    254  lazyDurationFormatData.style = style;
    255 
    256  // Step 25. (Not applicable in our implementation)
    257 
    258  // Step 26, unit = "years".
    259  var yearsOptions = GetDurationUnitOptions(
    260    "years",
    261    options,
    262    style,
    263    ["long", "short", "narrow"],
    264    "short",
    265    /* prevStyle= */ ""
    266  );
    267  lazyDurationFormatData.yearsStyle = yearsOptions.style;
    268  lazyDurationFormatData.yearsDisplay = yearsOptions.display;
    269 
    270  // Step 26, unit = "months".
    271  var monthsOptions = GetDurationUnitOptions(
    272    "months",
    273    options,
    274    style,
    275    ["long", "short", "narrow"],
    276    "short",
    277    /* prevStyle= */ ""
    278  );
    279  lazyDurationFormatData.monthsStyle = monthsOptions.style;
    280  lazyDurationFormatData.monthsDisplay = monthsOptions.display;
    281 
    282  // Step 26, unit = "weeks".
    283  var weeksOptions = GetDurationUnitOptions(
    284    "weeks",
    285    options,
    286    style,
    287    ["long", "short", "narrow"],
    288    "short",
    289    /* prevStyle= */ ""
    290  );
    291  lazyDurationFormatData.weeksStyle = weeksOptions.style;
    292  lazyDurationFormatData.weeksDisplay = weeksOptions.display;
    293 
    294  // Step 26, unit = "days".
    295  var daysOptions = GetDurationUnitOptions(
    296    "days",
    297    options,
    298    style,
    299    ["long", "short", "narrow"],
    300    "short",
    301    /* prevStyle= */ ""
    302  );
    303  lazyDurationFormatData.daysStyle = daysOptions.style;
    304  lazyDurationFormatData.daysDisplay = daysOptions.display;
    305 
    306  // Step 26, unit = "hours".
    307  var hoursOptions = GetDurationUnitOptions(
    308    "hours",
    309    options,
    310    style,
    311    ["long", "short", "narrow", "numeric", "2-digit"],
    312    "numeric",
    313    /* prevStyle= */ ""
    314  );
    315  lazyDurationFormatData.hoursStyle = hoursOptions.style;
    316  lazyDurationFormatData.hoursDisplay = hoursOptions.display;
    317 
    318  // Step 26, unit = "minutes".
    319  var minutesOptions = GetDurationUnitOptions(
    320    "minutes",
    321    options,
    322    style,
    323    ["long", "short", "narrow", "numeric", "2-digit"],
    324    "numeric",
    325    hoursOptions.style
    326  );
    327  lazyDurationFormatData.minutesStyle = minutesOptions.style;
    328  lazyDurationFormatData.minutesDisplay = minutesOptions.display;
    329 
    330  // Step 26, unit = "seconds".
    331  var secondsOptions = GetDurationUnitOptions(
    332    "seconds",
    333    options,
    334    style,
    335    ["long", "short", "narrow", "numeric", "2-digit"],
    336    "numeric",
    337    minutesOptions.style
    338  );
    339  lazyDurationFormatData.secondsStyle = secondsOptions.style;
    340  lazyDurationFormatData.secondsDisplay = secondsOptions.display;
    341 
    342  // Step 26, unit = "milliseconds".
    343  var millisecondsOptions = GetDurationUnitOptions(
    344    "milliseconds",
    345    options,
    346    style,
    347    ["long", "short", "narrow", "numeric"],
    348    "numeric",
    349    secondsOptions.style
    350  );
    351  lazyDurationFormatData.millisecondsStyle = millisecondsOptions.style;
    352  lazyDurationFormatData.millisecondsDisplay = millisecondsOptions.display;
    353 
    354  // Step 26, unit = "microseconds".
    355  var microsecondsOptions = GetDurationUnitOptions(
    356    "microseconds",
    357    options,
    358    style,
    359    ["long", "short", "narrow", "numeric"],
    360    "numeric",
    361    millisecondsOptions.style
    362  );
    363  lazyDurationFormatData.microsecondsStyle = microsecondsOptions.style;
    364  lazyDurationFormatData.microsecondsDisplay = microsecondsOptions.display;
    365 
    366  // Step 26, unit = "milliseconds".
    367  var nanosecondsOptions = GetDurationUnitOptions(
    368    "nanoseconds",
    369    options,
    370    style,
    371    ["long", "short", "narrow", "numeric"],
    372    "numeric",
    373    microsecondsOptions.style
    374  );
    375  lazyDurationFormatData.nanosecondsStyle = nanosecondsOptions.style;
    376  lazyDurationFormatData.nanosecondsDisplay = nanosecondsOptions.display;
    377 
    378  // Step 27.
    379  lazyDurationFormatData.fractionalDigits = GetNumberOption(
    380    options,
    381    "fractionalDigits",
    382    0,
    383    9,
    384    undefined
    385  );
    386 
    387  // We've done everything that must be done now: mark the lazy data as fully
    388  // computed and install it.
    389  initializeIntlObject(
    390    durationFormat,
    391    "DurationFormat",
    392    lazyDurationFormatData
    393  );
    394 }
    395 
    396 /**
    397 * GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle, twoDigitHours )
    398 */
    399 function GetDurationUnitOptions(
    400  unit,
    401  options,
    402  baseStyle,
    403  stylesList,
    404  digitalBase,
    405  prevStyle
    406 ) {
    407  assert(typeof unit === "string", "unit is a string");
    408  assert(IsObject(options), "options is an object");
    409  assert(typeof baseStyle === "string", "baseStyle is a string");
    410  assert(IsArray(stylesList), "stylesList is an array");
    411  assert(typeof digitalBase === "string", "digitalBase is a string");
    412  assert(typeof prevStyle === "string", "prevStyle is a string");
    413 
    414  // Step 1.
    415  var styleOption = GetOption(options, unit, "string", stylesList, undefined);
    416 
    417  var style = styleOption;
    418 
    419  // Step 2.
    420  var displayDefault = "always";
    421 
    422  // Step 3.
    423  if (style === undefined) {
    424    // Steps 3.a-b.
    425    if (baseStyle === "digital") {
    426      // Step 3.a.i.
    427      if (unit !== "hours" && unit !== "minutes" && unit !== "seconds") {
    428        displayDefault = "auto";
    429      }
    430 
    431      // Step 3.a.ii.
    432      style = digitalBase;
    433    } else {
    434      // Steps 3.b.i-ii. ("fractional" handled implicitly)
    435      if (prevStyle === "numeric" || prevStyle === "2-digit") {
    436        // Step 3.b.i.1.
    437        if (unit !== "minutes" && unit !== "seconds") {
    438          // Step 3.b.i.1.a.
    439          displayDefault = "auto";
    440        }
    441 
    442        // Step 3.b.i.2.
    443        style = "numeric";
    444      } else {
    445        // Step 3.b.ii.1.
    446        displayDefault = "auto";
    447 
    448        // Step 3.b.ii.2.
    449        style = baseStyle;
    450      }
    451    }
    452  }
    453 
    454  // Step 4.
    455  var isFractional =
    456    style === "numeric" &&
    457    (unit === "milliseconds" ||
    458      unit === "microseconds" ||
    459      unit === "nanoseconds");
    460  if (isFractional) {
    461    // Step 4.a.i. (Not applicable in our implementation)
    462 
    463    // Step 4.a.ii.
    464    displayDefault = "auto";
    465  }
    466 
    467  // Step 5.
    468  var displayField = unit + "Display";
    469 
    470  // Step 6.
    471  var displayOption = GetOption(
    472    options,
    473    displayField,
    474    "string",
    475    ["auto", "always"],
    476    undefined
    477  );
    478 
    479  var display = displayOption ?? displayDefault;
    480 
    481  // Step 7.
    482  if (display === "always" && isFractional) {
    483    assert(
    484      styleOption !== undefined || displayOption !== undefined,
    485      "no error is thrown when both 'style' and 'display' are absent"
    486    );
    487 
    488    ThrowRangeError(
    489      // eslint-disable-next-line no-nested-ternary
    490      styleOption !== undefined && displayOption !== undefined
    491        ? JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION
    492        : displayOption !== undefined
    493        ? JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_STYLE
    494        : JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_DISPLAY,
    495      unit
    496    );
    497  }
    498 
    499  // Steps 8-9.
    500  if (prevStyle === "numeric" || prevStyle === "2-digit") {
    501    // Step 8.a. and 9.a.
    502    if (style !== "numeric" && style !== "2-digit") {
    503      ThrowRangeError(
    504        JSMSG_INTL_DURATION_INVALID_NON_NUMERIC_OPTION,
    505        unit,
    506        `"${style}"`
    507      );
    508    }
    509 
    510    // Step 9.b.
    511    else if (unit === "minutes" || unit === "seconds") {
    512      style = "2-digit";
    513    }
    514  }
    515 
    516  // Step 10. (Our implementation doesn't use |twoDigitHours|.)
    517 
    518  // Step 11.
    519  return { style, display };
    520 }
    521 
    522 /**
    523 * Returns the resolved options for a DurationFormat object.
    524 */
    525 function Intl_DurationFormat_resolvedOptions() {
    526  // Step 1.
    527  var durationFormat = this;
    528 
    529  // Step 2.
    530  if (
    531    !IsObject(durationFormat) ||
    532    (durationFormat = intl_GuardToDurationFormat(durationFormat)) === null
    533  ) {
    534    return callFunction(
    535      intl_CallDurationFormatMethodIfWrapped,
    536      this,
    537      "Intl_DurationFormat_resolvedOptions"
    538    );
    539  }
    540 
    541  var internals = getDurationFormatInternals(durationFormat);
    542 
    543  // Steps 3-4.
    544  var result = {
    545    locale: internals.locale,
    546    numberingSystem: internals.numberingSystem,
    547    style: internals.style,
    548    years: internals.yearsStyle,
    549    yearsDisplay: internals.yearsDisplay,
    550    months: internals.monthsStyle,
    551    monthsDisplay: internals.monthsDisplay,
    552    weeks: internals.weeksStyle,
    553    weeksDisplay: internals.weeksDisplay,
    554    days: internals.daysStyle,
    555    daysDisplay: internals.daysDisplay,
    556    hours: internals.hoursStyle,
    557    hoursDisplay: internals.hoursDisplay,
    558    minutes: internals.minutesStyle,
    559    minutesDisplay: internals.minutesDisplay,
    560    seconds: internals.secondsStyle,
    561    secondsDisplay: internals.secondsDisplay,
    562    milliseconds: internals.millisecondsStyle,
    563    millisecondsDisplay: internals.millisecondsDisplay,
    564    microseconds: internals.microsecondsStyle,
    565    microsecondsDisplay: internals.microsecondsDisplay,
    566    nanoseconds: internals.nanosecondsStyle,
    567    nanosecondsDisplay: internals.nanosecondsDisplay,
    568  };
    569 
    570  if (internals.fractionalDigits !== undefined) {
    571    DefineDataProperty(result, "fractionalDigits", internals.fractionalDigits);
    572  }
    573 
    574  // Step 5.
    575  return result;
    576 }