tor-browser

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

shell.js (51278B)


      1 // GENERATED, DO NOT EDIT
      2 // file: asyncHelpers.js
      3 // Copyright (C) 2022 Igalia, S.L. All rights reserved.
      4 // This code is governed by the BSD license found in the LICENSE file.
      5 /*---
      6 description: |
      7    A collection of assertion and wrapper functions for testing asynchronous built-ins.
      8 defines: [asyncTest, assert.throwsAsync]
      9 ---*/
     10 
     11 /**
     12 * Defines the **sole** asynchronous test of a file.
     13 * @see {@link ../docs/rfcs/async-helpers.md} for background.
     14 *
     15 * @param {Function} testFunc a callback whose returned promise indicates test results
     16 *   (fulfillment for success, rejection for failure)
     17 * @returns {void}
     18 */
     19 function asyncTest(testFunc) {
     20  if (!Object.prototype.hasOwnProperty.call(globalThis, "$DONE")) {
     21    throw new Test262Error("asyncTest called without async flag");
     22  }
     23  if (typeof testFunc !== "function") {
     24    $DONE(new Test262Error("asyncTest called with non-function argument"));
     25    return;
     26  }
     27  try {
     28    testFunc().then(
     29      function () {
     30        $DONE();
     31      },
     32      function (error) {
     33        $DONE(error);
     34      }
     35    );
     36  } catch (syncError) {
     37    $DONE(syncError);
     38  }
     39 }
     40 
     41 /**
     42 * Asserts that a callback asynchronously throws an instance of a particular
     43 * error (i.e., returns a promise whose rejection value is an object referencing
     44 * the constructor).
     45 *
     46 * @param {Function} expectedErrorConstructor the expected constructor of the
     47 *   rejection value
     48 * @param {Function} func the callback
     49 * @param {string} [message] the prefix to use for failure messages
     50 * @returns {Promise<void>} fulfills if the expected error is thrown,
     51 *   otherwise rejects
     52 */
     53 assert.throwsAsync = function (expectedErrorConstructor, func, message) {
     54  return new Promise(function (resolve) {
     55    var fail = function (detail) {
     56      if (message === undefined) {
     57        throw new Test262Error(detail);
     58      }
     59      throw new Test262Error(message + " " + detail);
     60    };
     61    if (typeof expectedErrorConstructor !== "function") {
     62      fail("assert.throwsAsync called with an argument that is not an error constructor");
     63    }
     64    if (typeof func !== "function") {
     65      fail("assert.throwsAsync called with an argument that is not a function");
     66    }
     67    var expectedName = expectedErrorConstructor.name;
     68    var expectation = "Expected a " + expectedName + " to be thrown asynchronously";
     69    var res;
     70    try {
     71      res = func();
     72    } catch (thrown) {
     73      fail(expectation + " but the function threw synchronously");
     74    }
     75    if (res === null || typeof res !== "object" || typeof res.then !== "function") {
     76      fail(expectation + " but result was not a thenable");
     77    }
     78    var onResFulfilled, onResRejected;
     79    var resSettlementP = new Promise(function (onFulfilled, onRejected) {
     80      onResFulfilled = onFulfilled;
     81      onResRejected = onRejected;
     82    });
     83    try {
     84      res.then(onResFulfilled, onResRejected)
     85    } catch (thrown) {
     86      fail(expectation + " but .then threw synchronously");
     87    }
     88    resolve(resSettlementP.then(
     89      function () {
     90        fail(expectation + " but no exception was thrown at all");
     91      },
     92      function (thrown) {
     93        var actualName;
     94        if (thrown === null || typeof thrown !== "object") {
     95          fail(expectation + " but thrown value was not an object");
     96        } else if (thrown.constructor !== expectedErrorConstructor) {
     97          actualName = thrown.constructor.name;
     98          if (expectedName === actualName) {
     99            fail(expectation +
    100              " but got a different error constructor with the same name");
    101          }
    102          fail(expectation + " but got a " + actualName);
    103        }
    104      }
    105    ));
    106  });
    107 };
    108 
    109 // file: temporalHelpers.js
    110 // Copyright (C) 2021 Igalia, S.L. All rights reserved.
    111 // This code is governed by the BSD license found in the LICENSE file.
    112 /*---
    113 description: |
    114    This defines helper objects and functions for testing Temporal.
    115 defines: [TemporalHelpers]
    116 features: [Symbol.species, Symbol.iterator, Temporal]
    117 ---*/
    118 
    119 const ASCII_IDENTIFIER = /^[$_a-zA-Z][$_a-zA-Z0-9]*$/u;
    120 
    121 function formatPropertyName(propertyKey, objectName = "") {
    122  switch (typeof propertyKey) {
    123    case "symbol":
    124      if (Symbol.keyFor(propertyKey) !== undefined) {
    125        return `${objectName}[Symbol.for('${Symbol.keyFor(propertyKey)}')]`;
    126      } else if (propertyKey.description.startsWith("Symbol.")) {
    127        return `${objectName}[${propertyKey.description}]`;
    128      } else {
    129        return `${objectName}[Symbol('${propertyKey.description}')]`;
    130      }
    131    case "string":
    132      if (propertyKey !== String(Number(propertyKey))) {
    133        if (ASCII_IDENTIFIER.test(propertyKey)) {
    134          return objectName ? `${objectName}.${propertyKey}` : propertyKey;
    135        }
    136        return `${objectName}['${propertyKey.replace(/'/g, "\\'")}']`;
    137      }
    138      // fall through
    139    default:
    140      // integer or string integer-index
    141      return `${objectName}[${propertyKey}]`;
    142  }
    143 }
    144 
    145 const SKIP_SYMBOL = Symbol("Skip");
    146 
    147 var TemporalHelpers = {
    148  /*
    149   * Codes and maximum lengths of months in the ISO 8601 calendar.
    150   */
    151  ISOMonths: [
    152    { month: 1, monthCode: "M01", daysInMonth: 31 },
    153    { month: 2, monthCode: "M02", daysInMonth: 29 },
    154    { month: 3, monthCode: "M03", daysInMonth: 31 },
    155    { month: 4, monthCode: "M04", daysInMonth: 30 },
    156    { month: 5, monthCode: "M05", daysInMonth: 31 },
    157    { month: 6, monthCode: "M06", daysInMonth: 30 },
    158    { month: 7, monthCode: "M07", daysInMonth: 31 },
    159    { month: 8, monthCode: "M08", daysInMonth: 31 },
    160    { month: 9, monthCode: "M09", daysInMonth: 30 },
    161    { month: 10, monthCode: "M10", daysInMonth: 31 },
    162    { month: 11, monthCode: "M11", daysInMonth: 30 },
    163    { month: 12, monthCode: "M12", daysInMonth: 31 }
    164  ],
    165 
    166  /*
    167   * List of known calendar eras and their possible aliases.
    168   *
    169   * https://tc39.es/proposal-intl-era-monthcode/#table-eras
    170   */
    171  CalendarEras: {
    172    buddhist: [
    173      { era: "be" },
    174    ],
    175    coptic: [
    176      { era: "am" },
    177    ],
    178    ethiopic: [
    179      { era: "aa", aliases: ["mundi"] },
    180      { era: "am", aliases: ["incar"] },
    181    ],
    182    ethioaa: [
    183      { era: "aa", aliases: ["mundi"] },
    184    ],
    185    gregory: [
    186      { era: "bce", aliases: ["bc"] },
    187      { era: "ce", aliases: ["ad"] },
    188    ],
    189    hebrew: [
    190      { era: "am" },
    191    ],
    192    indian: [
    193      { era: "shaka" },
    194    ],
    195    islamic: [
    196      { era: "ah" },
    197      { era: "bh" },
    198    ],
    199    "islamic-civil": [
    200      { era: "bh" },
    201      { era: "ah" },
    202    ],
    203    "islamic-rgsa": [
    204      { era: "bh" },
    205      { era: "ah" },
    206    ],
    207    "islamic-tbla": [
    208      { era: "bh" },
    209      { era: "ah" },
    210    ],
    211    "islamic-umalqura": [
    212      { era: "bh" },
    213      { era: "ah" },
    214    ],
    215    japanese: [
    216      { era: "bce", aliases: ["bc"] },
    217      { era: "ce", aliases: ["ad"] },
    218      { era: "heisei" },
    219      { era: "meiji" },
    220      { era: "reiwa" },
    221      { era: "showa" },
    222      { era: "taisho" },
    223    ],
    224    persian: [
    225      { era: "ap" },
    226    ],
    227    roc: [
    228      { era: "roc", aliases: ["minguo"] },
    229      { era: "broc", aliases: ["before-roc", "minguo-qian"] },
    230    ],
    231  },
    232 
    233  /*
    234   * Return the canonical era code.
    235   */
    236  canonicalizeCalendarEra(calendarId, eraName) {
    237    assert.sameValue(typeof calendarId, "string", "calendar must be string in canonicalizeCalendarEra");
    238 
    239    if (!Object.prototype.hasOwnProperty.call(TemporalHelpers.CalendarEras, calendarId)) {
    240      assert.sameValue(eraName, undefined);
    241      return undefined;
    242    }
    243 
    244    assert.sameValue(typeof eraName, "string", "eraName must be string or undefined in canonicalizeCalendarEra");
    245 
    246    for (let {era, aliases = []} of TemporalHelpers.CalendarEras[calendarId]) {
    247      if (era === eraName || aliases.includes(eraName)) {
    248        return era;
    249      }
    250    }
    251    throw new Test262Error(`Unsupported era name: ${eraName}`);
    252  },
    253 
    254  /*
    255   * assertDuration(duration, years, ...,  nanoseconds[, description]):
    256   *
    257   * Shorthand for asserting that each field of a Temporal.Duration is equal to
    258   * an expected value.
    259   */
    260  assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") {
    261    const prefix = description ? `${description}: ` : "";
    262    assert(duration instanceof Temporal.Duration, `${prefix}instanceof`);
    263    assert.sameValue(duration.years, years, `${prefix}years result:`);
    264    assert.sameValue(duration.months, months, `${prefix}months result:`);
    265    assert.sameValue(duration.weeks, weeks, `${prefix}weeks result:`);
    266    assert.sameValue(duration.days, days, `${prefix}days result:`);
    267    assert.sameValue(duration.hours, hours, `${prefix}hours result:`);
    268    assert.sameValue(duration.minutes, minutes, `${prefix}minutes result:`);
    269    assert.sameValue(duration.seconds, seconds, `${prefix}seconds result:`);
    270    assert.sameValue(duration.milliseconds, milliseconds, `${prefix}milliseconds result:`);
    271    assert.sameValue(duration.microseconds, microseconds, `${prefix}microseconds result:`);
    272    assert.sameValue(duration.nanoseconds, nanoseconds, `${prefix}nanoseconds result`);
    273  },
    274 
    275  /*
    276   * assertDateDuration(duration, years, months, weeks, days, [, description]):
    277   *
    278   * Shorthand for asserting that each date field of a Temporal.Duration is
    279   * equal to an expected value.
    280   */
    281  assertDateDuration(duration, years, months, weeks, days, description = "") {
    282    const prefix = description ? `${description}: ` : "";
    283    assert(duration instanceof Temporal.Duration, `${prefix}instanceof`);
    284    assert.sameValue(duration.years, years, `${prefix}years result:`);
    285    assert.sameValue(duration.months, months, `${prefix}months result:`);
    286    assert.sameValue(duration.weeks, weeks, `${prefix}weeks result:`);
    287    assert.sameValue(duration.days, days, `${prefix}days result:`);
    288    assert.sameValue(duration.hours, 0, `${prefix}hours result should be zero:`);
    289    assert.sameValue(duration.minutes, 0, `${prefix}minutes result should be zero:`);
    290    assert.sameValue(duration.seconds, 0, `${prefix}seconds result should be zero:`);
    291    assert.sameValue(duration.milliseconds, 0, `${prefix}milliseconds result should be zero:`);
    292    assert.sameValue(duration.microseconds, 0, `${prefix}microseconds result should be zero:`);
    293    assert.sameValue(duration.nanoseconds, 0, `${prefix}nanoseconds result should be zero:`);
    294  },
    295 
    296  /*
    297   * assertDurationsEqual(actual, expected[, description]):
    298   *
    299   * Shorthand for asserting that each field of a Temporal.Duration is equal to
    300   * the corresponding field in another Temporal.Duration.
    301   */
    302  assertDurationsEqual(actual, expected, description = "") {
    303    const prefix = description ? `${description}: ` : "";
    304    assert(expected instanceof Temporal.Duration, `${prefix}expected value should be a Temporal.Duration`);
    305    TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description);
    306  },
    307 
    308  /*
    309   * assertInstantsEqual(actual, expected[, description]):
    310   *
    311   * Shorthand for asserting that two Temporal.Instants are of the correct type
    312   * and equal according to their equals() methods.
    313   */
    314  assertInstantsEqual(actual, expected, description = "") {
    315    const prefix = description ? `${description}: ` : "";
    316    assert(expected instanceof Temporal.Instant, `${prefix}expected value should be a Temporal.Instant`);
    317    assert(actual instanceof Temporal.Instant, `${prefix}instanceof`);
    318    assert(actual.equals(expected), `${prefix}equals method`);
    319  },
    320 
    321  /*
    322   * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]):
    323   *
    324   * Shorthand for asserting that each field of a Temporal.PlainDate is equal to
    325   * an expected value. (Except the `calendar` property, since callers may want
    326   * to assert either object equality with an object they put in there, or the
    327   * value of date.calendarId.)
    328   */
    329  assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) {
    330    const prefix = description ? `${description}: ` : "";
    331    assert(date instanceof Temporal.PlainDate, `${prefix}instanceof`);
    332    assert.sameValue(
    333      TemporalHelpers.canonicalizeCalendarEra(date.calendarId, date.era),
    334      TemporalHelpers.canonicalizeCalendarEra(date.calendarId, era),
    335      `${prefix}era result:`
    336    );
    337    assert.sameValue(date.eraYear, eraYear, `${prefix}eraYear result:`);
    338    assert.sameValue(date.year, year, `${prefix}year result:`);
    339    assert.sameValue(date.month, month, `${prefix}month result:`);
    340    assert.sameValue(date.monthCode, monthCode, `${prefix}monthCode result:`);
    341    assert.sameValue(date.day, day, `${prefix}day result:`);
    342  },
    343 
    344  /*
    345   * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]):
    346   *
    347   * Shorthand for asserting that each field of a Temporal.PlainDateTime is
    348   * equal to an expected value. (Except the `calendar` property, since callers
    349   * may want to assert either object equality with an object they put in there,
    350   * or the value of datetime.calendarId.)
    351   */
    352  assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) {
    353    const prefix = description ? `${description}: ` : "";
    354    assert(datetime instanceof Temporal.PlainDateTime, `${prefix}instanceof`);
    355    assert.sameValue(
    356      TemporalHelpers.canonicalizeCalendarEra(datetime.calendarId, datetime.era),
    357      TemporalHelpers.canonicalizeCalendarEra(datetime.calendarId, era),
    358      `${prefix}era result:`
    359    );
    360    assert.sameValue(datetime.eraYear, eraYear, `${prefix}eraYear result:`);
    361    assert.sameValue(datetime.year, year, `${prefix}year result:`);
    362    assert.sameValue(datetime.month, month, `${prefix}month result:`);
    363    assert.sameValue(datetime.monthCode, monthCode, `${prefix}monthCode result:`);
    364    assert.sameValue(datetime.day, day, `${prefix}day result:`);
    365    assert.sameValue(datetime.hour, hour, `${prefix}hour result:`);
    366    assert.sameValue(datetime.minute, minute, `${prefix}minute result:`);
    367    assert.sameValue(datetime.second, second, `${prefix}second result:`);
    368    assert.sameValue(datetime.millisecond, millisecond, `${prefix}millisecond result:`);
    369    assert.sameValue(datetime.microsecond, microsecond, `${prefix}microsecond result:`);
    370    assert.sameValue(datetime.nanosecond, nanosecond, `${prefix}nanosecond result:`);
    371  },
    372 
    373  /*
    374   * assertPlainDateTimesEqual(actual, expected[, description]):
    375   *
    376   * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct
    377   * type, equal according to their equals() methods, and additionally that
    378   * their calendar internal slots are the same value.
    379   */
    380  assertPlainDateTimesEqual(actual, expected, description = "") {
    381    const prefix = description ? `${description}: ` : "";
    382    assert(expected instanceof Temporal.PlainDateTime, `${prefix}expected value should be a Temporal.PlainDateTime`);
    383    assert(actual instanceof Temporal.PlainDateTime, `${prefix}instanceof`);
    384    assert(actual.equals(expected), `${prefix}equals method`);
    385    assert.sameValue(
    386      actual.calendarId,
    387      expected.calendarId,
    388      `${prefix}calendar same value:`
    389    );
    390  },
    391 
    392  /*
    393   * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]):
    394   *
    395   * Shorthand for asserting that each field of a Temporal.PlainMonthDay is
    396   * equal to an expected value. (Except the `calendar` property, since callers
    397   * may want to assert either object equality with an object they put in there,
    398   * or the value of monthDay.calendarId().)
    399   */
    400  assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) {
    401    const prefix = description ? `${description}: ` : "";
    402    assert(monthDay instanceof Temporal.PlainMonthDay, `${prefix}instanceof`);
    403    assert.sameValue(monthDay.monthCode, monthCode, `${prefix}monthCode result:`);
    404    assert.sameValue(monthDay.day, day, `${prefix}day result:`);
    405    const isoYear = Number(monthDay.toString({ calendarName: "always" }).split("-")[0]);
    406    assert.sameValue(isoYear, referenceISOYear, `${prefix}referenceISOYear result:`);
    407  },
    408 
    409  /*
    410   * assertPlainTime(time, hour, ..., nanosecond[, description]):
    411   *
    412   * Shorthand for asserting that each field of a Temporal.PlainTime is equal to
    413   * an expected value.
    414   */
    415  assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") {
    416    const prefix = description ? `${description}: ` : "";
    417    assert(time instanceof Temporal.PlainTime, `${prefix}instanceof`);
    418    assert.sameValue(time.hour, hour, `${prefix}hour result:`);
    419    assert.sameValue(time.minute, minute, `${prefix}minute result:`);
    420    assert.sameValue(time.second, second, `${prefix}second result:`);
    421    assert.sameValue(time.millisecond, millisecond, `${prefix}millisecond result:`);
    422    assert.sameValue(time.microsecond, microsecond, `${prefix}microsecond result:`);
    423    assert.sameValue(time.nanosecond, nanosecond, `${prefix}nanosecond result:`);
    424  },
    425 
    426  /*
    427   * assertPlainTimesEqual(actual, expected[, description]):
    428   *
    429   * Shorthand for asserting that two Temporal.PlainTimes are of the correct
    430   * type and equal according to their equals() methods.
    431   */
    432  assertPlainTimesEqual(actual, expected, description = "") {
    433    const prefix = description ? `${description}: ` : "";
    434    assert(expected instanceof Temporal.PlainTime, `${prefix}expected value should be a Temporal.PlainTime`);
    435    assert(actual instanceof Temporal.PlainTime, `${prefix}instanceof`);
    436    assert(actual.equals(expected), `${prefix}equals method`);
    437  },
    438 
    439  /*
    440   * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear, referenceISODay]]):
    441   *
    442   * Shorthand for asserting that each field of a Temporal.PlainYearMonth is
    443   * equal to an expected value. (Except the `calendar` property, since callers
    444   * may want to assert either object equality with an object they put in there,
    445   * or the value of yearMonth.calendarId.)
    446   *
    447   * Pass null as the referenceISODay if you don't want to give it explicitly.
    448   * In that case, the expected referenceISODay will be computed using PlainDate
    449   * and only verified for consistency, not for equality with a specific value.
    450   */
    451  assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined, referenceISODay = 1) {
    452    const prefix = description ? `${description}: ` : "";
    453    assert(typeof referenceISODay === "number" || referenceISODay === null,
    454      `TemporalHelpers.assertPlainYearMonth() referenceISODay argument should be a number or null, not ${referenceISODay}`);
    455    assert(yearMonth instanceof Temporal.PlainYearMonth, `${prefix}instanceof`);
    456    assert.sameValue(
    457      TemporalHelpers.canonicalizeCalendarEra(yearMonth.calendarId, yearMonth.era),
    458      TemporalHelpers.canonicalizeCalendarEra(yearMonth.calendarId, era),
    459      `${prefix}era result:`
    460    );
    461    assert.sameValue(yearMonth.eraYear, eraYear, `${prefix}eraYear result:`);
    462    assert.sameValue(yearMonth.year, year, `${prefix}year result:`);
    463    assert.sameValue(yearMonth.month, month, `${prefix}month result:`);
    464    assert.sameValue(yearMonth.monthCode, monthCode, `${prefix}monthCode result:`);
    465    const isoDay = Number(yearMonth.toString({ calendarName: "always" }).slice(1).split("-")[2].slice(0, 2));
    466    const expectedISODay = referenceISODay ?? yearMonth.toPlainDate({ day: 1 }).withCalendar("iso8601").day;
    467    assert.sameValue(isoDay, expectedISODay, `${prefix}referenceISODay result:`);
    468  },
    469 
    470  /*
    471   * assertZonedDateTimesEqual(actual, expected[, description]):
    472   *
    473   * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct
    474   * type, equal according to their equals() methods, and additionally that
    475   * their time zones and calendar internal slots are the same value.
    476   */
    477  assertZonedDateTimesEqual(actual, expected, description = "") {
    478    const prefix = description ? `${description}: ` : "";
    479    assert(expected instanceof Temporal.ZonedDateTime, `${prefix}expected value should be a Temporal.ZonedDateTime`);
    480    assert(actual instanceof Temporal.ZonedDateTime, `${prefix}instanceof`);
    481    assert(actual.equals(expected), `${prefix}equals method`);
    482    assert.sameValue(actual.timeZoneId, expected.timeZoneId, `${prefix}time zone same value:`);
    483    assert.sameValue(
    484      actual.calendarId,
    485      expected.calendarId,
    486      `${prefix}calendar same value:`
    487    );
    488  },
    489 
    490  /*
    491   * assertUnreachable(description):
    492   *
    493   * Helper for asserting that code is not executed.
    494   */
    495  assertUnreachable(description) {
    496    let message = "This code should not be executed";
    497    if (description) {
    498      message = `${message}: ${description}`;
    499    }
    500    throw new Test262Error(message);
    501  },
    502 
    503  /*
    504   * checkPlainDateTimeConversionFastPath(func):
    505   *
    506   * ToTemporalDate and ToTemporalTime should both, if given a
    507   * Temporal.PlainDateTime instance, convert to the desired type by reading the
    508   * PlainDateTime's internal slots, rather than calling any getters.
    509   *
    510   * func(datetime) is the actual operation to test, that must
    511   * internally call the abstract operation ToTemporalDate or ToTemporalTime.
    512   * It is passed a Temporal.PlainDateTime instance.
    513   */
    514  checkPlainDateTimeConversionFastPath(func, message = "checkPlainDateTimeConversionFastPath") {
    515    const actual = [];
    516    const expected = [];
    517 
    518    const calendar = "iso8601";
    519    const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
    520    const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype);
    521    ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => {
    522      Object.defineProperty(datetime, property, {
    523        get() {
    524          actual.push(`get ${formatPropertyName(property)}`);
    525          const value = prototypeDescrs[property].get.call(this);
    526          return {
    527            toString() {
    528              actual.push(`toString ${formatPropertyName(property)}`);
    529              return value.toString();
    530            },
    531            valueOf() {
    532              actual.push(`valueOf ${formatPropertyName(property)}`);
    533              return value;
    534            },
    535          };
    536        },
    537      });
    538    });
    539    Object.defineProperty(datetime, "calendar", {
    540      get() {
    541        actual.push("get calendar");
    542        return calendar;
    543      },
    544    });
    545 
    546    func(datetime);
    547    assert.compareArray(actual, expected, `${message}: property getters not called`);
    548  },
    549 
    550  /*
    551   * Check that an options bag that accepts units written in the singular form,
    552   * also accepts the same units written in the plural form.
    553   * func(unit) should call the method with the appropriate options bag
    554   * containing unit as a value. This will be called twice for each element of
    555   * validSingularUnits, once with singular and once with plural, and the
    556   * results of each pair should be the same (whether a Temporal object or a
    557   * primitive value.)
    558   */
    559  checkPluralUnitsAccepted(func, validSingularUnits) {
    560    const plurals = {
    561      year: "years",
    562      month: "months",
    563      week: "weeks",
    564      day: "days",
    565      hour: "hours",
    566      minute: "minutes",
    567      second: "seconds",
    568      millisecond: "milliseconds",
    569      microsecond: "microseconds",
    570      nanosecond: "nanoseconds",
    571    };
    572 
    573    validSingularUnits.forEach((unit) => {
    574      const singularValue = func(unit);
    575      const pluralValue = func(plurals[unit]);
    576      const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`;
    577      if (singularValue instanceof Temporal.Duration) {
    578        TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc);
    579      } else if (singularValue instanceof Temporal.Instant) {
    580        TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc);
    581      } else if (singularValue instanceof Temporal.PlainDateTime) {
    582        TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc);
    583      } else if (singularValue instanceof Temporal.PlainTime) {
    584        TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc);
    585      } else if (singularValue instanceof Temporal.ZonedDateTime) {
    586        TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc);
    587      } else {
    588        assert.sameValue(pluralValue, singularValue);
    589      }
    590    });
    591  },
    592 
    593  /*
    594   * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc):
    595   *
    596   * Checks the type handling of the roundingIncrement option.
    597   * checkFunc(roundingIncrement) is a function which takes the value of
    598   * roundingIncrement to test, and calls the method under test with it,
    599   * returning the result. assertTrueResultFunc(result, description) should
    600   * assert that result is the expected result with roundingIncrement: true, and
    601   * assertObjectResultFunc(result, description) should assert that result is
    602   * the expected result with roundingIncrement being an object with a valueOf()
    603   * method.
    604   */
    605  checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) {
    606    // null converts to 0, which is out of range
    607    assert.throws(RangeError, () => checkFunc(null), "null");
    608    // Booleans convert to either 0 or 1, and 1 is allowed
    609    const trueResult = checkFunc(true);
    610    assertTrueResultFunc(trueResult, "true");
    611    assert.throws(RangeError, () => checkFunc(false), "false");
    612    // Symbols and BigInts cannot convert to numbers
    613    assert.throws(TypeError, () => checkFunc(Symbol()), "symbol");
    614    assert.throws(TypeError, () => checkFunc(2n), "bigint");
    615 
    616    // Objects prefer their valueOf() methods when converting to a number
    617    assert.throws(RangeError, () => checkFunc({}), "plain object");
    618 
    619    const expected = [
    620      "get roundingIncrement.valueOf",
    621      "call roundingIncrement.valueOf",
    622    ];
    623    const actual = [];
    624    const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement");
    625    const objectResult = checkFunc(observer);
    626    assertObjectResultFunc(objectResult, "object with valueOf");
    627    assert.compareArray(actual, expected, "order of operations");
    628  },
    629 
    630  /*
    631   * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc):
    632   *
    633   * Checks the type handling of a string option, of which there are several in
    634   * Temporal.
    635   * propertyName is the name of the option, and value is the value that
    636   * assertFunc should expect it to have.
    637   * checkFunc(value) is a function which takes the value of the option to test,
    638   * and calls the method under test with it, returning the result.
    639   * assertFunc(result, description) should assert that result is the expected
    640   * result with the option value being an object with a toString() method
    641   * which returns the given value.
    642   */
    643  checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) {
    644    // null converts to the string "null", which is an invalid string value
    645    assert.throws(RangeError, () => checkFunc(null), "null");
    646    // Booleans convert to the strings "true" or "false", which are invalid
    647    assert.throws(RangeError, () => checkFunc(true), "true");
    648    assert.throws(RangeError, () => checkFunc(false), "false");
    649    // Symbols cannot convert to strings
    650    assert.throws(TypeError, () => checkFunc(Symbol()), "symbol");
    651    // Numbers convert to strings which are invalid
    652    assert.throws(RangeError, () => checkFunc(2), "number");
    653    // BigInts convert to strings which are invalid
    654    assert.throws(RangeError, () => checkFunc(2n), "bigint");
    655 
    656    // Objects prefer their toString() methods when converting to a string
    657    assert.throws(RangeError, () => checkFunc({}), "plain object");
    658 
    659    const expected = [
    660      `get ${propertyName}.toString`,
    661      `call ${propertyName}.toString`,
    662    ];
    663    const actual = [];
    664    const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName);
    665    const result = checkFunc(observer);
    666    assertFunc(result, "object with toString");
    667    assert.compareArray(actual, expected, "order of operations");
    668  },
    669 
    670  /*
    671   * checkSubclassingIgnored(construct, constructArgs, method, methodArgs,
    672   *   resultAssertions):
    673   *
    674   * Methods of Temporal classes that return a new instance of the same class,
    675   * must not take the constructor of a subclass into account, nor the @@species
    676   * property. This helper runs tests to ensure this.
    677   *
    678   * construct(...constructArgs) must yield a valid instance of the Temporal
    679   * class. instance[method](...methodArgs) is the method call under test, which
    680   * must also yield a valid instance of the same Temporal class, not a
    681   * subclass. See below for the individual tests that this runs.
    682   * resultAssertions() is a function that performs additional assertions on the
    683   * instance returned by the method under test.
    684   */
    685  checkSubclassingIgnored(...args) {
    686    this.checkSubclassConstructorNotObject(...args);
    687    this.checkSubclassConstructorUndefined(...args);
    688    this.checkSubclassConstructorThrows(...args);
    689    this.checkSubclassConstructorNotCalled(...args);
    690    this.checkSubclassSpeciesInvalidResult(...args);
    691    this.checkSubclassSpeciesNotAConstructor(...args);
    692    this.checkSubclassSpeciesNull(...args);
    693    this.checkSubclassSpeciesUndefined(...args);
    694    this.checkSubclassSpeciesThrows(...args);
    695  },
    696 
    697  /*
    698   * Checks that replacing the 'constructor' property of the instance with
    699   * various primitive values does not affect the returned new instance.
    700   */
    701  checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) {
    702    function check(value, description) {
    703      const instance = new construct(...constructArgs);
    704      instance.constructor = value;
    705      const result = instance[method](...methodArgs);
    706      assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description);
    707      resultAssertions(result);
    708    }
    709 
    710    check(null, "null");
    711    check(true, "true");
    712    check("test", "string");
    713    check(Symbol(), "Symbol");
    714    check(7, "number");
    715    check(7n, "bigint");
    716  },
    717 
    718  /*
    719   * Checks that replacing the 'constructor' property of the subclass with
    720   * undefined does not affect the returned new instance.
    721   */
    722  checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) {
    723    let called = 0;
    724 
    725    class MySubclass extends construct {
    726      constructor() {
    727        ++called;
    728        super(...constructArgs);
    729      }
    730    }
    731 
    732    const instance = new MySubclass();
    733    assert.sameValue(called, 1);
    734 
    735    MySubclass.prototype.constructor = undefined;
    736 
    737    const result = instance[method](...methodArgs);
    738    assert.sameValue(called, 1);
    739    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    740    resultAssertions(result);
    741  },
    742 
    743  /*
    744   * Checks that making the 'constructor' property of the instance throw when
    745   * called does not affect the returned new instance.
    746   */
    747  checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) {
    748    function CustomError() {}
    749    const instance = new construct(...constructArgs);
    750    Object.defineProperty(instance, "constructor", {
    751      get() {
    752        throw new CustomError();
    753      }
    754    });
    755    const result = instance[method](...methodArgs);
    756    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    757    resultAssertions(result);
    758  },
    759 
    760  /*
    761   * Checks that when subclassing, the subclass constructor is not called by
    762   * the method under test.
    763   */
    764  checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) {
    765    let called = 0;
    766 
    767    class MySubclass extends construct {
    768      constructor() {
    769        ++called;
    770        super(...constructArgs);
    771      }
    772    }
    773 
    774    const instance = new MySubclass();
    775    assert.sameValue(called, 1);
    776 
    777    const result = instance[method](...methodArgs);
    778    assert.sameValue(called, 1);
    779    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    780    resultAssertions(result);
    781  },
    782 
    783  /*
    784   * Check that the constructor's @@species property is ignored when it's a
    785   * constructor that returns a non-object value.
    786   */
    787  checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) {
    788    function check(value, description) {
    789      const instance = new construct(...constructArgs);
    790      instance.constructor = {
    791        [Symbol.species]: function() {
    792          return value;
    793        },
    794      };
    795      const result = instance[method](...methodArgs);
    796      assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description);
    797      resultAssertions(result);
    798    }
    799 
    800    check(undefined, "undefined");
    801    check(null, "null");
    802    check(true, "true");
    803    check("test", "string");
    804    check(Symbol(), "Symbol");
    805    check(7, "number");
    806    check(7n, "bigint");
    807    check({}, "plain object");
    808  },
    809 
    810  /*
    811   * Check that the constructor's @@species property is ignored when it's not a
    812   * constructor.
    813   */
    814  checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) {
    815    function check(value, description) {
    816      const instance = new construct(...constructArgs);
    817      instance.constructor = {
    818        [Symbol.species]: value,
    819      };
    820      const result = instance[method](...methodArgs);
    821      assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description);
    822      resultAssertions(result);
    823    }
    824 
    825    check(true, "true");
    826    check("test", "string");
    827    check(Symbol(), "Symbol");
    828    check(7, "number");
    829    check(7n, "bigint");
    830    check({}, "plain object");
    831  },
    832 
    833  /*
    834   * Check that the constructor's @@species property is ignored when it's null.
    835   */
    836  checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) {
    837    let called = 0;
    838 
    839    class MySubclass extends construct {
    840      constructor() {
    841        ++called;
    842        super(...constructArgs);
    843      }
    844    }
    845 
    846    const instance = new MySubclass();
    847    assert.sameValue(called, 1);
    848 
    849    MySubclass.prototype.constructor = {
    850      [Symbol.species]: null,
    851    };
    852 
    853    const result = instance[method](...methodArgs);
    854    assert.sameValue(called, 1);
    855    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    856    resultAssertions(result);
    857  },
    858 
    859  /*
    860   * Check that the constructor's @@species property is ignored when it's
    861   * undefined.
    862   */
    863  checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) {
    864    let called = 0;
    865 
    866    class MySubclass extends construct {
    867      constructor() {
    868        ++called;
    869        super(...constructArgs);
    870      }
    871    }
    872 
    873    const instance = new MySubclass();
    874    assert.sameValue(called, 1);
    875 
    876    MySubclass.prototype.constructor = {
    877      [Symbol.species]: undefined,
    878    };
    879 
    880    const result = instance[method](...methodArgs);
    881    assert.sameValue(called, 1);
    882    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    883    resultAssertions(result);
    884  },
    885 
    886  /*
    887   * Check that the constructor's @@species property is ignored when it throws,
    888   * i.e. it is not called at all.
    889   */
    890  checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) {
    891    function CustomError() {}
    892 
    893    const instance = new construct(...constructArgs);
    894    instance.constructor = {
    895      get [Symbol.species]() {
    896        throw new CustomError();
    897      },
    898    };
    899 
    900    const result = instance[method](...methodArgs);
    901    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    902  },
    903 
    904  /*
    905   * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions):
    906   *
    907   * Static methods of Temporal classes that return a new instance of the class,
    908   * must not use the this-value as a constructor. This helper runs tests to
    909   * ensure this.
    910   *
    911   * construct[method](...methodArgs) is the static method call under test, and
    912   * must yield a valid instance of the Temporal class, not a subclass. See
    913   * below for the individual tests that this runs.
    914   * resultAssertions() is a function that performs additional assertions on the
    915   * instance returned by the method under test.
    916   */
    917  checkSubclassingIgnoredStatic(...args) {
    918    this.checkStaticInvalidReceiver(...args);
    919    this.checkStaticReceiverNotCalled(...args);
    920    this.checkThisValueNotCalled(...args);
    921  },
    922 
    923  /*
    924   * Check that calling the static method with a receiver that's not callable,
    925   * still calls the intrinsic constructor.
    926   */
    927  checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) {
    928    function check(value, description) {
    929      const result = construct[method].apply(value, methodArgs);
    930      assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    931      resultAssertions(result);
    932    }
    933 
    934    check(undefined, "undefined");
    935    check(null, "null");
    936    check(true, "true");
    937    check("test", "string");
    938    check(Symbol(), "symbol");
    939    check(7, "number");
    940    check(7n, "bigint");
    941    check({}, "Non-callable object");
    942  },
    943 
    944  /*
    945   * Check that calling the static method with a receiver that returns a value
    946   * that's not callable, still calls the intrinsic constructor.
    947   */
    948  checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) {
    949    function check(value, description) {
    950      const receiver = function () {
    951        return value;
    952      };
    953      const result = construct[method].apply(receiver, methodArgs);
    954      assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    955      resultAssertions(result);
    956    }
    957 
    958    check(undefined, "undefined");
    959    check(null, "null");
    960    check(true, "true");
    961    check("test", "string");
    962    check(Symbol(), "symbol");
    963    check(7, "number");
    964    check(7n, "bigint");
    965    check({}, "Non-callable object");
    966  },
    967 
    968  /*
    969   * Check that the receiver isn't called.
    970   */
    971  checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) {
    972    let called = false;
    973 
    974    class MySubclass extends construct {
    975      constructor(...args) {
    976        called = true;
    977        super(...args);
    978      }
    979    }
    980 
    981    const result = MySubclass[method](...methodArgs);
    982    assert.sameValue(called, false);
    983    assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
    984    resultAssertions(result);
    985  },
    986 
    987  /*
    988   * Check that any calendar-carrying Temporal object has its [[Calendar]]
    989   * internal slot read by ToTemporalCalendar, and does not fetch the calendar
    990   * by calling getters.
    991   */
    992  checkToTemporalCalendarFastPath(func) {
    993    const plainDate = new Temporal.PlainDate(2000, 5, 2, "iso8601");
    994    const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, "iso8601");
    995    const plainMonthDay = new Temporal.PlainMonthDay(5, 2, "iso8601");
    996    const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, "iso8601");
    997    const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "iso8601");
    998 
    999    [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => {
   1000      Object.defineProperty(temporalObject, "calendar", {
   1001        get() {
   1002          throw new Test262Error("should not get 'calendar' property");
   1003        },
   1004      });
   1005      Object.defineProperty(temporalObject, "calendarId", {
   1006        get() {
   1007          throw new Test262Error("should not get 'calendarId' property");
   1008        },
   1009      });
   1010 
   1011      func(temporalObject);
   1012    });
   1013  },
   1014 
   1015  checkToTemporalInstantFastPath(func) {
   1016    const actual = [];
   1017    const expected = [];
   1018 
   1019    const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
   1020    Object.defineProperty(datetime, "toString", {
   1021      get() {
   1022        actual.push("get toString");
   1023        return function (options) {
   1024          actual.push("call toString");
   1025          return Temporal.ZonedDateTime.prototype.toString.call(this, options);
   1026        };
   1027      },
   1028    });
   1029 
   1030    func(datetime);
   1031    assert.compareArray(actual, expected, "toString not called");
   1032  },
   1033 
   1034  checkToTemporalPlainDateTimeFastPath(func) {
   1035    const actual = [];
   1036    const expected = [];
   1037 
   1038    const date = new Temporal.PlainDate(2000, 5, 2, "iso8601");
   1039    const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype);
   1040    ["year", "month", "monthCode", "day"].forEach((property) => {
   1041      Object.defineProperty(date, property, {
   1042        get() {
   1043          actual.push(`get ${formatPropertyName(property)}`);
   1044          const value = prototypeDescrs[property].get.call(this);
   1045          return TemporalHelpers.toPrimitiveObserver(actual, value, property);
   1046        },
   1047      });
   1048    });
   1049    ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => {
   1050      Object.defineProperty(date, property, {
   1051        get() {
   1052          actual.push(`get ${formatPropertyName(property)}`);
   1053          return undefined;
   1054        },
   1055      });
   1056    });
   1057    Object.defineProperty(date, "calendar", {
   1058      get() {
   1059        actual.push("get calendar");
   1060        return "iso8601";
   1061      },
   1062    });
   1063 
   1064    func(date);
   1065    assert.compareArray(actual, expected, "property getters not called");
   1066  },
   1067 
   1068  /*
   1069   * observeProperty(calls, object, propertyName, value):
   1070   *
   1071   * Defines an own property @object.@propertyName with value @value, that
   1072   * will log any calls to its accessors to the array @calls.
   1073   */
   1074  observeProperty(calls, object, propertyName, value, objectName = "") {
   1075    Object.defineProperty(object, propertyName, {
   1076      get() {
   1077        calls.push(`get ${formatPropertyName(propertyName, objectName)}`);
   1078        return value;
   1079      },
   1080      set() {
   1081        calls.push(`set ${formatPropertyName(propertyName, objectName)}`);
   1082      }
   1083    });
   1084  },
   1085 
   1086  /*
   1087   * observeMethod(calls, object, propertyName, value):
   1088   *
   1089   * Defines an own property @object.@propertyName with value @value, that
   1090   * will log any calls of @value to the array @calls.
   1091   */
   1092  observeMethod(calls, object, propertyName, objectName = "") {
   1093    const method = object[propertyName];
   1094    object[propertyName] = function () {
   1095      calls.push(`call ${formatPropertyName(propertyName, objectName)}`);
   1096      return method.apply(object, arguments);
   1097    };
   1098  },
   1099 
   1100  /*
   1101   * Used for substituteMethod to indicate default behavior instead of a
   1102   * substituted value
   1103   */
   1104  SUBSTITUTE_SKIP: SKIP_SYMBOL,
   1105 
   1106  /*
   1107   * substituteMethod(object, propertyName, values):
   1108   *
   1109   * Defines an own property @object.@propertyName that will, for each
   1110   * subsequent call to the method previously defined as
   1111   * @object.@propertyName:
   1112   *  - Call the method, if no more values remain
   1113   *  - Call the method, if the value in @values for the corresponding call
   1114   *    is SUBSTITUTE_SKIP
   1115   *  - Otherwise, return the corresponding value in @value
   1116   */
   1117  substituteMethod(object, propertyName, values) {
   1118    let calls = 0;
   1119    const method = object[propertyName];
   1120    object[propertyName] = function () {
   1121      if (calls >= values.length) {
   1122        return method.apply(object, arguments);
   1123      } else if (values[calls] === SKIP_SYMBOL) {
   1124        calls++;
   1125        return method.apply(object, arguments);
   1126      } else {
   1127        return values[calls++];
   1128      }
   1129    };
   1130  },
   1131 
   1132  /*
   1133   * propertyBagObserver():
   1134   * Returns an object that behaves like the given propertyBag but tracks Get
   1135   * and Has operations on any of its properties, by appending messages to an
   1136   * array. If the value of a property in propertyBag is a primitive, the value
   1137   * of the returned object's property will additionally be a
   1138   * TemporalHelpers.toPrimitiveObserver that will track calls to its toString
   1139   * and valueOf methods in the same array. This is for the purpose of testing
   1140   * order of operations that are observable from user code. objectName is used
   1141   * in the log.
   1142   * If skipToPrimitive is given, it must be an array of property keys. Those
   1143   * properties will not have a TemporalHelpers.toPrimitiveObserver returned,
   1144   * and instead just be returned directly.
   1145   */
   1146  propertyBagObserver(calls, propertyBag, objectName, skipToPrimitive) {
   1147    return new Proxy(propertyBag, {
   1148      ownKeys(target) {
   1149        calls.push(`ownKeys ${objectName}`);
   1150        return Reflect.ownKeys(target);
   1151      },
   1152      getOwnPropertyDescriptor(target, key) {
   1153        calls.push(`getOwnPropertyDescriptor ${formatPropertyName(key, objectName)}`);
   1154        return Reflect.getOwnPropertyDescriptor(target, key);
   1155      },
   1156      get(target, key, receiver) {
   1157        calls.push(`get ${formatPropertyName(key, objectName)}`);
   1158        const result = Reflect.get(target, key, receiver);
   1159        if (result === undefined) {
   1160          return undefined;
   1161        }
   1162        if ((result !== null && typeof result === "object") || typeof result === "function") {
   1163          return result;
   1164        }
   1165        if (skipToPrimitive && skipToPrimitive.indexOf(key) >= 0) {
   1166          return result;
   1167        }
   1168        return TemporalHelpers.toPrimitiveObserver(calls, result, `${formatPropertyName(key, objectName)}`);
   1169      },
   1170      has(target, key) {
   1171        calls.push(`has ${formatPropertyName(key, objectName)}`);
   1172        return Reflect.has(target, key);
   1173      },
   1174    });
   1175  },
   1176 
   1177  /*
   1178   * Returns an object that will append logs of any Gets or Calls of its valueOf
   1179   * or toString properties to the array calls. Both valueOf and toString will
   1180   * return the actual primitiveValue. propertyName is used in the log.
   1181   */
   1182  toPrimitiveObserver(calls, primitiveValue, propertyName) {
   1183    return {
   1184      get valueOf() {
   1185        calls.push(`get ${propertyName}.valueOf`);
   1186        return function () {
   1187          calls.push(`call ${propertyName}.valueOf`);
   1188          return primitiveValue;
   1189        };
   1190      },
   1191      get toString() {
   1192        calls.push(`get ${propertyName}.toString`);
   1193        return function () {
   1194          calls.push(`call ${propertyName}.toString`);
   1195          if (primitiveValue === undefined) return undefined;
   1196          return primitiveValue.toString();
   1197        };
   1198      },
   1199    };
   1200  },
   1201 
   1202  /*
   1203   * An object containing further methods that return arrays of ISO strings, for
   1204   * testing parsers.
   1205   */
   1206  ISO: {
   1207    /*
   1208     * PlainMonthDay strings that are not valid.
   1209     */
   1210    plainMonthDayStringsInvalid() {
   1211      return [
   1212        "11-18junk",
   1213        "11-18[u-ca=gregory]",
   1214        "11-18[u-ca=hebrew]",
   1215        "11-18[U-CA=iso8601]",
   1216        "11-18[u-CA=iso8601]",
   1217        "11-18[FOO=bar]",
   1218        "-999999-01-01[u-ca=gregory]",
   1219        "-999999-01-01[u-ca=chinese]",
   1220        "+999999-01-01[u-ca=gregory]",
   1221        "+999999-01-01[u-ca=chinese]",
   1222      ];
   1223    },
   1224 
   1225    /*
   1226     * PlainMonthDay strings that are valid and that should produce October 1st.
   1227     */
   1228    plainMonthDayStringsValid() {
   1229      return [
   1230        "10-01",
   1231        "1001",
   1232        "1965-10-01",
   1233        "1976-10-01T152330.1+00:00",
   1234        "19761001T15:23:30.1+00:00",
   1235        "1976-10-01T15:23:30.1+0000",
   1236        "1976-10-01T152330.1+0000",
   1237        "19761001T15:23:30.1+0000",
   1238        "19761001T152330.1+00:00",
   1239        "19761001T152330.1+0000",
   1240        "+001976-10-01T152330.1+00:00",
   1241        "+0019761001T15:23:30.1+00:00",
   1242        "+001976-10-01T15:23:30.1+0000",
   1243        "+001976-10-01T152330.1+0000",
   1244        "+0019761001T15:23:30.1+0000",
   1245        "+0019761001T152330.1+00:00",
   1246        "+0019761001T152330.1+0000",
   1247        "1976-10-01T15:23:00",
   1248        "1976-10-01T15:23",
   1249        "1976-10-01T15",
   1250        "1976-10-01",
   1251        "--10-01",
   1252        "--1001",
   1253        "-999999-10-01",
   1254        "-999999-10-01[u-ca=iso8601]",
   1255        "+999999-10-01",
   1256        "+999999-10-01[u-ca=iso8601]",
   1257      ];
   1258    },
   1259 
   1260    /*
   1261     * PlainTime strings that may be mistaken for PlainMonthDay or
   1262     * PlainYearMonth strings, and so require a time designator.
   1263     */
   1264    plainTimeStringsAmbiguous() {
   1265      const ambiguousStrings = [
   1266        "2021-12",  // ambiguity between YYYY-MM and HHMM-UU
   1267        "2021-12[-12:00]",  // ditto, TZ does not disambiguate
   1268        "1214",     // ambiguity between MMDD and HHMM
   1269        "0229",     //   ditto, including MMDD that doesn't occur every year
   1270        "1130",     //   ditto, including DD that doesn't occur in every month
   1271        "12-14",    // ambiguity between MM-DD and HH-UU
   1272        "12-14[-14:00]",  // ditto, TZ does not disambiguate
   1273        "202112",   // ambiguity between YYYYMM and HHMMSS
   1274        "202112[UTC]",  // ditto, TZ does not disambiguate
   1275      ];
   1276      // Adding a calendar annotation to one of these strings must not cause
   1277      // disambiguation in favour of time.
   1278      const stringsWithCalendar = ambiguousStrings.map((s) => s + "[u-ca=iso8601]");
   1279      return ambiguousStrings.concat(stringsWithCalendar);
   1280    },
   1281 
   1282    /*
   1283     * PlainTime strings that are of similar form to PlainMonthDay and
   1284     * PlainYearMonth strings, but are not ambiguous due to components that
   1285     * aren't valid as months or days.
   1286     */
   1287    plainTimeStringsUnambiguous() {
   1288      return [
   1289        "2021-13",          // 13 is not a month
   1290        "202113",           //   ditto
   1291        "2021-13[-13:00]",  //   ditto
   1292        "202113[-13:00]",   //   ditto
   1293        "0000-00",          // 0 is not a month
   1294        "000000",           //   ditto
   1295        "0000-00[UTC]",     //   ditto
   1296        "000000[UTC]",      //   ditto
   1297        "1314",             // 13 is not a month
   1298        "13-14",            //   ditto
   1299        "1232",             // 32 is not a day
   1300        "0230",             // 30 is not a day in February
   1301        "0631",             // 31 is not a day in June
   1302        "0000",             // 0 is neither a month nor a day
   1303        "00-00",            //   ditto
   1304      ];
   1305    },
   1306 
   1307    /*
   1308     * PlainYearMonth-like strings that are not valid.
   1309     */
   1310    plainYearMonthStringsInvalid() {
   1311      return [
   1312        "2020-13",
   1313        "1976-11[u-ca=gregory]",
   1314        "1976-11[u-ca=hebrew]",
   1315        "1976-11[U-CA=iso8601]",
   1316        "1976-11[u-CA=iso8601]",
   1317        "1976-11[FOO=bar]",
   1318        "+999999-01",
   1319        "-999999-01",
   1320      ];
   1321    },
   1322 
   1323    /*
   1324     * PlainYearMonth-like strings that are valid and should produce November
   1325     * 1976 in the ISO 8601 calendar.
   1326     */
   1327    plainYearMonthStringsValid() {
   1328      return [
   1329        "1976-11",
   1330        "1976-11-10",
   1331        "1976-11-01T09:00:00+00:00",
   1332        "1976-11-01T00:00:00+05:00",
   1333        "197611",
   1334        "+00197611",
   1335        "1976-11-18T15:23:30.1-02:00",
   1336        "1976-11-18T152330.1+00:00",
   1337        "19761118T15:23:30.1+00:00",
   1338        "1976-11-18T15:23:30.1+0000",
   1339        "1976-11-18T152330.1+0000",
   1340        "19761118T15:23:30.1+0000",
   1341        "19761118T152330.1+00:00",
   1342        "19761118T152330.1+0000",
   1343        "+001976-11-18T152330.1+00:00",
   1344        "+0019761118T15:23:30.1+00:00",
   1345        "+001976-11-18T15:23:30.1+0000",
   1346        "+001976-11-18T152330.1+0000",
   1347        "+0019761118T15:23:30.1+0000",
   1348        "+0019761118T152330.1+00:00",
   1349        "+0019761118T152330.1+0000",
   1350        "1976-11-18T15:23",
   1351        "1976-11-18T15",
   1352        "1976-11-18",
   1353      ];
   1354    },
   1355 
   1356    /*
   1357     * PlainYearMonth-like strings that are valid and should produce November of
   1358     * the ISO year -9999.
   1359     */
   1360    plainYearMonthStringsValidNegativeYear() {
   1361      return [
   1362        "-009999-11",
   1363      ];
   1364    },
   1365  }
   1366 };