Skip to content

Commit

Permalink
Add internal create operations to avoid observable effects
Browse files Browse the repository at this point in the history
The constructors of PlainDate, PlainDateTime, PlainMonthDay,
PlainYearMonth, and ZonedDateTime call ToTemporalCalendar on the calendar
argument, and the constructor of ZonedDateTime additionally calls
ToTemporalTimeZone on its timeZone argument. Now that these operations
include an observable HasProperty operation, we do not want to call them
more than once on the same calendar or time zone object.

Therefore we add CreateTemporalDate etc. which create an instance without
any observable validation of the arguments.

The spec text already works like this, with abstract operations such as
CreateTemporalZonedDateTime and friends that do not call
ToTemporalCalendar or ToTemporalTimeZone. So this is not a normative
change; it's a compliance bug in the polyfill. It is required for the
test262 tests in 19cd26f to pass, which observe HasProperty(`timeZone`)
operations.

See: #1428
  • Loading branch information
ptomato committed Apr 16, 2021
1 parent 44525f5 commit 12dab2e
Show file tree
Hide file tree
Showing 10 changed files with 478 additions and 429 deletions.
24 changes: 8 additions & 16 deletions polyfill/lib/calendar.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,15 @@ impl['iso8601'] = {
fields = resolveNonLunisolarMonth(fields);
let { year, month, day } = fields;
({ year, month, day } = ES.RegulateISODate(year, month, day, overflow));
const TemporalPlainDate = GetIntrinsic('%Temporal.PlainDate%');
return new TemporalPlainDate(year, month, day, calendar);
return ES.CreateTemporalDate(year, month, day, calendar);
},
yearMonthFromFields(fields, options, calendar) {
const overflow = ES.ToTemporalOverflow(options);
fields = ES.PrepareTemporalFields(fields, [['month', undefined], ['monthCode', undefined], ['year']]);
fields = resolveNonLunisolarMonth(fields);
let { year, month } = fields;
({ year, month } = ES.RegulateISOYearMonth(year, month, overflow));
const TemporalPlainYearMonth = GetIntrinsic('%Temporal.PlainYearMonth%');
return new TemporalPlainYearMonth(year, month, calendar, /* referenceISODay */ 1);
return ES.CreateTemporalYearMonth(year, month, calendar, /* referenceISODay = */ 1);
},
monthDayFromFields(fields, options, calendar) {
const overflow = ES.ToTemporalOverflow(options);
Expand All @@ -207,8 +205,7 @@ impl['iso8601'] = {
fields = resolveNonLunisolarMonth(fields);
let { month, day, year } = fields;
({ month, day } = ES.RegulateISODate(useYear ? year : referenceISOYear, month, day, overflow));
const TemporalPlainMonthDay = GetIntrinsic('%Temporal.PlainMonthDay%');
return new TemporalPlainMonthDay(month, day, calendar, referenceISOYear);
return ES.CreateTemporalMonthDay(month, day, calendar, referenceISOYear);
},
fields(fields) {
return fields;
Expand All @@ -228,8 +225,7 @@ impl['iso8601'] = {
let month = GetSlot(date, ISO_MONTH);
let day = GetSlot(date, ISO_DAY);
({ year, month, day } = ES.AddISODate(year, month, day, years, months, weeks, days, overflow));
const TemporalPlainDate = GetIntrinsic('%Temporal.PlainDate%');
return new TemporalPlainDate(year, month, day, calendar);
return ES.CreateTemporalDate(year, month, day, calendar);
},
dateUntil(one, two, largestUnit) {
return ES.DifferenceISODate(
Expand Down Expand Up @@ -1782,8 +1778,7 @@ const nonIsoGeneralImpl = {
['year', undefined]
]);
const { year, month, day } = this.helper.calendarToIsoDate(fields, overflow, cache);
const TemporalPlainDate = GetIntrinsic('%Temporal.PlainDate%');
const result = new TemporalPlainDate(year, month, day, calendar);
const result = ES.CreateTemporalDate(year, month, day, calendar);
cache.setObject(result);
return result;
},
Expand All @@ -1799,8 +1794,7 @@ const nonIsoGeneralImpl = {
['year', undefined]
]);
const { year, month, day } = this.helper.calendarToIsoDate({ ...fields, day: 1 }, overflow, cache);
const TemporalPlainYearMonth = GetIntrinsic('%Temporal.PlainYearMonth%');
const result = new TemporalPlainYearMonth(year, month, calendar, /* referenceISODay = */ day);
const result = ES.CreateTemporalYearMonth(year, month, calendar, /* referenceISODay = */ day);
cache.setObject(result);
return result;
},
Expand All @@ -1821,8 +1815,7 @@ const nonIsoGeneralImpl = {
]);
const { year, month, day } = this.helper.monthDayFromFields(fields, overflow, cache);
// `year` is a reference year where this month/day exists in this calendar
const TemporalPlainMonthDay = GetIntrinsic('%Temporal.PlainMonthDay%');
const result = new TemporalPlainMonthDay(month, day, calendar, /* referenceISOYear */ year);
const result = ES.CreateTemporalMonthDay(month, day, calendar, /* referenceISOYear = */ year);
cache.setObject(result);
return result;
},
Expand Down Expand Up @@ -1857,8 +1850,7 @@ const nonIsoGeneralImpl = {
const added = this.helper.addCalendar(calendarDate, { years, months, weeks, days }, overflow, cache);
const isoAdded = this.helper.calendarToIsoDate(added, 'constrain', cache);
const { year, month, day } = isoAdded;
const TemporalPlainDate = GetIntrinsic('%Temporal.PlainDate%');
const newTemporalObject = new TemporalPlainDate(year, month, day, calendar);
const newTemporalObject = ES.CreateTemporalDate(year, month, day, calendar);
// The new object's cache starts with the cache of the old object
const newCache = new OneObjectCache(cache);
newCache.setObject(newTemporalObject);
Expand Down
Loading

0 comments on commit 12dab2e

Please sign in to comment.