tor-browser

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

PluralRules.js (11790B)


      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 * PluralRules internal properties.
      7 *
      8 * 9.1 Internal slots of Service Constructors
      9 * 16.2.3 Properties of the Intl.PluralRules Constructor, Internal slots
     10 *
     11 * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
     12 */
     13 var pluralRulesInternalProperties = {
     14  localeData: pluralRulesLocaleData,
     15  relevantExtensionKeys: [],
     16 };
     17 
     18 function pluralRulesLocaleData() {
     19  // PluralRules don't support any extension keys.
     20  return {};
     21 }
     22 
     23 /**
     24 * 16.1.2 InitializePluralRules ( pluralRules, locales, options )
     25 *
     26 * Compute an internal properties object from |lazyPluralRulesData|.
     27 *
     28 * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
     29 */
     30 function resolvePluralRulesInternals(lazyPluralRulesData) {
     31  assert(IsObject(lazyPluralRulesData), "lazy data not an object?");
     32 
     33  var internalProps = std_Object_create(null);
     34 
     35  var PluralRules = pluralRulesInternalProperties;
     36 
     37  // Compute effective locale.
     38 
     39  // Step 9.
     40  var localeData = PluralRules.localeData;
     41 
     42  // Step 10.
     43  var r = ResolveLocale(
     44    "PluralRules",
     45    lazyPluralRulesData.requestedLocales,
     46    lazyPluralRulesData.opt,
     47    PluralRules.relevantExtensionKeys,
     48    localeData
     49  );
     50 
     51  // Step 11.
     52  internalProps.locale = r.locale;
     53 
     54  // Step 7.
     55  internalProps.type = lazyPluralRulesData.type;
     56 
     57  // Step 8. SetNumberFormatDigitOptions, step 6.
     58  internalProps.minimumIntegerDigits = lazyPluralRulesData.minimumIntegerDigits;
     59 
     60  // Step 8. SetNumberFormatDigitOptions, step 14.
     61  internalProps.roundingIncrement = lazyPluralRulesData.roundingIncrement;
     62 
     63  // Step 8. SetNumberFormatDigitOptions, step 15.
     64  internalProps.roundingMode = lazyPluralRulesData.roundingMode;
     65 
     66  // Step 8. SetNumberFormatDigitOptions, step 16.
     67  internalProps.trailingZeroDisplay = lazyPluralRulesData.trailingZeroDisplay;
     68 
     69  // Step 8. SetNumberFormatDigitOptions, steps 25-26.
     70  if ("minimumFractionDigits" in lazyPluralRulesData) {
     71    assert(
     72      "maximumFractionDigits" in lazyPluralRulesData,
     73      "min/max frac digits mismatch"
     74    );
     75    internalProps.minimumFractionDigits =
     76      lazyPluralRulesData.minimumFractionDigits;
     77    internalProps.maximumFractionDigits =
     78      lazyPluralRulesData.maximumFractionDigits;
     79  }
     80 
     81  // Step 8. SetNumberFormatDigitOptions, steps 24 and 26.
     82  if ("minimumSignificantDigits" in lazyPluralRulesData) {
     83    assert(
     84      "maximumSignificantDigits" in lazyPluralRulesData,
     85      "min/max sig digits mismatch"
     86    );
     87    internalProps.minimumSignificantDigits =
     88      lazyPluralRulesData.minimumSignificantDigits;
     89    internalProps.maximumSignificantDigits =
     90      lazyPluralRulesData.maximumSignificantDigits;
     91  }
     92 
     93  // Step 8. SetNumberFormatDigitOptions, steps 26-30.
     94  internalProps.roundingPriority = lazyPluralRulesData.roundingPriority;
     95 
     96  // `pluralCategories` is lazily computed on first access.
     97  internalProps.pluralCategories = null;
     98 
     99  return internalProps;
    100 }
    101 
    102 /**
    103 * Returns an object containing the PluralRules internal properties of |obj|.
    104 */
    105 function getPluralRulesInternals(obj) {
    106  assert(IsObject(obj), "getPluralRulesInternals called with non-object");
    107  assert(
    108    intl_GuardToPluralRules(obj) !== null,
    109    "getPluralRulesInternals called with non-PluralRules"
    110  );
    111 
    112  var internals = getIntlObjectInternals(obj);
    113  assert(
    114    internals.type === "PluralRules",
    115    "bad type escaped getIntlObjectInternals"
    116  );
    117 
    118  var internalProps = maybeInternalProperties(internals);
    119  if (internalProps) {
    120    return internalProps;
    121  }
    122 
    123  internalProps = resolvePluralRulesInternals(internals.lazyData);
    124  setInternalProperties(internals, internalProps);
    125  return internalProps;
    126 }
    127 
    128 /**
    129 * 16.1.2 InitializePluralRules ( pluralRules, locales, options )
    130 *
    131 * Initializes an object as a PluralRules.
    132 *
    133 * This method is complicated a moderate bit by its implementing initialization
    134 * as a *lazy* concept.  Everything that must happen now, does -- but we defer
    135 * all the work we can until the object is actually used as a PluralRules.
    136 * This later work occurs in |resolvePluralRulesInternals|; steps not noted
    137 * here occur there.
    138 *
    139 * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
    140 */
    141 function InitializePluralRules(pluralRules, locales, options) {
    142  assert(IsObject(pluralRules), "InitializePluralRules called with non-object");
    143  assert(
    144    intl_GuardToPluralRules(pluralRules) !== null,
    145    "InitializePluralRules called with non-PluralRules"
    146  );
    147 
    148  // Lazy PluralRules data has the following structure:
    149  //
    150  //   {
    151  //     requestedLocales: List of locales,
    152  //     type: "cardinal" / "ordinal",
    153  //
    154  //     opt: // opt object computer in InitializePluralRules
    155  //       {
    156  //         localeMatcher: "lookup" / "best fit",
    157  //       }
    158  //
    159  //     minimumIntegerDigits: integer ∈ [1, 21],
    160  //
    161  //     // optional, mutually exclusive with the significant-digits option
    162  //     minimumFractionDigits: integer ∈ [0, 100],
    163  //     maximumFractionDigits: integer ∈ [0, 100],
    164  //
    165  //     // optional, mutually exclusive with the fraction-digits option
    166  //     minimumSignificantDigits: integer ∈ [1, 21],
    167  //     maximumSignificantDigits: integer ∈ [1, 21],
    168  //
    169  //     roundingPriority: "auto" / "lessPrecision" / "morePrecision",
    170  //
    171  //     trailingZeroDisplay: "auto" / "stripIfInteger",
    172  //
    173  //     roundingIncrement: integer ∈ (1, 2, 5,
    174  //                                   10, 20, 25, 50,
    175  //                                   100, 200, 250, 500,
    176  //                                   1000, 2000, 2500, 5000),
    177  //
    178  //     roundingMode: "ceil" / "floor" / "expand" / "trunc" /
    179  //                   "halfCeil" / "halfFloor" / "halfExpand" / "halfTrunc" / "halfEven",
    180  //   }
    181  //
    182  // Note that lazy data is only installed as a final step of initialization,
    183  // so every PluralRules lazy data object has *all* these properties, never a
    184  // subset of them.
    185  var lazyPluralRulesData = std_Object_create(null);
    186 
    187  // Step 1.
    188  var requestedLocales = CanonicalizeLocaleList(locales);
    189  lazyPluralRulesData.requestedLocales = requestedLocales;
    190 
    191  // Step 2. (Inlined call to CoerceOptionsToObject.)
    192  if (options === undefined) {
    193    options = std_Object_create(null);
    194  } else {
    195    options = ToObject(options);
    196  }
    197 
    198  // Step 3.
    199  var opt = NEW_RECORD();
    200  lazyPluralRulesData.opt = opt;
    201 
    202  // Steps 4-5.
    203  var matcher = GetOption(
    204    options,
    205    "localeMatcher",
    206    "string",
    207    ["lookup", "best fit"],
    208    "best fit"
    209  );
    210  opt.localeMatcher = matcher;
    211 
    212  // Steps 6-7.
    213  var type = GetOption(
    214    options,
    215    "type",
    216    "string",
    217    ["cardinal", "ordinal"],
    218    "cardinal"
    219  );
    220  lazyPluralRulesData.type = type;
    221 
    222  // Step 8.
    223  SetNumberFormatDigitOptions(lazyPluralRulesData, options, 0, 3, "standard");
    224 
    225  // Step 12.
    226  //
    227  // We've done everything that must be done now: mark the lazy data as fully
    228  // computed and install it.
    229  initializeIntlObject(pluralRules, "PluralRules", lazyPluralRulesData);
    230 }
    231 
    232 /**
    233 * 16.3.3 Intl.PluralRules.prototype.select ( value )
    234 *
    235 * Returns a String value representing the plural category matching
    236 * the number passed as value according to the
    237 * effective locale and the formatting options of this PluralRules.
    238 *
    239 * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
    240 */
    241 function Intl_PluralRules_select(value) {
    242  // Step 1.
    243  var pluralRules = this;
    244 
    245  // Step 2.
    246  if (
    247    !IsObject(pluralRules) ||
    248    (pluralRules = intl_GuardToPluralRules(pluralRules)) === null
    249  ) {
    250    return callFunction(
    251      intl_CallPluralRulesMethodIfWrapped,
    252      this,
    253      value,
    254      "Intl_PluralRules_select"
    255    );
    256  }
    257 
    258  // Step 3.
    259  var n = TO_NUMBER(value);
    260 
    261  // Ensure the PluralRules internals are resolved.
    262  getPluralRulesInternals(pluralRules);
    263 
    264  // Step 4.
    265  return intl_SelectPluralRule(pluralRules, n);
    266 }
    267 
    268 /**
    269 * 16.3.4 Intl.PluralRules.prototype.selectRange ( start, end )
    270 *
    271 * Returns a String value representing the plural category matching the input
    272 * number range according to the effective locale and the formatting options
    273 * of this PluralRules.
    274 *
    275 * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6
    276 */
    277 function Intl_PluralRules_selectRange(start, end) {
    278  // Step 1.
    279  var pluralRules = this;
    280 
    281  // Step 2.
    282  if (
    283    !IsObject(pluralRules) ||
    284    (pluralRules = intl_GuardToPluralRules(pluralRules)) === null
    285  ) {
    286    return callFunction(
    287      intl_CallPluralRulesMethodIfWrapped,
    288      this,
    289      start,
    290      end,
    291      "Intl_PluralRules_selectRange"
    292    );
    293  }
    294 
    295  // Step 3.
    296  if (start === undefined || end === undefined) {
    297    ThrowTypeError(
    298      JSMSG_UNDEFINED_NUMBER,
    299      start === undefined ? "start" : "end",
    300      "PluralRules",
    301      "selectRange"
    302    );
    303  }
    304 
    305  // Step 4.
    306  var x = TO_NUMBER(start);
    307 
    308  // Step 5.
    309  var y = TO_NUMBER(end);
    310 
    311  // Step 6.
    312  return intl_SelectPluralRuleRange(pluralRules, x, y);
    313 }
    314 
    315 /**
    316 * 16.3.5 Intl.PluralRules.prototype.resolvedOptions ( )
    317 *
    318 * Returns the resolved options for a PluralRules object.
    319 *
    320 * ES2024 Intl draft rev a1db4567870dbe505121a4255f1210338757190a
    321 */
    322 function Intl_PluralRules_resolvedOptions() {
    323  // Step 1.
    324  var pluralRules = this;
    325 
    326  // Step 2.
    327  if (
    328    !IsObject(pluralRules) ||
    329    (pluralRules = intl_GuardToPluralRules(pluralRules)) === null
    330  ) {
    331    return callFunction(
    332      intl_CallPluralRulesMethodIfWrapped,
    333      this,
    334      "Intl_PluralRules_resolvedOptions"
    335    );
    336  }
    337 
    338  var internals = getPluralRulesInternals(pluralRules);
    339 
    340  // Step 4.
    341  var internalsPluralCategories = internals.pluralCategories;
    342  if (internalsPluralCategories === null) {
    343    internalsPluralCategories = intl_GetPluralCategories(pluralRules);
    344    internals.pluralCategories = internalsPluralCategories;
    345  }
    346 
    347  // Step 5.b.
    348  var pluralCategories = [];
    349  for (var i = 0; i < internalsPluralCategories.length; i++) {
    350    DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]);
    351  }
    352 
    353  // Steps 3 and 5.
    354  var result = {
    355    locale: internals.locale,
    356    type: internals.type,
    357    minimumIntegerDigits: internals.minimumIntegerDigits,
    358  };
    359 
    360  // Min/Max fraction digits are either both present or not present at all.
    361  assert(
    362    hasOwn("minimumFractionDigits", internals) ===
    363      hasOwn("maximumFractionDigits", internals),
    364    "minimumFractionDigits is present iff maximumFractionDigits is present"
    365  );
    366 
    367  if (hasOwn("minimumFractionDigits", internals)) {
    368    DefineDataProperty(
    369      result,
    370      "minimumFractionDigits",
    371      internals.minimumFractionDigits
    372    );
    373    DefineDataProperty(
    374      result,
    375      "maximumFractionDigits",
    376      internals.maximumFractionDigits
    377    );
    378  }
    379 
    380  // Min/Max significant digits are either both present or not present at all.
    381  assert(
    382    hasOwn("minimumSignificantDigits", internals) ===
    383      hasOwn("maximumSignificantDigits", internals),
    384    "minimumSignificantDigits is present iff maximumSignificantDigits is present"
    385  );
    386 
    387  if (hasOwn("minimumSignificantDigits", internals)) {
    388    DefineDataProperty(
    389      result,
    390      "minimumSignificantDigits",
    391      internals.minimumSignificantDigits
    392    );
    393    DefineDataProperty(
    394      result,
    395      "maximumSignificantDigits",
    396      internals.maximumSignificantDigits
    397    );
    398  }
    399 
    400  DefineDataProperty(result, "pluralCategories", pluralCategories);
    401  DefineDataProperty(result, "roundingIncrement", internals.roundingIncrement);
    402  DefineDataProperty(result, "roundingMode", internals.roundingMode);
    403  DefineDataProperty(result, "roundingPriority", internals.roundingPriority);
    404  DefineDataProperty(
    405    result,
    406    "trailingZeroDisplay",
    407    internals.trailingZeroDisplay
    408  );
    409 
    410  // Step 6.
    411  return result;
    412 }