Skip to content

Commit 5e0c619

Browse files
committed
Normative: Look up calendar methods only once
Introduce a new spec type, Calendar Record, which stores a calendar object's dateAdd, dateFromFields, and dateUntil methods once they have been observably looked up. The record is passed around into abstract operations instead of the calendar object itself. These three are the only methods that are called more than once within the same API call. Others are called only once and can be looked up as needed. This is a large commit but most of it is mechanical replacement of Temporal.Calendar variables with Calendar Record variables.
1 parent 1eee9e6 commit 5e0c619

File tree

9 files changed

+606
-349
lines changed

9 files changed

+606
-349
lines changed

polyfill/lib/duration.mjs

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import * as ES from './ecmascript.mjs';
44
import { MakeIntrinsicClass } from './intrinsicclass.mjs';
5+
import { MethodRecord } from './methodrecord.mjs';
56
import {
67
YEARS,
78
MONTHS,
@@ -308,13 +309,40 @@ export class Duration {
308309
plainRelativeTo = ES.TemporalDateTimeToDate(dt);
309310
}
310311

312+
let calendar, calendarRec;
313+
if (zonedRelativeTo) {
314+
calendar = GetSlot(zonedRelativeTo, CALENDAR);
315+
} else if (plainRelativeTo) {
316+
calendar = GetSlot(plainRelativeTo, CALENDAR);
317+
}
318+
if (calendar) {
319+
calendarRec = new MethodRecord(calendar);
320+
if (
321+
years !== 0 ||
322+
months !== 0 ||
323+
weeks !== 0 ||
324+
largestUnit === 'year' ||
325+
largestUnit === 'month' ||
326+
largestUnit === 'week' ||
327+
smallestUnit === 'year' ||
328+
smallestUnit === 'month' ||
329+
smallestUnit === 'week'
330+
) {
331+
calendarRec.lookup('dateAdd');
332+
}
333+
if (largestUnit === 'year' || (largestUnit === 'month' && years !== 0) || smallestUnit === 'year') {
334+
calendarRec.lookup('dateUntil');
335+
}
336+
}
337+
311338
({ years, months, weeks, days } = ES.UnbalanceDurationRelative(
312339
years,
313340
months,
314341
weeks,
315342
days,
316343
largestUnit,
317-
plainRelativeTo
344+
plainRelativeTo,
345+
calendarRec
318346
));
319347
({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
320348
ES.RoundDuration(
@@ -332,6 +360,7 @@ export class Duration {
332360
smallestUnit,
333361
roundingMode,
334362
plainRelativeTo,
363+
calendarRec,
335364
zonedRelativeTo,
336365
timeZoneRec
337366
));
@@ -352,6 +381,7 @@ export class Duration {
352381
smallestUnit,
353382
roundingMode,
354383
zonedRelativeTo,
384+
calendarRec,
355385
timeZoneRec
356386
));
357387
}
@@ -373,7 +403,8 @@ export class Duration {
373403
weeks,
374404
days,
375405
largestUnit,
376-
plainRelativeTo
406+
plainRelativeTo,
407+
calendarRec
377408
));
378409

379410
return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
@@ -417,12 +448,36 @@ export class Duration {
417448
plainRelativeTo = ES.TemporalDateTimeToDate(dt);
418449
}
419450

451+
let calendar, calendarRec;
452+
if (zonedRelativeTo) {
453+
calendar = GetSlot(zonedRelativeTo, CALENDAR);
454+
} else if (plainRelativeTo) {
455+
calendar = GetSlot(plainRelativeTo, CALENDAR);
456+
}
457+
if (calendar) {
458+
calendarRec = new MethodRecord(calendar);
459+
if (years !== 0 || months !== 0 || weeks !== 0 || unit === 'year' || unit === 'month' || unit === 'week') {
460+
calendarRec.lookup('dateAdd');
461+
}
462+
if (unit === 'year' || (unit === 'month' && years !== 0)) {
463+
calendarRec.lookup('dateUntil');
464+
}
465+
}
466+
420467
// Convert larger units down to days
421-
({ years, months, weeks, days } = ES.UnbalanceDurationRelative(years, months, weeks, days, unit, plainRelativeTo));
468+
({ years, months, weeks, days } = ES.UnbalanceDurationRelative(
469+
years,
470+
months,
471+
weeks,
472+
days,
473+
unit,
474+
plainRelativeTo,
475+
calendarRec
476+
));
422477
// If the unit we're totalling is smaller than `days`, convert days down to that unit.
423478
let intermediate;
424479
if (zonedRelativeTo) {
425-
intermediate = ES.MoveRelativeZonedDateTime(zonedRelativeTo, timeZoneRec, years, months, weeks, 0);
480+
intermediate = ES.MoveRelativeZonedDateTime(zonedRelativeTo, calendarRec, timeZoneRec, years, months, weeks, 0);
426481
}
427482
let balanceResult = ES.BalancePossiblyInfiniteDuration(
428483
days,
@@ -458,6 +513,7 @@ export class Duration {
458513
unit,
459514
'trunc',
460515
plainRelativeTo,
516+
calendarRec,
461517
zonedRelativeTo,
462518
timeZoneRec
463519
);
@@ -550,15 +606,20 @@ export class Duration {
550606

551607
const calendarUnitsPresent = y1 !== 0 || y2 !== 0 || mon1 !== 0 || mon2 !== 0 || w1 !== 0 || w2 !== 0;
552608

609+
let calendarRec;
610+
if (relativeTo) {
611+
calendarRec = new MethodRecord(GetSlot(relativeTo, CALENDAR));
612+
if (calendarUnitsPresent) calendarRec.lookup('dateAdd');
613+
}
614+
553615
if (ES.IsTemporalZonedDateTime(relativeTo) && (calendarUnitsPresent || d1 != 0 || d2 !== 0)) {
554616
const instant = GetSlot(relativeTo, INSTANT);
555-
const calendar = GetSlot(relativeTo, CALENDAR);
556-
const precalculatedDateTime = ES.GetPlainDateTimeFor(timeZoneRec, instant, calendar);
617+
const precalculatedDateTime = ES.GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.receiver);
557618

558619
const after1 = ES.AddZonedDateTime(
559620
instant,
560621
timeZoneRec,
561-
calendar,
622+
calendarRec,
562623
y1,
563624
mon1,
564625
w1,
@@ -574,7 +635,7 @@ export class Duration {
574635
const after2 = ES.AddZonedDateTime(
575636
instant,
576637
timeZoneRec,
577-
calendar,
638+
calendarRec,
578639
y2,
579640
mon2,
580641
w2,
@@ -592,8 +653,8 @@ export class Duration {
592653

593654
if (calendarUnitsPresent) {
594655
// relativeTo is PlainDate or undefined
595-
({ days: d1 } = ES.UnbalanceDurationRelative(y1, mon1, w1, d1, 'day', relativeTo));
596-
({ days: d2 } = ES.UnbalanceDurationRelative(y2, mon2, w2, d2, 'day', relativeTo));
656+
({ days: d1 } = ES.UnbalanceDurationRelative(y1, mon1, w1, d1, 'day', relativeTo, calendarRec));
657+
({ days: d2 } = ES.UnbalanceDurationRelative(y2, mon2, w2, d2, 'day', relativeTo, calendarRec));
597658
}
598659
ns1 = ES.TotalDurationNanoseconds(d1, h1, min1, s1, ms1, µs1, ns1);
599660
ns2 = ES.TotalDurationNanoseconds(d2, h2, min2, s2, ms2, µs2, ns2);

0 commit comments

Comments
 (0)