Skip to content

Commit

Permalink
Fix optimization to reuse GetMethod results for CalendarDateAdd and C…
Browse files Browse the repository at this point in the history
…alendarDateUntil.

Previous optimizations had the effect of removing checks for internal slots on
returned values by bypassing CalendarDateAdd and CalendarDateUntil. This fixes
those bugs.

See: #1424
  • Loading branch information
cjtenny committed Apr 17, 2021
1 parent f520803 commit 040bc09
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 37 deletions.
61 changes: 42 additions & 19 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1724,14 +1724,18 @@ export const ES = ObjectAssign({}, ES2020, {
if (mergeFields === undefined) return { ...fields, ...additionalFields };
return ES.Call(mergeFields, calendar, [fields, additionalFields]);
},
CalendarDateAdd: (calendar, date, duration, options) => {
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
CalendarDateAdd: (calendar, date, duration, options, dateAdd) => {
if (dateAdd === undefined) {
dateAdd = ES.GetMethod(calendar, 'dateAdd');
}
const result = ES.Call(dateAdd, calendar, [date, duration, options]);
if (!ES.IsTemporalDate(result)) throw new TypeError('invalid result');
return result;
},
CalendarDateUntil: (calendar, date, otherDate, options) => {
const dateUntil = ES.GetMethod(calendar, 'dateUntil');
CalendarDateUntil: (calendar, date, otherDate, options, dateUntil) => {
if (dateUntil === undefined) {
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;
Expand Down Expand Up @@ -2848,10 +2852,11 @@ export const ES = ObjectAssign({}, ES2020, {
const dateUntil = ES.GetMethod(calendar, 'dateUntil');
while (MathAbs(years) > 0) {
const addOptions = ObjectCreate(null);
const newRelativeTo = ES.Call(dateAdd, calendar, [relativeTo, oneYear, addOptions]);
const newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, addOptions, dateAdd);
const untilOptions = ObjectCreate(null);
untilOptions.largestUnit = 'months';
const oneYearMonths = ES.Call(dateUntil, calendar, [relativeTo, newRelativeTo, untilOptions]).months;
const oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil)
.months;
relativeTo = newRelativeTo;
months += oneYearMonths;
years -= sign;
Expand Down Expand Up @@ -2952,19 +2957,19 @@ export const ES = ObjectAssign({}, ES2020, {
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
const dateUntil = ES.GetMethod(calendar, 'dateUntil');
const addOptions = ObjectCreate(null);
newRelativeTo = ES.Call(dateAdd, calendar, [relativeTo, oneYear, addOptions]);
newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, addOptions, dateAdd);
const untilOptions = ObjectCreate(null);
untilOptions.largestUnit = 'months';
let oneYearMonths = ES.Call(dateUntil, calendar, [relativeTo, newRelativeTo, untilOptions]).months;
let oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil).months;
while (MathAbs(months) >= MathAbs(oneYearMonths)) {
months -= oneYearMonths;
years += sign;
relativeTo = newRelativeTo;
const addOptions = ObjectCreate(null);
newRelativeTo = ES.Call(dateAdd, calendar, [relativeTo, oneYear, addOptions]);
newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, addOptions, dateAdd);
const untilOptions = ObjectCreate(null);
untilOptions.largestUnit = 'months';
oneYearMonths = ES.Call(dateUntil, calendar, [relativeTo, newRelativeTo, untilOptions]).months;
oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil).months;
}
break;
}
Expand Down Expand Up @@ -3526,11 +3531,11 @@ export const ES = ObjectAssign({}, ES2020, {
);
const dateDuration1 = new TemporalDuration(y1, mon1, w1, d1, 0, 0, 0, 0, 0, 0);
const dateDuration2 = new TemporalDuration(y2, mon2, w2, d2, 0, 0, 0, 0, 0, 0);
const dateAdd = calendar.dateAdd;
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
const firstAddOptions = ObjectCreate(null);
const intermediate = ES.Call(dateAdd, calendar, [datePart, dateDuration1, firstAddOptions]);
const intermediate = ES.CalendarDateAdd(calendar, datePart, dateDuration1, firstAddOptions, dateAdd);
const secondAddOptions = ObjectCreate(null);
const end = ES.Call(dateAdd, calendar, [intermediate, dateDuration2, secondAddOptions]);
const end = ES.CalendarDateAdd(calendar, intermediate, dateDuration2, secondAddOptions, dateAdd);

const dateLargestUnit = ES.LargerOfTwoTemporalDurationUnits('days', largestUnit);
const differenceOptions = ObjectCreate(null);
Expand Down Expand Up @@ -4079,23 +4084,35 @@ export const ES = ObjectAssign({}, ES2020, {
// relativeTo + years, relativeTo + { years, months, weeks })
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
const firstAddOptions = ObjectCreate(null);
const yearsLater = ES.Call(dateAdd, calendar, [relativeTo, new TemporalDuration(years), firstAddOptions]);
const yearsLater = ES.CalendarDateAdd(
calendar,
relativeTo,
new TemporalDuration(years),
firstAddOptions,
dateAdd
);
const yearsMonthsWeeks = new TemporalDuration(years, months, weeks);
const secondAddOptions = ObjectCreate(null);
const yearsMonthsWeeksLater = ES.Call(dateAdd, calendar, [relativeTo, yearsMonthsWeeks, secondAddOptions]);
const yearsMonthsWeeksLater = ES.CalendarDateAdd(
calendar,
relativeTo,
yearsMonthsWeeks,
secondAddOptions,
dateAdd
);
const monthsWeeksInDays = ES.DaysUntil(yearsLater, yearsMonthsWeeksLater);
relativeTo = yearsLater;
days += monthsWeeksInDays;

const thirdAddOptions = ObjectCreate(null);
const daysLater = ES.Call(dateAdd, calendar, [relativeTo, { days }, thirdAddOptions]);
const daysLater = ES.CalendarDateAdd(calendar, relativeTo, { days }, thirdAddOptions, dateAdd);
const untilOptions = ObjectCreate(null);
untilOptions.largestUnit = 'years';
const yearsPassed = ES.CalendarDateUntil(calendar, relativeTo, daysLater, untilOptions).years;
years += yearsPassed;
const oldRelativeTo = relativeTo;
const fourthAddOptions = ObjectCreate(null);
relativeTo = ES.Call(dateAdd, calendar, [relativeTo, { years: yearsPassed }, fourthAddOptions]);
relativeTo = ES.CalendarDateAdd(calendar, relativeTo, { years: yearsPassed }, fourthAddOptions);
const daysPassed = ES.DaysUntil(oldRelativeTo, relativeTo);
days -= daysPassed;
const oneYear = new TemporalDuration(days < 0 ? -1 : 1);
Expand Down Expand Up @@ -4124,10 +4141,16 @@ export const ES = ObjectAssign({}, ES2020, {
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
const yearsMonths = new TemporalDuration(years, months);
const firstAddOptions = ObjectCreate(null);
const yearsMonthsLater = ES.Call(dateAdd, calendar, [relativeTo, yearsMonths, firstAddOptions]);
const yearsMonthsLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonths, firstAddOptions, dateAdd);
const yearsMonthsWeeks = new TemporalDuration(years, months, weeks);
const secondAddOptions = ObjectCreate(null);
const yearsMonthsWeeksLater = ES.Call(dateAdd, calendar, [relativeTo, yearsMonthsWeeks, secondAddOptions]);
const yearsMonthsWeeksLater = ES.CalendarDateAdd(
calendar,
relativeTo,
yearsMonthsWeeks,
secondAddOptions,
dateAdd
);
const weeksInDays = ES.DaysUntil(yearsMonthsLater, yearsMonthsWeeksLater);
relativeTo = yearsMonthsLater;
days += weeksInDays;
Expand Down
12 changes: 8 additions & 4 deletions spec/calendar.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,24 @@ <h1>CalendarMergeFields ( _calendar_, _fields_, _additionalFields_ )</h1>
</emu-clause>

<emu-clause id="sec-temporal-calendardateadd" aoid="CalendarDateAdd">
<h1>CalendarDateAdd ( _calendar_, _date_, _duration_ [ , _options_ ] )</h1>
<h1>CalendarDateAdd ( _calendar_, _date_, _duration_, _options_ [ , _dateAdd_ ] )</h1>
<emu-alg>
1. Assert: Type(_calendar_) is Object.
1. Let _addedDate_ be ? Invoke( _calendar_, *"dateAdd"*, « _date_, _duration_, _options_ »).
1. If _dateAdd_ is *undefined*, then
1. Set _dateAdd_ to ? GetMethod(_calendar_, *"dateAdd"*).
1. Let _addedDate_ be ? Call(_dateAdd_, _calendar_, « _date_, _duration_, _options_ »).
1. Perform ? RequireInternalSlot(_addedDate_, [[InitializedTemporalDate]]).
1. Return _addedDate_.
</emu-alg>
</emu-clause>

<emu-clause id="sec-temporal-calendardateuntil" aoid="CalendarDateUntil">
<h1>CalendarDateUntil ( _calendar_, _one_, _two_, _options_ )</h1>
<h1>CalendarDateUntil ( _calendar_, _one_, _two_, _options_ [ , _dateUntil_ ] )</h1>
<emu-alg>
1. Assert: Type(_calendar_) is Object.
1. Let _duration_ be ? Invoke(_calendar_, *"dateUntil"*, « _one_, _two_, _options_ »).
1. If _dateUntil_ is *undefined*, then
1. Set _dateUntil_ to ? GetMethod(_calendar_, *"dateUntil"*).
1. Let _duration_ be ? Call(_dateUntil_, _calendar_, « _one_, _two_, _options_ »).
1. Perform ? RequireInternalSlot(_duration_, [[InitializedTemporalDuration]]).
1. Return _duration_.
</emu-alg>
Expand Down
28 changes: 14 additions & 14 deletions spec/duration.html
Original file line number Diff line number Diff line change
Expand Up @@ -939,10 +939,10 @@ <h1>UnbalanceDurationRelative ( _years_, _months_, _weeks_, _days_, _largestUnit
1. Let _dateUntil_ be ? GetMethod(_calendar_, *"dateUntil"*).
1. Repeat, while abs(_years_) &gt; 0,
1. Let _addOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _newRelativeTo_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _oneYear_, _addOptions_ »).
1. Let _newRelativeTo_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _oneYear_, _addOptions_, _dateAdd_).
1. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*).
1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"months"*).
1. Let _untilResult_ be ? Call(_dateUntil_, _calendar_, « _relativeTo_, _newRelativeTo_, _untilOptions_ »).
1. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_).
1. Let _oneYearMonths_ be ? Get(_untilResult_, *"months"*).
1. Set _relativeTo_ to _newRelativeTo_.
1. Set _years_ to _years__sign_.
Expand Down Expand Up @@ -1035,20 +1035,20 @@ <h1>BalanceDurationRelative ( _years_, _months_, _weeks_, _days_, _largestUnit_,
1. Set _relativeTo_ to _moveResult_.[[RelativeTo]].
1. Set _oneMonthDays_ to _moveResult_.[[Days]].
1. Let _addOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _newRelativeTo_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _oneYear_, _addOptions_ »).
1. Let _newRelativeTo_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _oneYear_, _addOptions_, _dateAdd_).
1. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*).
1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"months"*).
1. Let _untilResult_ be ? Call(_dateUntil_, _calendar_, « _relativeTo_, _newRelativeTo_, _untilOptions_ »).
1. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_).
1. Let _oneYearMonths_ be ? Get(_untilResult_, *"months"*).
1. Repeat, while abs(_months_) ≥ abs(_oneYearMonths_),
1. Set _months_ to _months__oneYearMonths_.
1. Set _years_ to _years_ + _sign_.
1. Set _relativeTo_ to _newRelativeTo_.
1. Let _addOptions_ be ! OrdinaryObjectCreate(*null*).
1. Set _newRelativeTo_ to ? Call(_dateAdd_, _calendar_, « _relativeTo_, _oneYear_, _addOptions_ »).
1. Set _newRelativeTo_ to ? CalendarDateAdd(_calendar_, _relativeTo_, _oneYear_, _addOptions_, _dateAdd_).
1. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*).
1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"months"*).
1. Set _untilResult_ to ? Call(_dateUntil_, _calendar_, « _relativeTo_, _newRelativeTo_, _untilOptions_ »).
1. Set _untilResult_ to ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_).
1. Set _oneYearMonths_ to ? Get(_untilResult_, *"months"*).
1. Else if _largestUnit_ is *"months"*, then
1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo, _oneMonth_).
Expand Down Expand Up @@ -1111,9 +1111,9 @@ <h1>AddDuration ( _y1_, _mon1_, _w1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _
1. Let _dateDuration2_ be ? CreateTemporalDuration(_y2_, _mon2_, _w2_, _d2_, 0, 0, 0, 0, 0, 0).
1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*).
1. Let _firstAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _intermediate_ be ? Call(_dateAdd_, _calendar_, « _datePart_, _dateDuration1_, _firstAddOptions_ »).
1. Let _intermediate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration1_, _firstAddOptions_, _dateAdd_).
1. Let _secondAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _end_ be ? Call(_dateAdd_, _calendar_, « _intermediate_, _dateDuration2_, _secondAddOptions_ »).
1. Let _end_ be ? CalendarDateAdd(_calendar_, _intermediate_, _dateDuration2_, _secondAddOptions_, _dateAdd_).
1. Let _dateLargestUnit_ be ! LargerOfTwoTemporalDurationUnits(*"days"*, _largestUnit_).
1. Let _differenceOptions_ be ! OrdinaryObjectCreate(*null*).
1. Perform ! CreateDataPropertyOrThrow(_differenceOptions_, *"largestUnit"*, _dateLargestUnit_).
Expand Down Expand Up @@ -1249,16 +1249,16 @@ <h1>RoundDuration ( _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _sec
1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*).
1. Let _yearsDuration_ be ? CreateTemporalDuration(_years_, 0, 0, 0, 0, 0, 0, 0, 0, 0).
1. Let _firstAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _yearsLater_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _yearsDuration_, _firstAddptions_ »).
1. Let _yearsLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsDuration_, _firstAddptions_, _dateAdd_).
1. Let _yearsMonthsWeeks_ be ? CreateTemporalDuration(_years_, _months_, _weeks_, 0, 0, 0, 0, 0, 0, 0).
1. Let _secondAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _yearsMonthsWeeksLater_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _yearsMonthsWeeks_, _secondAddOptions_ »).
1. Let _yearsMonthsWeeksLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsMonthsWeeks_, _secondAddOptions_, _dateAdd_).
1. Let _monthsWeeksInDays_ be ? DaysUntil(_yearsLater_, _yearsMonthsWeeksLater_).
1. Set _relativeTo_ to _yearsLater_.
1. Let _days_ be _days_ + _monthsWeeksInDays_..
1. Let _daysDuration_ be ? CreateTemporalDuration(0, 0, 0, _days_, 0, 0, 0, 0, 0, 0).
1. Let _thirdAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _daysLater_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _daysDuration_, _thirdAddOptions_ »).
1. Let _daysLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _daysDuration_, _thirdAddOptions_, _dateAdd_).
1. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*).
1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"years"*).
1. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_).
Expand All @@ -1267,7 +1267,7 @@ <h1>RoundDuration ( _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _sec
1. Let _oldRelativeTo_ be _relativeTo_.
1. Let _yearsDuration_ be ? CreateTemporalDuration(_yearsPassed_, 0, 0, 0, 0, 0, 0, 0, 0, 0).
1. Let _fourthAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Set _relativeTo_ to ? Call(_dateAdd_, _calendar_, « _relativeTo_, _yearsDuration_, _fourthAddOptions_ »).
1. Set _relativeTo_ to ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsDuration_, _fourthAddOptions_, _dateAdd_).
1. Let _daysPassed_ be ? DaysUntil(_oldRelativeTo_, _relativeTo_).
1. Set _days_ to _days_ - _daysPassed_.
1. Let _sign_ be ! Sign(_days_).
Expand All @@ -1283,10 +1283,10 @@ <h1>RoundDuration ( _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _sec
1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*).
1. Let _yearsMonths_ be ? CreateTemporalDuration(_years_, _months_, 0, 0, 0, 0, 0, 0, 0, 0).
1. Let _firstAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _yearsMonthsLater_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _yearsMonths_, _firstAddOptions_ »).
1. Let _yearsMonthsLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsMonths_, _firstAddOptions_, _dateAdd_).
1. Let _yearsMonthsWeeks_ be ? CreateTemporalDuration(_years_, _months_, _weeks_, 0, 0, 0, 0, 0, 0, 0).
1. Let _secondAddOptions_ be ! OrdinaryObjectCreate(*null*).
1. Let _yearsMonthsWeeksLater_ be ? Call(_dateAdd_, _calendar_, « _relativeTo_, _yearsMonthsWeeks_, _secondAddOptions_ »).
1. Let _yearsMonthsWeeksLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsMonthsWeeks_, _secondAddOptions_, _dateAdd_).
1. Let _weeksInDays_ be ? DaysUntil(_yearsMonthsLater_, _yearsMonthsWeeksLater_).
1. Set _relativeTo_ to _yearsMonthsLater_.
1. Let _days_ be _days_ + _weeksInDays_.
Expand Down

0 comments on commit 040bc09

Please sign in to comment.