text: /* This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
  /**
   * RelativeTimeFormat internal properties.
   *
   * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.3.3.
   */
  var relativeTimeFormatInternalProperties = {
      localeData: relativeTimeFormatLocaleData,
      relevantExtensionKeys: ["nu"],
  };
  
  function relativeTimeFormatLocaleData() {
      return {
          nu: getNumberingSystems,
          default: {
              nu: intl_numberingSystem,
          },
      };
  }
  
  /**
   * Compute an internal properties object from |lazyRelativeTimeFormatData|.
   */
  function resolveRelativeTimeFormatInternals(lazyRelativeTimeFormatData) {
      assert(IsObject(lazyRelativeTimeFormatData), "lazy data not an object?");
  
      var internalProps = std_Object_create(null);
  
      var RelativeTimeFormat = relativeTimeFormatInternalProperties;
  
      // Steps 10-11.
      const r = ResolveLocale("RelativeTimeFormat",
                              lazyRelativeTimeFormatData.requestedLocales,
                              lazyRelativeTimeFormatData.opt,
                              RelativeTimeFormat.relevantExtensionKeys,
                              RelativeTimeFormat.localeData);
  
      // Steps 12-13.
      internalProps.locale = r.locale;
  
      // Step 14.
      internalProps.numberingSystem = r.nu;
  
      // Step 15 (Not relevant in our implementation).
  
      // Step 17.
      internalProps.style = lazyRelativeTimeFormatData.style;
  
      // Step 19.
      internalProps.numeric = lazyRelativeTimeFormatData.numeric;
  
      // Steps 20-24 (Not relevant in our implementation).
  
      return internalProps;
  }
  
  /**
   * Returns an object containing the RelativeTimeFormat internal properties of |obj|.
   */
  function getRelativeTimeFormatInternals(obj) {
      assert(IsObject(obj), "getRelativeTimeFormatInternals called with non-object");
      assert(intl_GuardToRelativeTimeFormat(obj) !== null,
             "getRelativeTimeFormatInternals called with non-RelativeTimeFormat");
  
      var internals = getIntlObjectInternals(obj);
      assert(internals.type === "RelativeTimeFormat", "bad type escaped getIntlObjectInternals");
  
      var internalProps = maybeInternalProperties(internals);
      if (internalProps)
          return internalProps;
  
      internalProps = resolveRelativeTimeFormatInternals(internals.lazyData);
      setInternalProperties(internals, internalProps);
      return internalProps;
  }
  
  /**
   * Initializes an object as a RelativeTimeFormat.
   *
   * This method is complicated a moderate bit by its implementing initialization
   * as a *lazy* concept.  Everything that must happen now, does -- but we defer
   * all the work we can until the object is actually used as a RelativeTimeFormat.
   * This later work occurs in |resolveRelativeTimeFormatInternals|; steps not noted
   * here occur there.
   *
   * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.1.1.
   */
  function InitializeRelativeTimeFormat(relativeTimeFormat, locales, options) {
      assert(IsObject(relativeTimeFormat),
             "InitializeRelativeimeFormat called with non-object");
      assert(intl_GuardToRelativeTimeFormat(relativeTimeFormat) !== null,
             "InitializeRelativeTimeFormat called with non-RelativeTimeFormat");
  
      // Lazy RelativeTimeFormat data has the following structure:
      //
      //   {
      //     requestedLocales: List of locales,
      //     style: "long" / "short" / "narrow",
      //     numeric: "always" / "auto",
      //
      //     opt: // opt object computed in InitializeRelativeTimeFormat
      //       {
      //         localeMatcher: "lookup" / "best fit",
      //       }
      //   }
      //
      // Note that lazy data is only installed as a final step of initialization,
      // so every RelativeTimeFormat lazy data object has *all* these properties, never a
      // subset of them.
      const lazyRelativeTimeFormatData = std_Object_create(null);
  
      // Step 1.
      let requestedLocales = CanonicalizeLocaleList(locales);
      lazyRelativeTimeFormatData.requestedLocales = requestedLocales;
  
      // Steps 2-3.
      if (options === undefined)
          options = std_Object_create(null);
      else
          options = ToObject(options);
  
      // Step 4.
      let opt = new_Record();
  
      // Steps 5-6.
      let matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit");
      opt.localeMatcher = matcher;
  
      // Steps 7-9.
      let numberingSystem = GetOption(options, "numberingSystem", "string", undefined, undefined);
      if (numberingSystem !== undefined) {
          numberingSystem = intl_ValidateAndCanonicalizeUnicodeExtensionType(numberingSystem,
                                                                             "numberingSystem",
                                                                             "nu");
      }
      opt.nu = numberingSystem;
  
      lazyRelativeTimeFormatData.opt = opt;
  
      // Steps 16-17.
      const style = GetOption(options, "style", "string", ["long", "short", "narrow"], "long");
      lazyRelativeTimeFormatData.style = style;
  
      // Steps 18-19.
      const numeric = GetOption(options, "numeric", "string", ["always", "auto"], "always");
      lazyRelativeTimeFormatData.numeric = numeric;
  
      initializeIntlObject(relativeTimeFormat, "RelativeTimeFormat", lazyRelativeTimeFormatData);
  }
  
  /**
   * Returns the subset of the given locale list for which this locale list has a
   * matching (possibly fallback) locale. Locales appear in the same order in the
   * returned list as in the input list.
   *
   * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.3.2.
   */
  function Intl_RelativeTimeFormat_supportedLocalesOf(locales /*, options*/) {
      var options = arguments.length > 1 ? arguments[1] : undefined;
  
      // Step 1.
      var availableLocales = "RelativeTimeFormat";
  
      // Step 2.
      let requestedLocales = CanonicalizeLocaleList(locales);
  
      // Step 3.
      return SupportedLocales(availableLocales, requestedLocales, options);
  }
  
  /**
   * Returns a String value representing the written form of a relative date
   * formatted according to the effective locale and the formatting options
   * of this RelativeTimeFormat object.
   *
   * Spec: ECMAScript 402 API, RelativeTImeFormat, 1.4.3.
   */
  function Intl_RelativeTimeFormat_format(value, unit) {
      // Step 1.
      let relativeTimeFormat = this;
  
      // Step 2.
      if (!IsObject(relativeTimeFormat) ||
          (relativeTimeFormat = intl_GuardToRelativeTimeFormat(relativeTimeFormat)) === null)
      {
          return callFunction(intl_CallRelativeTimeFormatMethodIfWrapped, this, value, unit,
                              "Intl_RelativeTimeFormat_format");
      }
  
      // Step 3.
      let t = ToNumber(value);
  
      // Step 4.
      let u = ToString(unit);
  
      // Ensure the RelativeTimeFormat internals are resolved.
      var internals = getRelativeTimeFormatInternals(relativeTimeFormat);
  
      // Step 5.
      return intl_FormatRelativeTime(relativeTimeFormat, t, u, internals.numeric,
                                     false);
  }
  
  /**
   * Returns an Array composed of the components of a relative date formatted
   * according to the effective locale and the formatting options of this
   * RelativeTimeFormat object.
   *
   * Spec: ECMAScript 402 API, RelativeTImeFormat, 1.4.4.
   */
  function Intl_RelativeTimeFormat_formatToParts(value, unit) {
      // Step 1.
      let relativeTimeFormat = this;
  
      // Step 2.
      if (!IsObject(relativeTimeFormat) ||
          (relativeTimeFormat = intl_GuardToRelativeTimeFormat(relativeTimeFormat)) === null)
      {
          return callFunction(intl_CallRelativeTimeFormatMethodIfWrapped, this, value, unit,
                              "Intl_RelativeTimeFormat_formatToParts");
      }
  
      // Step 3.
      let t = ToNumber(value);
  
      // Step 4.
      let u = ToString(unit);
  
      // Ensure the RelativeTimeFormat internals are resolved.
      var internals = getRelativeTimeFormatInternals(relativeTimeFormat);
  
      // Step 5.
      return intl_FormatRelativeTime(relativeTimeFormat, t, u, internals.numeric,
                                     true);
  }
  
  /**
   * Returns the resolved options for a RelativeTimeFormat object.
   *
   * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.4.5.
   */
  function Intl_RelativeTimeFormat_resolvedOptions() {
      // Step 1.
      var relativeTimeFormat = this;
  
      // Steps 2-3.
      if (!IsObject(relativeTimeFormat) ||
          (relativeTimeFormat = intl_GuardToRelativeTimeFormat(relativeTimeFormat)) === null)
      {
          return callFunction(intl_CallRelativeTimeFormatMethodIfWrapped, this,
                              "Intl_RelativeTimeFormat_resolvedOptions");
      }
  
      var internals = getRelativeTimeFormatInternals(relativeTimeFormat);
  
      // Steps 4-5.
      var result = {
          locale: internals.locale,
          style: internals.style,
          numeric: internals.numeric,
          numberingSystem: internals.numberingSystem,
      };
  
      // Step 6.
      return result;
  }
  