From 4b4c8ca86f2496c062357fb3aa77d47c107ca1dc Mon Sep 17 00:00:00 2001
From: Philip Chimento <pchimento@igalia.com>
Date: Thu, 25 Feb 2021 21:10:38 -0800
Subject: [PATCH] Consistently call and validate calendar methods

This introduces a bunch of abstract operations, and brings the existing
ones in line with each other, to consistently use GetMethod (which throws
if the method isn't callable) to get the calendar methods off of the
calendar object. Any methods for which we have agreed that Temporal core
(and not the calendars) should validate the return value, are now also
consistently validated in these abstract operations.

Bring the spec text in line with this as well. Some of these abstract
operations existed, but weren't consistently used. (The exception to this
is where the method was fetched only once from the calendar object to be
called multiple times. This will be resolved one way or the other in
issue #1294.)
---
 polyfill/lib/ecmascript.mjs     | 150 ++++++++++++++++++++++++++------
 polyfill/lib/plaindate.mjs      |  64 ++++----------
 polyfill/lib/plaindatetime.mjs  |  50 +++--------
 polyfill/lib/plainmonthday.mjs  |  12 +--
 polyfill/lib/plainyearmonth.mjs |  48 ++++------
 polyfill/lib/zoneddatetime.mjs  |  52 +++--------
 spec/calendar.html              | 140 +++++++++++++++++++++++++++++
 spec/duration.html              |   4 +-
 spec/intl.html                  |  66 +++++++-------
 spec/plaindate.html             |  40 +++------
 spec/plaindatetime.html         |  40 +++------
 spec/plainmonthday.html         |   8 +-
 spec/plainyearmonth.html        |  27 ++----
 spec/zoneddatetime.html         |  44 ++++------
 14 files changed, 418 insertions(+), 327 deletions(-)

diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index d30374e857..8593b32136 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -19,6 +19,7 @@ const ObjectEntries = Object.entries;
 
 import bigInt from 'big-integer';
 import Call from 'es-abstract/2020/Call.js';
+import GetMethod from 'es-abstract/2020/GetMethod.js';
 import SpeciesConstructor from 'es-abstract/2020/SpeciesConstructor.js';
 import IsInteger from 'es-abstract/2020/IsInteger.js';
 import ToInteger from 'es-abstract/2020/ToInteger.js';
@@ -110,6 +111,7 @@ import * as PARSE from './regex.mjs';
 
 const ES2020 = {
   Call,
+  GetMethod,
   SpeciesConstructor,
   IsInteger,
   ToInteger,
@@ -1526,15 +1528,107 @@ export const ES = ObjectAssign({}, ES2020, {
     return calendar;
   },
   CalendarFields: (calendar, fieldNames) => {
-    let fields = calendar.fields;
+    const fields = ES.GetMethod(calendar, 'fields');
     if (fields !== undefined) fieldNames = ES.Call(fields, calendar, [fieldNames]);
     return ES.CreateListFromArrayLike(fieldNames, ['String']);
   },
   CalendarMergeFields: (calendar, fields, additionalFields) => {
-    let mergeFields = calendar.mergeFields;
+    const mergeFields = ES.GetMethod(calendar, 'mergeFields');
     if (mergeFields === undefined) return { ...fields, ...additionalFields };
     return ES.Call(mergeFields, calendar, [fields, additionalFields]);
   },
+  CalendarDateAdd: (calendar, date, duration, options, constructor) => {
+    const dateAdd = ES.GetMethod(calendar, 'dateAdd');
+    const result = ES.Call(dateAdd, calendar, [date, duration, options, constructor]);
+    if (!ES.IsTemporalDate(result)) throw new TypeError('invalid result');
+    return result;
+  },
+  CalendarDateUntil: (calendar, date, otherDate, options) => {
+    const dateUntil = ES.GetMethod(calendar, 'dateUntil');
+    const result = ES.Call(dateUntil, calendar, [date, otherDate, options]);
+    if (!ES.IsTemporalDuration(result)) throw new TypeError('invalid result');
+    return result;
+  },
+  CalendarYear: (calendar, dateLike) => {
+    const year = ES.GetMethod(calendar, 'year');
+    const result = ES.Call(year, calendar, [dateLike]);
+    if (result === undefined) {
+      throw new RangeError('calendar year result must be an integer');
+    }
+    return ES.ToInteger(result);
+  },
+  CalendarMonth: (calendar, dateLike) => {
+    const month = ES.GetMethod(calendar, 'month');
+    const result = ES.Call(month, calendar, [dateLike]);
+    if (result === undefined) {
+      throw new RangeError('calendar month result must be a positive integer');
+    }
+    return ES.ToPositiveInteger(result);
+  },
+  CalendarMonthCode: (calendar, dateLike) => {
+    const monthCode = ES.GetMethod(calendar, 'monthCode');
+    const result = ES.Call(monthCode, calendar, [dateLike]);
+    if (result === undefined) {
+      throw new RangeError('calendar monthCode result must be a string');
+    }
+    return ES.ToString(result);
+  },
+  CalendarDay: (calendar, dateLike) => {
+    const day = ES.GetMethod(calendar, 'day');
+    const result = ES.Call(day, calendar, [dateLike]);
+    if (result === undefined) {
+      throw new RangeError('calendar day result must be a positive integer');
+    }
+    return ES.ToPositiveInteger(result);
+  },
+  CalendarEra: (calendar, dateLike) => {
+    const era = ES.GetMethod(calendar, 'era');
+    let result = ES.Call(era, calendar, [dateLike]);
+    if (result !== undefined) {
+      result = ES.ToString(result);
+    }
+    return result;
+  },
+  CalendarEraYear: (calendar, dateLike) => {
+    const eraYear = ES.GetMethod(calendar, 'eraYear');
+    let result = ES.Call(eraYear, calendar, [dateLike]);
+    if (result !== undefined) {
+      result = ES.ToInteger(result);
+    }
+    return result;
+  },
+  CalendarDayOfWeek: (calendar, dateLike) => {
+    const dayOfWeek = ES.GetMethod(calendar, 'dayOfWeek');
+    return ES.Call(dayOfWeek, calendar, [dateLike]);
+  },
+  CalendarDayOfYear: (calendar, dateLike) => {
+    const dayOfYear = ES.GetMethod(calendar, 'dayOfYear');
+    return ES.Call(dayOfYear, calendar, [dateLike]);
+  },
+  CalendarWeekOfYear: (calendar, dateLike) => {
+    const weekOfYear = ES.GetMethod(calendar, 'weekOfYear');
+    return ES.Call(weekOfYear, calendar, [dateLike]);
+  },
+  CalendarDaysInWeek: (calendar, dateLike) => {
+    const daysInWeek = ES.GetMethod(calendar, 'daysInWeek');
+    return ES.Call(daysInWeek, calendar, [dateLike]);
+  },
+  CalendarDaysInMonth: (calendar, dateLike) => {
+    const daysInMonth = ES.GetMethod(calendar, 'daysInMonth');
+    return ES.Call(daysInMonth, calendar, [dateLike]);
+  },
+  CalendarDaysInYear: (calendar, dateLike) => {
+    const daysInYear = ES.GetMethod(calendar, 'daysInYear');
+    return ES.Call(daysInYear, calendar, [dateLike]);
+  },
+  CalendarMonthsInYear: (calendar, dateLike) => {
+    const monthsInYear = ES.GetMethod(calendar, 'monthsInYear');
+    return ES.Call(monthsInYear, calendar, [dateLike]);
+  },
+  CalendarInLeapYear: (calendar, dateLike) => {
+    const inLeapYear = ES.GetMethod(calendar, 'inLeapYear');
+    return ES.Call(inLeapYear, calendar, [dateLike]);
+  },
 
   ToTemporalCalendar: (calendarLike) => {
     if (ES.Type(calendarLike) === 'Object') {
@@ -1565,17 +1659,20 @@ export const ES = ObjectAssign({}, ES2020, {
     }
   },
   DateFromFields: (calendar, fields, constructor, options) => {
-    const result = calendar.dateFromFields(fields, options, constructor);
+    const dateFromFields = ES.GetMethod(calendar, 'dateFromFields');
+    const result = ES.Call(dateFromFields, calendar, [fields, options, constructor]);
     if (!ES.IsTemporalDate(result)) throw new TypeError('invalid result');
     return result;
   },
   YearMonthFromFields: (calendar, fields, constructor, options) => {
-    const result = calendar.yearMonthFromFields(fields, options, constructor);
+    const yearMonthFromFields = ES.GetMethod(calendar, 'yearMonthFromFields');
+    const result = ES.Call(yearMonthFromFields, calendar, [fields, options, constructor]);
     if (!ES.IsTemporalYearMonth(result)) throw new TypeError('invalid result');
     return result;
   },
   MonthDayFromFields: (calendar, fields, constructor, options) => {
-    const result = calendar.monthDayFromFields(fields, options, constructor);
+    const monthDayFromFields = ES.GetMethod(calendar, 'monthDayFromFields');
+    const result = ES.Call(monthDayFromFields, calendar, [fields, options, constructor]);
     if (!ES.IsTemporalMonthDay(result)) throw new TypeError('invalid result');
     return result;
   },
@@ -1625,7 +1722,7 @@ export const ES = ObjectAssign({}, ES2020, {
     );
   },
   GetOffsetNanosecondsFor: (timeZone, instant) => {
-    let getOffsetNanosecondsFor = timeZone.getOffsetNanosecondsFor;
+    let getOffsetNanosecondsFor = ES.GetMethod(timeZone, 'getOffsetNanosecondsFor');
     if (getOffsetNanosecondsFor === undefined) {
       getOffsetNanosecondsFor = GetIntrinsic('%Temporal.TimeZone.prototype.getOffsetNanosecondsFor%');
     }
@@ -1639,14 +1736,14 @@ export const ES = ObjectAssign({}, ES2020, {
     return offsetNs;
   },
   GetOffsetStringFor: (timeZone, instant) => {
-    let getOffsetStringFor = timeZone.getOffsetStringFor;
+    let getOffsetStringFor = ES.GetMethod(timeZone, 'getOffsetStringFor');
     if (getOffsetStringFor === undefined) {
       getOffsetStringFor = GetIntrinsic('%Temporal.TimeZone.prototype.getOffsetStringFor%');
     }
     return ES.ToString(ES.Call(getOffsetStringFor, timeZone, [instant]));
   },
   GetTemporalDateTimeFor: (timeZone, instant, calendar) => {
-    let getPlainDateTimeFor = timeZone.getPlainDateTimeFor;
+    let getPlainDateTimeFor = ES.GetMethod(timeZone, 'getPlainDateTimeFor');
     if (getPlainDateTimeFor === undefined) {
       getPlainDateTimeFor = GetIntrinsic('%Temporal.TimeZone.prototype.getPlainDateTimeFor%');
     }
@@ -1657,7 +1754,7 @@ export const ES = ObjectAssign({}, ES2020, {
     return dateTime;
   },
   GetTemporalInstantFor: (timeZone, dateTime, disambiguation) => {
-    let getInstantFor = timeZone.getInstantFor;
+    let getInstantFor = ES.GetMethod(timeZone, 'getInstantFor');
     if (getInstantFor === undefined) {
       getInstantFor = GetIntrinsic('%Temporal.TimeZone.prototype.getInstantFor%');
     }
@@ -1668,7 +1765,7 @@ export const ES = ObjectAssign({}, ES2020, {
     return result;
   },
   GetPossibleInstantsFor: (timeZone, dateTime) => {
-    let getPossibleInstantsFor = timeZone.getPossibleInstantsFor;
+    let getPossibleInstantsFor = ES.GetMethod(timeZone, 'getPossibleInstantsFor');
     const possibleInstants = ES.Call(getPossibleInstantsFor, timeZone, [dateTime]);
     const result = ES.CreateListFromArrayLike(possibleInstants, ['Object']);
     const numInstants = result.length;
@@ -2369,8 +2466,9 @@ export const ES = ObjectAssign({}, ES2020, {
         if (!calendar) throw new RangeError('a starting point is required for months balancing');
         // balance years down to months
         while (MathAbs(years) > 0) {
-          const newRelativeTo = calendar.dateAdd(relativeTo, oneYear, {}, TemporalDate);
-          const oneYearMonths = calendar.dateUntil(relativeTo, newRelativeTo, { largestUnit: 'months' }).months;
+          const newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, {}, TemporalDate);
+          const oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, { largestUnit: 'months' })
+            .months;
           relativeTo = newRelativeTo;
           months += oneYearMonths;
           years -= sign;
@@ -2468,14 +2566,14 @@ export const ES = ObjectAssign({}, ES2020, {
         }
 
         // balance months up to years
-        newRelativeTo = calendar.dateAdd(relativeTo, oneYear, {}, TemporalDate);
-        let oneYearMonths = calendar.dateUntil(relativeTo, newRelativeTo, { largestUnit: 'months' }).months;
+        newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, {}, TemporalDate);
+        let oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, { largestUnit: 'months' }).months;
         while (MathAbs(months) >= MathAbs(oneYearMonths)) {
           months -= oneYearMonths;
           years += sign;
           relativeTo = newRelativeTo;
-          newRelativeTo = calendar.dateAdd(relativeTo, oneYear, {}, TemporalDate);
-          oneYearMonths = calendar.dateUntil(relativeTo, newRelativeTo, { largestUnit: 'months' }).months;
+          newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, {}, TemporalDate);
+          oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, { largestUnit: 'months' }).months;
         }
         break;
       }
@@ -2815,7 +2913,7 @@ export const ES = ObjectAssign({}, ES2020, {
     const date2 = new TemporalDate(y2, mon2, d2, calendar);
     const dateLargestUnit = ES.LargerOfTwoTemporalDurationUnits('days', largestUnit);
     const untilOptions = { ...options, largestUnit: dateLargestUnit };
-    let { years, months, weeks, days } = calendar.dateUntil(date1, date2, untilOptions);
+    let { years, months, weeks, days } = ES.CalendarDateUntil(calendar, date1, date2, untilOptions);
     // Signs of date part and time part may not agree; balance them together
     ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceDuration(
       days,
@@ -3007,7 +3105,9 @@ export const ES = ObjectAssign({}, ES2020, {
       const end = ES.Call(dateAdd, calendar, [intermediate, dateDuration2, {}, TemporalPlainDate]);
 
       const dateLargestUnit = ES.LargerOfTwoTemporalDurationUnits('days', largestUnit);
-      ({ years, months, weeks, days } = calendar.dateUntil(datePart, end, { largestUnit: dateLargestUnit }));
+      ({ years, months, weeks, days } = ES.CalendarDateUntil(calendar, datePart, end, {
+        largestUnit: dateLargestUnit
+      }));
       // Signs of date part and time part may not agree; balance them together
       ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceDuration(
         days,
@@ -3155,7 +3255,7 @@ export const ES = ObjectAssign({}, ES2020, {
     const TemporalDuration = GetIntrinsic('%Temporal.Duration%');
     const datePart = new TemporalDate(year, month, day, calendar);
     const dateDuration = new TemporalDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0);
-    const addedDate = calendar.dateAdd(datePart, dateDuration, options, TemporalDate);
+    const addedDate = ES.CalendarDateAdd(calendar, datePart, dateDuration, options, TemporalDate);
 
     return {
       year: GetSlot(addedDate, ISO_YEAR),
@@ -3187,7 +3287,7 @@ export const ES = ObjectAssign({}, ES2020, {
     let dt = ES.GetTemporalDateTimeFor(timeZone, instant, calendar);
     const TemporalDate = GetIntrinsic('%Temporal.PlainDate%');
     const datePart = new TemporalDate(GetSlot(dt, ISO_YEAR), GetSlot(dt, ISO_MONTH), GetSlot(dt, ISO_DAY), calendar);
-    const addedDate = calendar.dateAdd(datePart, { years, months, weeks, days }, options, TemporalDate);
+    const addedDate = ES.CalendarDateAdd(calendar, datePart, { years, months, weeks, days }, options, TemporalDate);
     const TemporalDateTime = GetIntrinsic('%Temporal.PlainDateTime%');
     const dtIntermediate = new TemporalDateTime(
       GetSlot(addedDate, ISO_YEAR),
@@ -3335,7 +3435,7 @@ export const ES = ObjectAssign({}, ES2020, {
   MoveRelativeDate: (calendar, relativeTo, duration) => {
     const TemporalDate = GetIntrinsic('%Temporal.PlainDate%');
     const PlainDateTime = GetIntrinsic('%Temporal.PlainDateTime%');
-    const later = calendar.dateAdd(relativeTo, duration, {}, TemporalDate);
+    const later = ES.CalendarDateAdd(calendar, relativeTo, duration, {}, TemporalDate);
     const days = ES.DaysUntil(relativeTo, later);
     relativeTo = new PlainDateTime(
       GetSlot(later, ISO_YEAR),
@@ -3548,9 +3648,9 @@ export const ES = ObjectAssign({}, ES2020, {
 
         // convert months and weeks to days by calculating difference(
         // relativeTo + years, relativeTo + { years, months, weeks })
-        const yearsLater = calendar.dateAdd(relativeTo, new TemporalDuration(years), {}, TemporalDate);
+        const yearsLater = ES.CalendarDateAdd(calendar, relativeTo, new TemporalDuration(years), {}, TemporalDate);
         const yearsMonthsWeeks = new TemporalDuration(years, months, weeks);
-        const yearsMonthsWeeksLater = calendar.dateAdd(relativeTo, yearsMonthsWeeks, {}, TemporalDate);
+        const yearsMonthsWeeksLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonthsWeeks, {}, TemporalDate);
         const monthsWeeksInDays = ES.DaysUntil(yearsLater, yearsMonthsWeeksLater);
         relativeTo = yearsLater;
         days += monthsWeeksInDays;
@@ -3590,9 +3690,9 @@ export const ES = ObjectAssign({}, ES2020, {
         // convert weeks to days by calculating difference(relativeTo +
         //   { years, months }, relativeTo + { years, months, weeks })
         const yearsMonths = new TemporalDuration(years, months);
-        const yearsMonthsLater = calendar.dateAdd(relativeTo, yearsMonths, {}, TemporalDate);
+        const yearsMonthsLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonths, {}, TemporalDate);
         const yearsMonthsWeeks = new TemporalDuration(years, months, weeks);
-        const yearsMonthsWeeksLater = calendar.dateAdd(relativeTo, yearsMonthsWeeks, {}, TemporalDate);
+        const yearsMonthsWeeksLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonthsWeeks, {}, TemporalDate);
         const weeksInDays = ES.DaysUntil(yearsMonthsLater, yearsMonthsWeeksLater);
         relativeTo = yearsMonthsLater;
         days += weeksInDays;
diff --git a/polyfill/lib/plaindate.mjs b/polyfill/lib/plaindate.mjs
index 973036c08e..11cfc62aaa 100644
--- a/polyfill/lib/plaindate.mjs
+++ b/polyfill/lib/plaindate.mjs
@@ -67,83 +67,59 @@ export class PlainDate {
   }
   get era() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).era(this);
-    if (result !== undefined) {
-      result = ES.ToString(result);
-    }
-    return result;
+    return ES.CalendarEra(GetSlot(this, CALENDAR), this);
   }
   get eraYear() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).eraYear(this);
-    if (result !== undefined) {
-      result = ES.ToInteger(result);
-    }
-    return result;
+    return ES.CalendarEraYear(GetSlot(this, CALENDAR), this);
   }
   get year() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).year(this);
-    if (result === undefined) {
-      throw new RangeError('calendar year result must be an integer');
-    }
-    return ES.ToInteger(result);
+    return ES.CalendarYear(GetSlot(this, CALENDAR), this);
   }
   get month() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).month(this);
-    if (result === undefined) {
-      throw new RangeError('calendar month result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarMonth(GetSlot(this, CALENDAR), this);
   }
   get monthCode() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).monthCode(this);
-    if (result === undefined) {
-      throw new RangeError('calendar monthCode result must be a string');
-    }
-    return ES.ToString(result);
+    return ES.CalendarMonthCode(GetSlot(this, CALENDAR), this);
   }
   get day() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).day(this);
-    if (result === undefined) {
-      throw new RangeError('calendar day result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarDay(GetSlot(this, CALENDAR), this);
   }
   get dayOfWeek() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).dayOfWeek(this);
+    return ES.CalendarDayOfWeek(GetSlot(this, CALENDAR), this);
   }
   get dayOfYear() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).dayOfYear(this);
+    return ES.CalendarDayOfYear(GetSlot(this, CALENDAR), this);
   }
   get weekOfYear() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).weekOfYear(this);
+    return ES.CalendarWeekOfYear(GetSlot(this, CALENDAR), this);
   }
   get daysInWeek() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInWeek(this);
+    return ES.CalendarDaysInWeek(GetSlot(this, CALENDAR), this);
   }
   get daysInMonth() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInMonth(this);
+    return ES.CalendarDaysInMonth(GetSlot(this, CALENDAR), this);
   }
   get daysInYear() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInYear(this);
+    return ES.CalendarDaysInYear(GetSlot(this, CALENDAR), this);
   }
   get monthsInYear() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).monthsInYear(this);
+    return ES.CalendarMonthsInYear(GetSlot(this, CALENDAR), this);
   }
   get inLeapYear() {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).inLeapYear(this);
+    return ES.CalendarInLeapYear(GetSlot(this, CALENDAR), this);
   }
   with(temporalDateLike, options = undefined) {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
@@ -190,9 +166,7 @@ export class PlainDate {
     ({ days } = ES.BalanceDuration(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 'days'));
     duration = { years, months, weeks, days };
     const Construct = ES.SpeciesConstructor(this, PlainDate);
-    const result = GetSlot(this, CALENDAR).dateAdd(this, duration, options, Construct);
-    if (!ES.IsTemporalDate(result)) throw new TypeError('invalid result');
-    return result;
+    return ES.CalendarDateAdd(GetSlot(this, CALENDAR), this, duration, options, Construct);
   }
   subtract(temporalDurationLike, options = undefined) {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
@@ -205,9 +179,7 @@ export class PlainDate {
     ({ days } = ES.BalanceDuration(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 'days'));
     duration = { years: -years, months: -months, weeks: -weeks, days: -days };
     const Construct = ES.SpeciesConstructor(this, PlainDate);
-    const result = GetSlot(this, CALENDAR).dateAdd(this, duration, options, Construct);
-    if (!ES.IsTemporalDate(result)) throw new TypeError('invalid result');
-    return result;
+    return ES.CalendarDateAdd(GetSlot(this, CALENDAR), this, duration, options, Construct);
   }
   until(other, options = undefined) {
     if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
@@ -229,7 +201,7 @@ export class PlainDate {
     const roundingMode = ES.ToTemporalRoundingMode(options, 'trunc');
     const roundingIncrement = ES.ToTemporalRoundingIncrement(options, undefined, false);
 
-    const result = calendar.dateUntil(this, other, options);
+    const result = ES.CalendarDateUntil(calendar, this, other, options);
     if (smallestUnit === 'days' && roundingIncrement === 1) return result;
 
     let { years, months, weeks, days } = result;
@@ -286,7 +258,7 @@ export class PlainDate {
     const roundingMode = ES.ToTemporalRoundingMode(options, 'trunc');
     const roundingIncrement = ES.ToTemporalRoundingIncrement(options, undefined, false);
 
-    let { years, months, weeks, days } = calendar.dateUntil(this, other, options);
+    let { years, months, weeks, days } = ES.CalendarDateUntil(calendar, this, other, options);
     const Duration = GetIntrinsic('%Temporal.Duration%');
     if (smallestUnit === 'days' && roundingIncrement === 1) {
       return new Duration(-years, -months, -weeks, -days, 0, 0, 0, 0, 0, 0);
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index 057a730b80..519ea16505 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -122,33 +122,19 @@ export class PlainDateTime {
   }
   get year() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).year(this);
-    if (result === undefined) {
-      throw new RangeError('calendar year result must be an integer');
-    }
-    return ES.ToInteger(result);
+    return ES.CalendarYear(GetSlot(this, CALENDAR), this);
   }
   get month() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).month(this);
-    if (result === undefined) {
-      throw new RangeError('calendar month result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarMonth(GetSlot(this, CALENDAR), this);
   }
   get monthCode() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).monthCode(this);
-    if (result !== undefined) result = ES.ToString(result);
-    return result;
+    return ES.CalendarMonthCode(GetSlot(this, CALENDAR), this);
   }
   get day() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).day(this);
-    if (result === undefined) {
-      throw new RangeError('calendar day result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarDay(GetSlot(this, CALENDAR), this);
   }
   get hour() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
@@ -176,51 +162,43 @@ export class PlainDateTime {
   }
   get era() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).era(this);
-    if (result !== undefined) {
-      result = ES.ToString(result);
-    }
-    return result;
+    return ES.CalendarEra(GetSlot(this, CALENDAR), this);
   }
   get eraYear() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).eraYear(this);
-    if (result !== undefined) {
-      result = ES.ToInteger(result);
-    }
-    return result;
+    return ES.CalendarEraYear(GetSlot(this, CALENDAR), this);
   }
   get dayOfWeek() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).dayOfWeek(this);
+    return ES.CalendarDayOfWeek(GetSlot(this, CALENDAR), this);
   }
   get dayOfYear() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).dayOfYear(this);
+    return ES.CalendarDayOfYear(GetSlot(this, CALENDAR), this);
   }
   get weekOfYear() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).weekOfYear(this);
+    return ES.CalendarWeekOfYear(GetSlot(this, CALENDAR), this);
   }
   get daysInWeek() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInWeek(this);
+    return ES.CalendarDaysInWeek(GetSlot(this, CALENDAR), this);
   }
   get daysInYear() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInYear(this);
+    return ES.CalendarDaysInYear(GetSlot(this, CALENDAR), this);
   }
   get daysInMonth() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInMonth(this);
+    return ES.CalendarDaysInMonth(GetSlot(this, CALENDAR), this);
   }
   get monthsInYear() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).monthsInYear(this);
+    return ES.CalendarMonthsInYear(GetSlot(this, CALENDAR), this);
   }
   get inLeapYear() {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).inLeapYear(this);
+    return ES.CalendarInLeapYear(GetSlot(this, CALENDAR), this);
   }
   with(temporalDateTimeLike, options = undefined) {
     if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
diff --git a/polyfill/lib/plainmonthday.mjs b/polyfill/lib/plainmonthday.mjs
index 1f2533ed86..a6318c0f1c 100644
--- a/polyfill/lib/plainmonthday.mjs
+++ b/polyfill/lib/plainmonthday.mjs
@@ -57,19 +57,11 @@ export class PlainMonthDay {
 
   get monthCode() {
     if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).monthCode(this);
-    if (result === undefined) {
-      throw new RangeError('calendar monthCode result must be a string');
-    }
-    return ES.ToString(result);
+    return ES.CalendarMonthCode(GetSlot(this, CALENDAR), this);
   }
   get day() {
     if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).day(this);
-    if (result === undefined) {
-      throw new RangeError('calendar day result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarDay(GetSlot(this, CALENDAR), this);
   }
   get calendar() {
     if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
diff --git a/polyfill/lib/plainyearmonth.mjs b/polyfill/lib/plainyearmonth.mjs
index 5cf4c729b4..21de6234bc 100644
--- a/polyfill/lib/plainyearmonth.mjs
+++ b/polyfill/lib/plainyearmonth.mjs
@@ -55,25 +55,15 @@ export class PlainYearMonth {
   }
   get year() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).year(this);
-    if (result === undefined) {
-      throw new RangeError('calendar year result must be an integer');
-    }
-    return ES.ToInteger(result);
+    return ES.CalendarYear(GetSlot(this, CALENDAR), this);
   }
   get month() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).month(this);
-    if (result === undefined) {
-      throw new RangeError('calendar month result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarMonth(GetSlot(this, CALENDAR), this);
   }
   get monthCode() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).monthCode(this);
-    if (result !== undefined) result = ES.ToString(result);
-    return result;
+    return ES.CalendarMonthCode(GetSlot(this, CALENDAR), this);
   }
   get calendar() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
@@ -81,35 +71,27 @@ export class PlainYearMonth {
   }
   get era() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).era(this);
-    if (result !== undefined) {
-      result = ES.ToString(result);
-    }
-    return result;
+    return ES.CalendarEra(GetSlot(this, CALENDAR), this);
   }
   get eraYear() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).eraYear(this);
-    if (result !== undefined) {
-      result = ES.ToInteger(result);
-    }
-    return result;
+    return ES.CalendarEraYear(GetSlot(this, CALENDAR), this);
   }
   get daysInMonth() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInMonth(this);
+    return ES.CalendarDaysInMonth(GetSlot(this, CALENDAR), this);
   }
   get daysInYear() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInYear(this);
+    return ES.CalendarDaysInYear(GetSlot(this, CALENDAR), this);
   }
   get monthsInYear() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).monthsInYear(this);
+    return ES.CalendarMonthsInYear(GetSlot(this, CALENDAR), this);
   }
   get inLeapYear() {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).inLeapYear(this);
+    return ES.CalendarInLeapYear(GetSlot(this, CALENDAR), this);
   }
   with(temporalYearMonthLike, options = undefined) {
     if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
@@ -151,9 +133,9 @@ export class PlainYearMonth {
     const fieldNames = ES.CalendarFields(calendar, ['monthCode', 'year']);
     const fields = ES.ToTemporalYearMonthFields(this, fieldNames);
     const sign = ES.DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0);
-    const day = sign < 0 ? calendar.daysInMonth(this) : 1;
+    const day = sign < 0 ? ES.CalendarDaysInMonth(calendar, this) : 1;
     const startDate = ES.DateFromFields(calendar, { ...fields, day }, TemporalDate);
-    const addedDate = calendar.dateAdd(startDate, { ...duration, days }, options, TemporalDate);
+    const addedDate = ES.CalendarDateAdd(calendar, startDate, { ...duration, days }, options, TemporalDate);
     const addedDateFields = ES.ToTemporalYearMonthFields(addedDate, fieldNames);
 
     const Construct = ES.SpeciesConstructor(this, PlainYearMonth);
@@ -185,9 +167,9 @@ export class PlainYearMonth {
     const fieldNames = ES.CalendarFields(calendar, ['monthCode', 'year']);
     const fields = ES.ToTemporalYearMonthFields(this, fieldNames);
     const sign = ES.DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0);
-    const day = sign < 0 ? calendar.daysInMonth(this) : 1;
+    const day = sign < 0 ? ES.CalendarDaysInMonth(calendar, this) : 1;
     const startDate = ES.DateFromFields(calendar, { ...fields, day }, TemporalDate);
-    const addedDate = calendar.dateAdd(startDate, { ...duration, days }, options, TemporalDate);
+    const addedDate = ES.CalendarDateAdd(calendar, startDate, { ...duration, days }, options, TemporalDate);
     const addedDateFields = ES.ToTemporalYearMonthFields(addedDate, fieldNames);
 
     const Construct = ES.SpeciesConstructor(this, PlainYearMonth);
@@ -230,7 +212,7 @@ export class PlainYearMonth {
     const thisDate = ES.DateFromFields(calendar, { ...thisFields, day: 1 }, TemporalDate);
 
     const untilOptions = { ...options, largestUnit };
-    const result = calendar.dateUntil(thisDate, otherDate, untilOptions);
+    const result = ES.CalendarDateUntil(calendar, thisDate, otherDate, untilOptions);
     if (smallestUnit === 'months' && roundingIncrement === 1) return result;
 
     let { years, months } = result;
@@ -304,7 +286,7 @@ export class PlainYearMonth {
     const thisDate = ES.DateFromFields(calendar, { ...thisFields, day: 1 }, TemporalDate);
 
     const untilOptions = { ...options, largestUnit };
-    let { years, months } = calendar.dateUntil(thisDate, otherDate, untilOptions);
+    let { years, months } = ES.CalendarDateUntil(calendar, thisDate, otherDate, untilOptions);
     const Duration = GetIntrinsic('%Temporal.Duration%');
     if (smallestUnit === 'months' && roundingIncrement === 1) {
       return new Duration(-years, -months, 0, 0, 0, 0, 0, 0, 0, 0);
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 870643274f..842ffe6107 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -69,35 +69,19 @@ export class ZonedDateTime {
   }
   get year() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).year(dateTime(this));
-    if (result === undefined) {
-      throw new RangeError('calendar year result must be an integer');
-    }
-    return ES.ToInteger(result);
+    return ES.CalendarYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get month() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).month(dateTime(this));
-    if (result === undefined) {
-      throw new RangeError('calendar month result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarMonth(GetSlot(this, CALENDAR), dateTime(this));
   }
   get monthCode() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).monthCode(dateTime(this));
-    if (result === undefined) {
-      throw new RangeError('calendar monthCode result must be a string');
-    }
-    return ES.ToString(result);
+    return ES.CalendarMonthCode(GetSlot(this, CALENDAR), dateTime(this));
   }
   get day() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    const result = GetSlot(this, CALENDAR).day(dateTime(this));
-    if (result === undefined) {
-      throw new RangeError('calendar day result must be a positive integer');
-    }
-    return ES.ToPositiveInteger(result);
+    return ES.CalendarDay(GetSlot(this, CALENDAR), dateTime(this));
   }
   get hour() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
@@ -125,19 +109,11 @@ export class ZonedDateTime {
   }
   get era() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).era(dateTime(this));
-    if (result !== undefined) {
-      result = ES.ToString(result);
-    }
-    return result;
+    return ES.CalendarEra(GetSlot(this, CALENDAR), dateTime(this));
   }
   get eraYear() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    let result = GetSlot(this, CALENDAR).eraYear(dateTime(this));
-    if (result !== undefined) {
-      result = ES.ToInteger(result);
-    }
-    return result;
+    return ES.CalendarEraYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get epochSeconds() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
@@ -160,15 +136,15 @@ export class ZonedDateTime {
   }
   get dayOfWeek() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).dayOfWeek(dateTime(this));
+    return ES.CalendarDayOfWeek(GetSlot(this, CALENDAR), dateTime(this));
   }
   get dayOfYear() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).dayOfYear(dateTime(this));
+    return ES.CalendarDayOfYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get weekOfYear() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).weekOfYear(dateTime(this));
+    return ES.CalendarWeekOfYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get hoursInDay() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
@@ -187,23 +163,23 @@ export class ZonedDateTime {
   }
   get daysInWeek() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInWeek(dateTime(this));
+    return ES.CalendarDaysInWeek(GetSlot(this, CALENDAR), dateTime(this));
   }
   get daysInMonth() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInMonth(dateTime(this));
+    return ES.CalendarDaysInMonth(GetSlot(this, CALENDAR), dateTime(this));
   }
   get daysInYear() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).daysInYear(dateTime(this));
+    return ES.CalendarDaysInYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get monthsInYear() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).monthsInYear(dateTime(this));
+    return ES.CalendarMonthsInYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get inLeapYear() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
-    return GetSlot(this, CALENDAR).inLeapYear(dateTime(this));
+    return ES.CalendarInLeapYear(GetSlot(this, CALENDAR), dateTime(this));
   }
   get offset() {
     if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
diff --git a/spec/calendar.html b/spec/calendar.html
index b112b42efd..a3005722b6 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -82,6 +82,146 @@ <h1>CalendarDateUntil ( _calendar_, _one_, _two_, _options_ )</h1>
       </emu-alg>
     </emu-clause>
 
+    <emu-clause id="sec-temporal-calendaryear" aoid="CalendarYear">
+      <h1>CalendarYear ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarYear calls the given _calendar_'s `year()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Let _result_ be ? Invoke(_calendar_, *"year"*, « _dateLike_ »).
+        1. If _result_ is *undefined*, throw a *RangeError* exception.
+        1. Return ? ToIntegerOrInfinity(_result_).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendarmonth" aoid="CalendarMonth">
+      <h1>CalendarMonth ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarMonth calls the given _calendar_'s `month()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Let _result_ be ? Invoke(_calendar_, *"month"*, « _dateLike_ »).
+        1. If _result_ is *undefined*, throw a *RangeError* exception.
+        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendarmonthcode" aoid="CalendarMonthCode">
+      <h1>CalendarMonthCode ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarMonthCode calls the given _calendar_'s `monthCode()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _dateLike_ »).
+        1. If _result_ is *undefined*, throw a *RangeError* exception.
+        1. Return ? ToString(_result_).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendarday" aoid="CalendarDay">
+      <h1>CalendarDay ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarDay calls the given _calendar_'s `day()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Let _result_ be ? Invoke(_calendar_, *"day"*, « _dateLike_ »).
+        1. If _result_ is *undefined*, throw a *RangeError* exception.
+        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendardayofweek" aoid="CalendarDayOfWeek">
+      <h1>CalendarDayOfWeek ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarDayOfWeek calls the given _calendar_'s `dayOfWeek()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"dayOfWeek"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendardayofyear" aoid="CalendarDayOfYear">
+      <h1>CalendarDayOfYear ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarDayOfYear calls the given _calendar_'s `dayOfYear()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"dayOfYear"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendarweekofyear" aoid="CalendarWeekOfYear">
+      <h1>CalendarWeekOfYear ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarWeekOfYear calls the given _calendar_'s `weekOfYear()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"weekOfYear"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendardaysinweek" aoid="CalendarDaysInWeek">
+      <h1>CalendarDaysInWeek ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarDaysInWeek calls the given _calendar_'s `daysInWeek()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"daysInWeek"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendardaysinmonth" aoid="CalendarDaysInMonth">
+      <h1>CalendarDaysInMonth ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarDaysInMonth calls the given _calendar_'s `daysInMonth()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"daysInMonth"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendardaysinyear" aoid="CalendarDaysInYear">
+      <h1>CalendarDaysInYear ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarDaysInYear calls the given _calendar_'s `daysInYear()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"daysInYear"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendarmonthsinyear" aoid="CalendarMonthsInYear">
+      <h1>CalendarMonthsInYear ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarMonthsInYear calls the given _calendar_'s `monthsInYear()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"monthsInYear"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
+    <emu-clause id="sec-temporal-calendarinleapyear" aoid="CalendarInLeapYear">
+      <h1>CalendarInLeapYear ( _calendar_, _dateLike_ )</h1>
+      <p>
+        The abstract operation CalendarInLeapYear calls the given _calendar_'s `inLeapYear()` method and validates the result.
+      </p>
+      <emu-alg>
+        1. Assert: Type(_calendar_) is Object.
+        1. Return ? Invoke(_calendar_, *"inLeapYear"*, « _dateLike_ »).
+      </emu-alg>
+    </emu-clause>
+
     <emu-clause id="sec-temporal-totemporalcalendar" aoid="ToTemporalCalendar">
       <h1>ToTemporalCalendar ( _temporalCalendarLike_ )</h1>
       <emu-alg>
diff --git a/spec/duration.html b/spec/duration.html
index 117820243f..d465b8d513 100644
--- a/spec/duration.html
+++ b/spec/duration.html
@@ -1155,7 +1155,7 @@ <h1>AddDuration ( _y1_, _mon1_, _w1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _
           1. Let _dateLargestUnit_ be ! LargerOfTwoTemporalDurationUnits(*"days"*, _largestUnit_).
           1. Let _differenceOptions_ be ! OrdinaryObjectCreate(%Object.prototype%).
           1. Perform ! CreateDataPropertyOrThrow(_differenceOptions_, *"largestUnit"*, _dateLargestUnit_).
-          1. Let _dateDifference_ be ? Invoke(_calendar_, *"dateUntil"*, « _datePart_, _end_, _differenceOptions_ »).
+          1. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _datePart_, _end_, _differenceOptions_).
           1. Let _result_ be ! BalanceDuration(_dateDifference_.[[Days]], _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_).
           1. Let _years_ be _dateDifference_.[[Years]].
           1. Let _months_ be _dateDifference_.[[Months]].
@@ -1236,7 +1236,7 @@ <h1>MoveRelativeDate ( _calendar_, _relativeTo_, _duration_ )</h1>
       </p>
       <emu-alg>
         1. Let _options_ be ! OrdinaryObjectCreate(%Object.prototype%).
-        1. Let _later_ be ? Invoke(_calendar_, *"dateAdd"*, « _relativeTo_, _duration_, _options_, %Temporal.PlainDate% »).
+        1. Let _later_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _duration_, _options_, %Temporal.PlainDate%).
         1. Let _days_ be ? DaysUntil(_relativeTo_, _later_).
         1. Let _dateTime_ be ? CreateTemporalDateTime(_later_.[[ISOYear]], _later_.[[ISOMonth]], _later_.[[ISODay]], _relativeTo_.[[ISOHour]], _relativeTo_.[[ISOMinute]], _relativeTo_.[[ISOSecond]], _relativeTo_.[[ISOMillisecond]], _relativeTo_.[[ISOMicrosecond]], _relativeTo_.[[ISONanosecond]], _relativeTo_.[[Calendar]]).
         1. Return the new Record {
diff --git a/spec/intl.html b/spec/intl.html
index 0c314ad42e..b2d825d012 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -1097,6 +1097,32 @@ <h1>IsBuiltinCalendar ( _id_ )</h1>
             1. Return *false*.
           </emu-alg>
         </emu-clause>
+
+        <emu-clause id="sec-temporal-calendarera" aoid="CalendarEra">
+          <h1>CalendarEra ( _calendar_, _dateLike_ )</h1>
+          <p>
+            The abstract operation CalendarEra calls the given _calendar_'s `era()` method and validates the result.
+          </p>
+          <emu-alg>
+            1. Assert: Type(_calendar_) is Object.
+            1. Let _result_ be ? Invoke(_calendar_, *"era"*, « _dateLike_ »).
+            1. If _result_ is not *undefined*, set _result_ to ? ToString(_result_).
+            1. Return _result_.
+          </emu-alg>
+        </emu-clause>
+
+        <emu-clause id="sec-temporal-calendarerayear" aoid="CalendarEraYear">
+          <h1>CalendarEraYear ( _calendar_, _dateLike_ )</h1>
+          <p>
+            The abstract operation CalendarEraYear calls the given _calendar_'s `eraYear()` method and validates the result.
+          </p>
+          <emu-alg>
+            1. Assert: Type(_calendar_) is Object.
+            1. Let _result_ be ? Invoke(_calendar_, *"eraYear"*, « _dateLike_ »).
+            1. If _result_ is not *undefined*, set _result_ to ? ToIntegerOrInfinity(_result_).
+            1. Return _result_.
+          </emu-alg>
+        </emu-clause>
       </emu-clause>
 
       <emu-clause id="sup-properties-of-the-temporal-calendar-prototype-object">
@@ -1542,10 +1568,7 @@ <h1>get Temporal.PlainDate.prototype.era</h1>
             1. Let _plainDate_ be the *this* value.
             1. Perform ? RequireInternalSlot(_plainDate_, [[InitializedTemporalDate]]).
             1. Let _calendar_ be _plainDate_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"era"*, « _plainDate_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToString(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEra(_calendar_, _plainDate_).
           </emu-alg>
         </emu-clause>
 
@@ -1559,10 +1582,7 @@ <h1>get Temporal.PlainDate.prototype.eraYear</h1>
             1. Let _plainDate_ be the *this* value.
             1. Perform ? RequireInternalSlot(_plainDate_, [[InitializedTemporalDate]]).
             1. Let _calendar_ be _plainDate_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"eraYear"*, « _plainDate_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToIntegerOrInfinity(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEraYear(_calendar_, _plainDate_).
           </emu-alg>
         </emu-clause>
       </emu-clause>
@@ -1594,10 +1614,7 @@ <h1>get Temporal.PlainDateTime.prototype.era</h1>
             1. Let _plainDateTime_ be the *this* value.
             1. Perform ? RequireInternalSlot(_plainDateTime_, [[InitializedTemporalDateTime]]).
             1. Let _calendar_ be _plainDateTime_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"era"*, « _plainDateTime_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToString(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEra(_calendar_, _plainDateTime_).
           </emu-alg>
         </emu-clause>
 
@@ -1611,10 +1628,7 @@ <h1>get Temporal.PlainDateTime.prototype.eraYear</h1>
             1. Let _plainDateTime_ be the *this* value.
             1. Perform ? RequireInternalSlot(_plainDateTime_, [[InitializedTemporalDateTime]]).
             1. Let _calendar_ be _plainDateTime_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"eraYear"*, « _plainDateTime_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToIntegerOrInfinity(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEraYear(_calendar_, _plainDateTime_).
           </emu-alg>
         </emu-clause>
       </emu-clause>
@@ -1682,10 +1696,7 @@ <h1>get Temporal.PlainYearMonth.prototype.era</h1>
             1. Let _plainYearMonth_ be the *this* value.
             1. Perform ? RequireInternalSlot(_plainYearMonth_, [[InitializedTemporalYearMonth]]).
             1. Let _calendar_ be _plainYearMonth_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"era"*, « _plainYearMonth_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToString(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEra(_calendar_, _plainYearMonth_).
           </emu-alg>
         </emu-clause>
 
@@ -1699,10 +1710,7 @@ <h1>get Temporal.PlainYearMonth.prototype.eraYear</h1>
             1. Let _plainYearMonth_ be the *this* value.
             1. Perform ? RequireInternalSlot(_plainYearMonth_, [[InitializedTemporalYearMonth]]).
             1. Let _calendar_ be _plainYearMonth_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"eraYear"*, « _plainYearMonth_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToIntegerOrInfinity(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEraYear(_calendar_, _plainYearMonth_).
           </emu-alg>
         </emu-clause>
       </emu-clause>
@@ -1737,10 +1745,7 @@ <h1>get Temporal.ZonedDateTime.prototype.era</h1>
             1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
             1. Let _plainDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
             1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-            1. Let _result_ be ? Invoke(_calendar_, *"era"*, « _plainDateTime_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToString(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEra(_calendar_, _plainDateTime_).
           </emu-alg>
         </emu-clause>
 
@@ -1757,10 +1762,7 @@ <h1>get Temporal.ZonedDateTime.prototype.eraYear</h1>
             1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
             1. Let _plainDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
             1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-            1. Let _result_ ? Invoke(_calendar_, *"eraYear"*, « _plainDateTime_ »).
-            1. If _result_ is not *undefined*, then
-              1. Set _result_ to ? ToIntegerOrInfinity(_result_).
-            1. Return _result_.
+            1. Return ? CalendarEraYear(_calendar_, _plainDateTime_).
           </emu-alg>
         </emu-clause>
       </emu-clause>
diff --git a/spec/plaindate.html b/spec/plaindate.html
index b8e1bc0113..06af623c5c 100644
--- a/spec/plaindate.html
+++ b/spec/plaindate.html
@@ -139,10 +139,7 @@ <h1>get Temporal.PlainDate.prototype.year</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"year"*, « _temporalDate_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToIntegerOrInfinity(_result_).
+        1. Return ? CalendarYear(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -156,10 +153,7 @@ <h1>get Temporal.PlainDate.prototype.month</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"month"*, « _temporalDate_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarMonth(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -173,10 +167,7 @@ <h1>get Temporal.PlainDate.prototype.monthCode</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _temporalDate_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToString(_result_).
+        1. Return ? CalendarMonthCode(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -190,10 +181,7 @@ <h1>get Temporal.PlainDate.prototype.day</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"day"*, « _temporalDate_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarDay(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -207,7 +195,7 @@ <h1>get Temporal.PlainDate.prototype.dayOfWeek</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"dayOfWeek"*, « _temporalDate_ »).
+        1. Return ? CalendarDayOfWeek(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -221,7 +209,7 @@ <h1>get Temporal.PlainDate.prototype.dayOfYear</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"dayOfYear"*, « _temporalDate_ »).
+        1. Return ? CalendarDayOfYear(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -235,7 +223,7 @@ <h1>get Temporal.PlainDate.prototype.weekOfYear</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"weekOfYear"*, « _temporalDate_ »).
+        1. Return ? CalendarWeekOfYear(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -249,7 +237,7 @@ <h1>get Temporal.PlainDate.prototype.daysInWeek</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInWeek"*, « _temporalDate_ »).
+        1. Return ? CalendarDaysInWeek(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -263,7 +251,7 @@ <h1>get Temporal.PlainDate.prototype.daysInMonth</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInMonth"*, « _temporalDate_ »).
+        1. Return ? CalendarDaysInMonth(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -277,7 +265,7 @@ <h1>get Temporal.PlainDate.prototype.daysInYear</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInYear"*, « _temporalDate_ »).
+        1. Return ? CalendarDaysInYear(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -291,7 +279,7 @@ <h1>get Temporal.PlainDate.prototype.monthsInYear</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"monthsInYear"*, « _temporalDate_ »).
+        1. Return ? CalendarMonthsInYear(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -305,7 +293,7 @@ <h1>get Temporal.PlainDate.prototype.inLeapYear</h1>
         1. Let _temporalDate_ be the *this* value.
         1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
         1. Let _calendar_ be _temporalDate_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"inLeapYear"*, « _temporalDate_ »).
+        1. Return ? CalendarInLeapYear(_calendar_, _temporalDate_).
       </emu-alg>
     </emu-clause>
 
@@ -370,7 +358,7 @@ <h1>Temporal.PlainDate.prototype.add ( _temporalDurationLike_ [ , _options_ ] )<
         1. Let _balanceResult_ be ? BalanceDuration(_duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], *"days"*).
         1. Set _options_ to ? NormalizeOptionsObject(_options_).
         1. Let _constructor_ be ? SpeciesConstructor(_temporalDate_, %Temporal.PlainDate%).
-        1. Return ? Invoke(_calendar_, *"dateAdd"*, « _temporalDate_, _duration_, _options_, _constructor_ »).
+        1. Return ? CalendarDateAdd(_calendar_, _temporalDate_, _duration_, _options_, _constructor_).
       </emu-alg>
     </emu-clause>
 
@@ -389,7 +377,7 @@ <h1>Temporal.PlainDate.prototype.subtract ( _temporalDurationLike_ [ , _options_
         1. Set _options_ to ? NormalizeOptionsObject(_options_).
         1. Let _negatedDuration_ be ? CreateTemporalDuration(−_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]]).
         1. Let _constructor_ be ? SpeciesConstructor(_temporalDate_, %Temporal.PlainDate%).
-        1. Return ? Invoke(_calendar_, *"dateAdd"*, « _temporalDate_, _negatedDuration_, _options_, _constructor_ »).
+        1. Return ? CalendarDateAdd(_calendar_, _temporalDate_, _negatedDuration_, _options_, _constructor_).
       </emu-alg>
     </emu-clause>
 
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index f7dd96c7f0..17ebf55404 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -147,10 +147,7 @@ <h1>get Temporal.PlainDateTime.prototype.year</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"year"*, « _dateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToIntegerOrInfinity(_result_).
+        1. Return ? CalendarYear(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -164,10 +161,7 @@ <h1>get Temporal.PlainDateTime.prototype.month</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"month"*, « _dateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarMonth(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -181,10 +175,7 @@ <h1>get Temporal.PlainDateTime.prototype.monthCode</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _dateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToString(_result_).
+        1. Return ? CalendarMonthCode(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -198,10 +189,7 @@ <h1>get Temporal.PlainDateTime.prototype.day</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"day"*, « _dateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarDay(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -293,7 +281,7 @@ <h1>get Temporal.PlainDateTime.prototype.dayOfWeek</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"dayOfWeek"*, « _dateTime_ »).
+        1. Return ? CalendarDayOfWeek(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -307,7 +295,7 @@ <h1>get Temporal.PlainDateTime.prototype.dayOfYear</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"dayOfYear"*, « _dateTime_ »).
+        1. Return ? CalendarDayOfYear(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -321,7 +309,7 @@ <h1>get Temporal.PlainDateTime.prototype.weekOfYear</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"weekOfYear"*, « _dateTime_ »).
+        1. Return ? CalendarWeekOfYear(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -335,7 +323,7 @@ <h1>get Temporal.PlainDateTime.prototype.daysInWeek</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInWeek"*, « _dateTime_ »).
+        1. Return ? CalendarDaysInWeek(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -349,7 +337,7 @@ <h1>get Temporal.PlainDateTime.prototype.daysInMonth</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInMonth"*, « _dateTime_ »).
+        1. Return ? CalendarDaysInMonth(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -363,7 +351,7 @@ <h1>get Temporal.PlainDateTime.prototype.daysInYear</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInYear"*, « _dateTime_ »).
+        1. Return ? CalendarDaysInYear(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -377,7 +365,7 @@ <h1>get Temporal.PlainDateTime.prototype.monthsInYear</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"monthsInYear"*, « _dateTime_ »).
+        1. Return ? CalendarMonthsInYear(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -391,7 +379,7 @@ <h1>get Temporal.PlainDateTime.prototype.inLeapYear</h1>
         1. Let _dateTime_ be the *this* value.
         1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
         1. Let _calendar_ be _dateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"inLeapYear"*, « _dateTime_ »).
+        1. Return ? CalendarInLeapYear(_calendar_, _dateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -1129,7 +1117,7 @@ <h1>AddDateTime ( _year_, _month_, _day_, _hour_, _minute_, _second_, _milliseco
         1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).
         1. Let _datePart_ be ? CreateTemporalDate(_year_, _month_, _day_, _calendar_).
         1. Let _dateDuration_ be ? CreateTemporalDuration(_years_, _months_, _weeks_, _days_ + _timeResult_.[[Days]]).
-        1. Let _addedDate_ be ? Invoke(_calendar_, *"dateAdd"*, « _datePart_, _dateDuration_, _options_, %Temporal.PlainDate% »).
+        1. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_, %Temporal.PlainDate%).
         1. Return the new Record {
             [[Year]]: _addedDate_.[[ISOYear]],
             [[Month]]: _addedDate_.[[ISOMonth]],
@@ -1181,7 +1169,7 @@ <h1>DifferenceDateTime ( _y1_, _mon1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_,
         1. Let _date2_ be ? CreateTemporalDate(_y2_, _mon2_, _d2_).
         1. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"days"*, _largestUnit_).
         1. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_).
-        1. Let _dateDifference_ be ? Invoke(_calendar_, *"dateUntil"*, « _date1_, _date2_, _untilOptions_ »).
+        1. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_).
         1. Return ? BalanceDuration(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _dateDifference_.[[Days]], _timeDifference_.[[Hours]], _timeDifference_.[[Minutes]], _timeDifference_.[[Seconds]], _timeDifference_.[[Milliseconds]], _timeDifference_.[[Microseconds]], _timeDifference_.[[Nanoseconds]], _largestUnit_).
       </emu-alg>
     </emu-clause>
diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html
index 53636a10ed..b0ee41eef1 100644
--- a/spec/plainmonthday.html
+++ b/spec/plainmonthday.html
@@ -127,9 +127,7 @@ <h1>get Temporal.PlainMonthDay.prototype.monthCode</h1>
         1. Let _monthDay_ be the *this* value.
         1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]).
         1. Let _calendar_ be _monthDay_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _monthDay_ »).
-        1. If _result_ is *undefined*, throw a *RangeError* exception.
-        1. Return ? ToString(_result_).
+        1. Return ? CalendarMonthCode(_calendar_, _monthDay_).
       </emu-alg>
     </emu-clause>
 
@@ -143,9 +141,7 @@ <h1>get Temporal.PlainMonthDay.prototype.day</h1>
         1. Let _monthDay_ be the *this* value.
         1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]).
         1. Let _calendar_ be _monthDay_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"day"*, « _monthDay_ »).
-        1. If _result_ is *undefined*, throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarDay(_calendar_, _monthDay_).
       </emu-alg>
     </emu-clause>
 
diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html
index 799ca82d65..5370bb823e 100644
--- a/spec/plainyearmonth.html
+++ b/spec/plainyearmonth.html
@@ -140,10 +140,7 @@ <h1>get Temporal.PlainYearMonth.prototype.year</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"year"*, « _yearMonth_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToIntegerOrInfinity(_result_).
+        1. Return ? CalendarYear(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -157,10 +154,7 @@ <h1>get Temporal.PlainYearMonth.prototype.month</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"month"*, « _yearMonth_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarMonth(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -174,10 +168,7 @@ <h1>get Temporal.PlainYearMonth.prototype.monthCode</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _yearMonth_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToString(_result_).
+        1. Return ? CalendarMonthCode(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -191,7 +182,7 @@ <h1>get Temporal.PlainYearMonth.prototype.daysInYear</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInYear"*, « _yearMonth_ »).
+        1. Return ? CalendarDaysInYear(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -205,7 +196,7 @@ <h1>get Temporal.PlainYearMonth.prototype.daysInMonth</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInMonth"*, « _yearMonth_ »).
+        1. Return ? CalendarDaysInMonth(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -219,7 +210,7 @@ <h1>get Temporal.PlainYearMonth.prototype.monthsInYear</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"monthsInYear"*, « _yearMonth_ »).
+        1. Return ? CalendarMonthsInYear(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -233,7 +224,7 @@ <h1>get Temporal.PlainYearMonth.prototype.inLeapYear</h1>
         1. Let _yearMonth_ be the *this* value.
         1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
         1. Let _calendar_ be _yearMonth_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"inLeapYear"*, « _yearMonth_ »).
+        1. Return ? CalendarInLeapYear(_calendar_, _yearMonth_).
       </emu-alg>
     </emu-clause>
 
@@ -282,7 +273,7 @@ <h1>Temporal.PlainYearMonth.prototype.add ( _temporalDurationLike_ [ , _options_
         1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »).
         1. Let _sign_ be ! DurationSign(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], 0, 0, 0, 0, 0, 0).
         1. If _sign_ &lt; 0, then
-          1. Let _day_ be ? Invoke(_calendar_, *"daysInMonth"*, « _yearMonth_ »).
+          1. Let _day_ be ? CalendarDaysInMonth(_calendar_, _yearMonth_).
         1. Else,
           1. Let _day_ be 1.
         1. Let _date_ be ? CreateTemporalDate(_yearMonth_.[[ISOYear]], _yearMonth_.[[ISOMonth]], _day_, _calendar_).
@@ -311,7 +302,7 @@ <h1>Temporal.PlainYearMonth.prototype.subtract ( _temporalDurationLike_ [ , _opt
         1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »).
         1. Let _sign_ be ! DurationSign(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], 0, 0, 0, 0, 0, 0).
         1. If _sign_ &lt; 0, then
-          1. Let _day_ be ? Invoke(_calendar_, *"daysInMonth"*, « _yearMonth_ »).
+          1. Let _day_ be ? CalendarDaysInMonth(_calendar_, _yearMonth_).
         1. Else,
           1. Let _day_ be 1.
         1. Let _date_ be ? CreateTemporalDate(_yearMonth_.[[ISOYear]], _yearMonth_.[[ISOMonth]], _day_, _calendar_).
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 9dc3e27db6..670a151b89 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -163,10 +163,7 @@ <h1>get Temporal.ZonedDateTime.prototype.year</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"year"*, « _temporalDateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToIntegerOrInfinity(_result_).
+        1. Return ? CalendarYear(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -183,10 +180,7 @@ <h1>get Temporal.ZonedDateTime.prototype.month</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"month"*, « _temporalDateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarMonth(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -203,10 +197,7 @@ <h1>get Temporal.ZonedDateTime.prototype.monthCode</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _temporalDateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToString(_result_).
+        1. Return ? CalendarMonthCode(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -223,10 +214,7 @@ <h1>get Temporal.ZonedDateTime.prototype.day</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Let _result_ be ? Invoke(_calendar_, *"day"*, « _temporalDateTime_ »).
-        1. If _result_ is *undefined*, then
-          1. Throw a *RangeError* exception.
-        1. Return ? ToPositiveIntegerOrInfinity(_result_).
+        1. Return ? CalendarDay(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -397,7 +385,7 @@ <h1>get Temporal.ZonedDateTime.prototype.dayOfWeek</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"dayOfWeek"*, « _temporalDateTime_ »).
+        1. Return ? CalendarDayOfWeek(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -414,7 +402,7 @@ <h1>get Temporal.ZonedDateTime.prototype.dayOfYear</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"dayOfYear"*, « _temporalDateTime_ »).
+        1. Return ? CalendarDayOfYear(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -431,7 +419,7 @@ <h1>get Temporal.ZonedDateTime.prototype.weekOfYear</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"weekOfYear"*, « _temporalDateTime_ »).
+        1. Return ? CalendarWeekOfYear(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -474,7 +462,7 @@ <h1>get Temporal.ZonedDateTime.prototype.daysInWeek</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInWeek"*, « _temporalDateTime_ »).
+        1. Return ? CalendarDaysInWeek(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -491,7 +479,7 @@ <h1>get Temporal.ZonedDateTime.prototype.daysInMonth</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInMonth"*, « _temporalDateTime_ »).
+        1. Return ? CalendarDaysInMonth(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -508,7 +496,7 @@ <h1>get Temporal.ZonedDateTime.prototype.daysInYear</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"daysInYear"*, « _temporalDateTime_ »).
+        1. Return ? CalendarDaysInYear(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -525,7 +513,7 @@ <h1>get Temporal.ZonedDateTime.prototype.monthsInYear</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"monthsInYear"*, « _temporalDateTime_ »).
+        1. Return ? CalendarMonthsInYear(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -542,7 +530,7 @@ <h1>get Temporal.ZonedDateTime.prototype.inLeapYear</h1>
         1. Let _instant_ be ? CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_).
         1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
-        1. Return ? Invoke(_calendar_, *"inLeapYear"*, « _temporalDateTime_ »).
+        1. Return ? CalendarInLeapYear(_calendar_, _temporalDateTime_).
       </emu-alg>
     </emu-clause>
 
@@ -981,8 +969,7 @@ <h1>Temporal.ZonedDateTime.prototype.toPlainYearMonth ( )</h1>
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_, _calendar_).
         1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"monthCode"*, *"year"* »).
         1. Let _fields_ be ? ToTemporalYearMonthFields(_temporalDateTime_, _fieldNames_).
-        1. Let _options_ be ? OrdinaryObjectCreate(%Object.prototype%).
-        1. Return ? Invoke(_calendar_, *"yearMonthFromFields"*, « _fields_, _options_, %Temporal.PlainMonthDay% »).
+        1. Return ? YearMonthFromFields(_calendar_, _fields_, %Temporal.PlainMonthDay%).
       </emu-alg>
     </emu-clause>
 
@@ -1000,8 +987,7 @@ <h1>Temporal.ZonedDateTime.prototype.toPlainMonthDay ( )</h1>
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_, _calendar_).
         1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"monthCode"* »).
         1. Let _fields_ be ? ToTemporalMonthDayFields(_temporalDateTime_, _fieldNames_).
-        1. Let _options_ be ? OrdinaryObjectCreate(%Object.prototype%).
-        1. Return ? Invoke(_calendar_, *"monthDayFromFields"*, « _fields_, _options_, %Temporal.PlainMonthDay% »).
+        1. Return ? MonthDayFromFields(_calendar_, _fields_, %Temporal.PlainMonthDay%).
       </emu-alg>
     </emu-clause>
 
@@ -1285,7 +1271,7 @@ <h1>AddZonedDateTime ( _epochNanoseconds_, _timeZone_, _calendar_, _years_, _mon
         1. Let _temporalDateTime_ be ? GetTemporalDateTimeFor(_timeZone_, _instant_, _calendar_).
         1. Let _datePart_ be ? CreateTemporalDate(_temporalDateTime_.[[ISOYear]], _temporalDateTime_.[[ISOMonth]], _temporalDateTime_.[[ISODay]], _calendar_).
         1. Let _dateDuration_ be ? CreateTemporalDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0).
-        1. Let _addedDate_ be ? Invoke(_calendar_, *"dateAdd"*, « _dateDuration_, _options_, %Temporal.PlainDate% »).
+        1. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _dateDuration_, _options_, %Temporal.PlainDate%).
         1. Let _intermediateDateTime_ be ? CreateTemporalDateTime(_addedDate_.[[ISOYear]], _addedDate_.[[ISOMonth]], _addedDate_.[[ISODay]], _temporalDateTime_.[[ISOHour]], _temporalDateTime_.[[ISOMinute]], _temporalDateTime_.[[ISOSecond]], _temporalDateTime_.[[ISOMillisecond]], _temporalDateTime_.[[ISOMicrosecond]], _temporalDateTime_.[[ISONanosecond]], _calendar_).
         1. Let _intermediateInstant_ be ? GetTemporalInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*).
         1. Return ! AddInstant(_intermediateInstant_.[[Nanoseconds]], _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).