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