tor-browser

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

DisplayNames.js (9422B)


      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 * Intl.DisplayNames internal properties.
      7 */
      8 function displayNamesLocaleData() {
      9  // Intl.DisplayNames doesn't support any extension keys.
     10  return {};
     11 }
     12 var displayNamesInternalProperties = {
     13  localeData: displayNamesLocaleData,
     14  relevantExtensionKeys: [],
     15 };
     16 
     17 function mozDisplayNamesLocaleData() {
     18  return {
     19    ca: intl_availableCalendars,
     20    default: {
     21      ca: intl_defaultCalendar,
     22    },
     23  };
     24 }
     25 var mozDisplayNamesInternalProperties = {
     26  localeData: mozDisplayNamesLocaleData,
     27  relevantExtensionKeys: ["ca"],
     28 };
     29 
     30 /**
     31 * Intl.DisplayNames ( [ locales [ , options ] ] )
     32 *
     33 * Compute an internal properties object from |lazyDisplayNamesData|.
     34 */
     35 function resolveDisplayNamesInternals(lazyDisplayNamesData) {
     36  assert(IsObject(lazyDisplayNamesData), "lazy data not an object?");
     37 
     38  var internalProps = std_Object_create(null);
     39 
     40  var mozExtensions = lazyDisplayNamesData.mozExtensions;
     41 
     42  var DisplayNames = mozExtensions
     43    ? mozDisplayNamesInternalProperties
     44    : displayNamesInternalProperties;
     45 
     46  // Compute effective locale.
     47 
     48  // Step 7.
     49  var localeData = DisplayNames.localeData;
     50 
     51  // Step 10.
     52  var r = ResolveLocale(
     53    "DisplayNames",
     54    lazyDisplayNamesData.requestedLocales,
     55    lazyDisplayNamesData.opt,
     56    DisplayNames.relevantExtensionKeys,
     57    localeData
     58  );
     59 
     60  // Step 12.
     61  internalProps.style = lazyDisplayNamesData.style;
     62 
     63  // Step 14.
     64  var type = lazyDisplayNamesData.type;
     65  internalProps.type = type;
     66 
     67  // Step 16.
     68  internalProps.fallback = lazyDisplayNamesData.fallback;
     69 
     70  // Step 17.
     71  internalProps.locale = r.locale;
     72 
     73  // Step 25.
     74  if (type === "language") {
     75    internalProps.languageDisplay = lazyDisplayNamesData.languageDisplay;
     76  }
     77 
     78  if (mozExtensions) {
     79    // Note that special casing applies in DateTimeFormat.
     80    internalProps.calendar = r.ca;
     81  }
     82 
     83  // The caller is responsible for associating |internalProps| with the right
     84  // object using |setInternalProperties|.
     85  return internalProps;
     86 }
     87 
     88 /**
     89 * Returns an object containing the DisplayNames internal properties of |obj|.
     90 */
     91 function getDisplayNamesInternals(obj) {
     92  assert(IsObject(obj), "getDisplayNamesInternals called with non-object");
     93  assert(
     94    intl_GuardToDisplayNames(obj) !== null,
     95    "getDisplayNamesInternals called with non-DisplayNames"
     96  );
     97 
     98  var internals = getIntlObjectInternals(obj);
     99  assert(
    100    internals.type === "DisplayNames",
    101    "bad type escaped getIntlObjectInternals"
    102  );
    103 
    104  // If internal properties have already been computed, use them.
    105  var internalProps = maybeInternalProperties(internals);
    106  if (internalProps) {
    107    return internalProps;
    108  }
    109 
    110  // Otherwise it's time to fully create them.
    111  internalProps = resolveDisplayNamesInternals(internals.lazyData);
    112  setInternalProperties(internals, internalProps);
    113  return internalProps;
    114 }
    115 
    116 /**
    117 * Intl.DisplayNames ( [ locales [ , options ] ] )
    118 *
    119 * Initializes an object as a DisplayNames.
    120 *
    121 * This method is complicated a moderate bit by its implementing initialization
    122 * as a *lazy* concept.  Everything that must happen now, does -- but we defer
    123 * all the work we can until the object is actually used as a DisplayNames.
    124 * This later work occurs in |resolveDisplayNamesInternals|; steps not noted
    125 * here occur there.
    126 */
    127 function InitializeDisplayNames(displayNames, locales, options, mozExtensions) {
    128  assert(
    129    IsObject(displayNames),
    130    "InitializeDisplayNames called with non-object"
    131  );
    132  assert(
    133    intl_GuardToDisplayNames(displayNames) !== null,
    134    "InitializeDisplayNames called with non-DisplayNames"
    135  );
    136 
    137  // Lazy DisplayNames data has the following structure:
    138  //
    139  //   {
    140  //     requestedLocales: List of locales,
    141  //
    142  //     opt: // opt object computed in InitializeDisplayNames
    143  //       {
    144  //         localeMatcher: "lookup" / "best fit",
    145  //
    146  //         ca: string matching a Unicode extension type, // optional
    147  //       }
    148  //
    149  //     localeMatcher: "lookup" / "best fit",
    150  //
    151  //     style: "narrow" / "short" / "abbreviated" / "long",
    152  //
    153  //     type: "language" / "region" / "script" / "currency" / "weekday" /
    154  //           "month" / "quarter" / "dayPeriod" / "dateTimeField"
    155  //
    156  //     fallback: "code" / "none",
    157  //
    158  //     // field present only if type === "language":
    159  //     languageDisplay: "dialect" / "standard",
    160  //
    161  //     mozExtensions: true / false,
    162  //   }
    163  //
    164  // Note that lazy data is only installed as a final step of initialization,
    165  // so every DisplayNames lazy data object has *all* these properties, never a
    166  // subset of them.
    167  var lazyDisplayNamesData = std_Object_create(null);
    168 
    169  // Step 3.
    170  var requestedLocales = CanonicalizeLocaleList(locales);
    171  lazyDisplayNamesData.requestedLocales = requestedLocales;
    172 
    173  // Step 4.
    174  if (!IsObject(options)) {
    175    ThrowTypeError(
    176      JSMSG_OBJECT_REQUIRED,
    177      options === null ? "null" : typeof options
    178    );
    179  }
    180 
    181  // Step 5.
    182  var opt = NEW_RECORD();
    183  lazyDisplayNamesData.opt = opt;
    184  lazyDisplayNamesData.mozExtensions = mozExtensions;
    185 
    186  // Steps 7-8.
    187  var matcher = GetOption(
    188    options,
    189    "localeMatcher",
    190    "string",
    191    ["lookup", "best fit"],
    192    "best fit"
    193  );
    194  opt.localeMatcher = matcher;
    195 
    196  if (mozExtensions) {
    197    var calendar = GetOption(
    198      options,
    199      "calendar",
    200      "string",
    201      undefined,
    202      undefined
    203    );
    204 
    205    if (calendar !== undefined) {
    206      calendar = intl_ValidateAndCanonicalizeUnicodeExtensionType(
    207        calendar,
    208        "calendar",
    209        "ca"
    210      );
    211    }
    212 
    213    opt.ca = calendar;
    214  }
    215 
    216  // Step 10.
    217  var style;
    218  if (mozExtensions) {
    219    style = GetOption(
    220      options,
    221      "style",
    222      "string",
    223      ["narrow", "short", "abbreviated", "long"],
    224      "long"
    225    );
    226  } else {
    227    style = GetOption(
    228      options,
    229      "style",
    230      "string",
    231      ["narrow", "short", "long"],
    232      "long"
    233    );
    234  }
    235 
    236  // Step 11.
    237  lazyDisplayNamesData.style = style;
    238 
    239  // Step 12.
    240  var type;
    241  if (mozExtensions) {
    242    type = GetOption(
    243      options,
    244      "type",
    245      "string",
    246      [
    247        "language",
    248        "region",
    249        "script",
    250        "currency",
    251        "calendar",
    252        "dateTimeField",
    253        "weekday",
    254        "month",
    255        "quarter",
    256        "dayPeriod",
    257      ],
    258      undefined
    259    );
    260  } else {
    261    type = GetOption(
    262      options,
    263      "type",
    264      "string",
    265      ["language", "region", "script", "currency", "calendar", "dateTimeField"],
    266      undefined
    267    );
    268  }
    269 
    270  // Step 13.
    271  if (type === undefined) {
    272    ThrowTypeError(JSMSG_UNDEFINED_TYPE);
    273  }
    274 
    275  // Step 14.
    276  lazyDisplayNamesData.type = type;
    277 
    278  // Step 15.
    279  var fallback = GetOption(
    280    options,
    281    "fallback",
    282    "string",
    283    ["code", "none"],
    284    "code"
    285  );
    286 
    287  // Step 16.
    288  lazyDisplayNamesData.fallback = fallback;
    289 
    290  // Step 24.
    291  var languageDisplay = GetOption(
    292    options,
    293    "languageDisplay",
    294    "string",
    295    ["dialect", "standard"],
    296    "dialect"
    297  );
    298 
    299  // Step 25.
    300  if (type === "language") {
    301    lazyDisplayNamesData.languageDisplay = languageDisplay;
    302  }
    303 
    304  // We've done everything that must be done now: mark the lazy data as fully
    305  // computed and install it.
    306  initializeIntlObject(displayNames, "DisplayNames", lazyDisplayNamesData);
    307 }
    308 
    309 /**
    310 * Returns the resolved options for a DisplayNames object.
    311 */
    312 function Intl_DisplayNames_of(code) {
    313  // Step 1.
    314  var displayNames = this;
    315 
    316  // Steps 2-3.
    317  if (
    318    !IsObject(displayNames) ||
    319    (displayNames = intl_GuardToDisplayNames(displayNames)) === null
    320  ) {
    321    return callFunction(
    322      intl_CallDisplayNamesMethodIfWrapped,
    323      this,
    324      "Intl_DisplayNames_of"
    325    );
    326  }
    327 
    328  code = ToString(code);
    329 
    330  var internals = getDisplayNamesInternals(displayNames);
    331 
    332  // Unpack the internals object to avoid a slow runtime to selfhosted JS call
    333  // in |intl_ComputeDisplayName()|.
    334  var {
    335    locale,
    336    calendar = "",
    337    style,
    338    type,
    339    languageDisplay = "",
    340    fallback,
    341  } = internals;
    342 
    343  // Steps 5-10.
    344  return intl_ComputeDisplayName(
    345    displayNames,
    346    locale,
    347    calendar,
    348    style,
    349    languageDisplay,
    350    fallback,
    351    type,
    352    code
    353  );
    354 }
    355 
    356 /**
    357 * Returns the resolved options for a DisplayNames object.
    358 */
    359 function Intl_DisplayNames_resolvedOptions() {
    360  // Step 1.
    361  var displayNames = this;
    362 
    363  // Steps 2-3.
    364  if (
    365    !IsObject(displayNames) ||
    366    (displayNames = intl_GuardToDisplayNames(displayNames)) === null
    367  ) {
    368    return callFunction(
    369      intl_CallDisplayNamesMethodIfWrapped,
    370      this,
    371      "Intl_DisplayNames_resolvedOptions"
    372    );
    373  }
    374 
    375  var internals = getDisplayNamesInternals(displayNames);
    376 
    377  // Steps 4-5.
    378  var options = {
    379    locale: internals.locale,
    380    style: internals.style,
    381    type: internals.type,
    382    fallback: internals.fallback,
    383  };
    384 
    385  // languageDisplay is only present for language display names.
    386  assert(
    387    hasOwn("languageDisplay", internals) === (internals.type === "language"),
    388    "languageDisplay is present iff type is 'language'"
    389  );
    390 
    391  if (hasOwn("languageDisplay", internals)) {
    392    DefineDataProperty(options, "languageDisplay", internals.languageDisplay);
    393  }
    394 
    395  if (hasOwn("calendar", internals)) {
    396    DefineDataProperty(options, "calendar", internals.calendar);
    397  }
    398 
    399  // Step 6.
    400  return options;
    401 }