Skip to content

Commit

Permalink
Copy objects received from user code before passing them into user co…
Browse files Browse the repository at this point in the history
…de again

The intention of this is that any getters installed on an object received
from user code are called once each, in a defined order.

Requires a few fixes to make the polyfill match the spec text.

See: #1426
  • Loading branch information
ptomato committed Apr 6, 2021
1 parent 388ab08 commit 8ee543e
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 15 deletions.
6 changes: 3 additions & 3 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,10 +1123,10 @@ export const ES = ObjectAssign({}, ES2020, {
['month', undefined],
['monthCode', undefined],
['nanosecond', 0],
['offset', undefined],
['second', 0],
['timeZone'],
['year', undefined]
['year', undefined],
['offset', undefined],
['timeZone']
];
// Add extra fields from the calendar at the end
fieldNames.forEach((fieldName) => {
Expand Down
1 change: 1 addition & 0 deletions polyfill/lib/plaindate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export class PlainDate {
}
let fields = ES.ToTemporalDateFields(this, fieldNames);
fields = ES.CalendarMergeFields(calendar, fields, props);
fields = ES.ToTemporalDateFields(fields, fieldNames);

options = ES.NormalizeOptionsObject(options);

Expand Down
1 change: 1 addition & 0 deletions polyfill/lib/plaindatetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export class PlainDateTime {
}
let fields = ES.ToTemporalDateTimeFields(this, fieldNames);
fields = ES.CalendarMergeFields(calendar, fields, props);
fields = ES.ToTemporalDateTimeFields(fields, fieldNames);
const {
year,
month,
Expand Down
23 changes: 17 additions & 6 deletions polyfill/lib/plainmonthday.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class PlainMonthDay {
}
let fields = ES.ToTemporalMonthDayFields(this, fieldNames);
fields = ES.CalendarMergeFields(calendar, fields, props);
fields = ES.ToTemporalMonthDayFields(fields, fieldNames);

options = ES.NormalizeOptionsObject(options);
return ES.MonthDayFromFields(calendar, fields, options);
Expand Down Expand Up @@ -124,18 +125,28 @@ export class PlainMonthDay {
const calendar = GetSlot(this, CALENDAR);

const receiverFieldNames = ES.CalendarFields(calendar, ['day', 'monthCode']);
const fields = ES.ToTemporalMonthDayFields(this, receiverFieldNames);
let fields = ES.ToTemporalMonthDayFields(this, receiverFieldNames);

const inputFieldNames = ES.CalendarFields(calendar, ['year']);
const entries = [['year']];
const inputEntries = [['year']];
// Add extra fields from the calendar at the end
inputFieldNames.forEach((fieldName) => {
if (!entries.some(([name]) => name === fieldName)) {
entries.push([fieldName, undefined]);
if (!inputEntries.some(([name]) => name === fieldName)) {
inputEntries.push([fieldName, undefined]);
}
});
ObjectAssign(fields, ES.PrepareTemporalFields(item, entries));
return ES.DateFromFields(calendar, fields);
const inputFields = ES.PrepareTemporalFields(item, inputEntries);
let mergedFields = ES.CalendarMergeFields(calendar, fields, inputFields);

const mergedFieldNames = [...new Set([...receiverFieldNames, ...inputFieldNames])];
const mergedEntries = [];
mergedFieldNames.forEach((fieldName) => {
if (!mergedEntries.some(([name]) => name === fieldName)) {
mergedEntries.push([fieldName, undefined]);
}
});
mergedFields = ES.PrepareTemporalFields(mergedFields, mergedEntries);
return ES.DateFromFields(calendar, mergedFields);
}
getISOFields() {
if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
Expand Down
23 changes: 17 additions & 6 deletions polyfill/lib/plainyearmonth.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export class PlainYearMonth {
}
let fields = ES.ToTemporalYearMonthFields(this, fieldNames);
fields = ES.CalendarMergeFields(calendar, fields, props);
fields = ES.ToTemporalYearMonthFields(fields, fieldNames);

options = ES.NormalizeOptionsObject(options);

Expand Down Expand Up @@ -348,18 +349,28 @@ export class PlainYearMonth {
const calendar = GetSlot(this, CALENDAR);

const receiverFieldNames = ES.CalendarFields(calendar, ['monthCode', 'year']);
const fields = ES.ToTemporalYearMonthFields(this, receiverFieldNames);
let fields = ES.ToTemporalYearMonthFields(this, receiverFieldNames);

const inputFieldNames = ES.CalendarFields(calendar, ['day']);
const entries = [['day']];
const inputEntries = [['day']];
// Add extra fields from the calendar at the end
inputFieldNames.forEach((fieldName) => {
if (!entries.some(([name]) => name === fieldName)) {
entries.push([fieldName, undefined]);
if (!inputEntries.some(([name]) => name === fieldName)) {
inputEntries.push([fieldName, undefined]);
}
});
ObjectAssign(fields, ES.PrepareTemporalFields(item, entries));
return ES.DateFromFields(calendar, fields, { overflow: 'reject' });
const inputFields = ES.PrepareTemporalFields(item, inputEntries);
let mergedFields = ES.CalendarMergeFields(calendar, fields, inputFields);

const mergedFieldNames = [...new Set([...receiverFieldNames, ...inputFieldNames])];
const mergedEntries = [];
mergedFieldNames.forEach((fieldName) => {
if (!mergedEntries.some(([name]) => name === fieldName)) {
mergedEntries.push([fieldName, undefined]);
}
});
mergedFields = ES.PrepareTemporalFields(mergedFields, mergedEntries);
return ES.DateFromFields(calendar, mergedFields, { overflow: 'reject' });
}
getISOFields() {
if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
Expand Down
1 change: 1 addition & 0 deletions polyfill/lib/zoneddatetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ export class ZonedDateTime {
}
let fields = ES.ToTemporalZonedDateTimeFields(this, fieldNames);
fields = ES.CalendarMergeFields(calendar, fields, props);
fields = ES.ToTemporalZonedDateTimeFields(fields, fieldNames);
let {
year,
month,
Expand Down
1 change: 1 addition & 0 deletions spec/plaindate.html
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ <h1>Temporal.PlainDate.prototype.with ( _temporalDateLike_ [ , _options_ ] )</h1
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _fields_ be ? PrepareTemporalFields(_temporalDate_, _fieldNames_, «»).
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDate_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»).
1. Return ? DateFromFields(_calendar_, _fields_, _options_).
</emu-alg>
</emu-clause>
Expand Down
1 change: 1 addition & 0 deletions spec/plaindatetime.html
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ <h1>Temporal.PlainDateTime.prototype.with ( _temporalDateTimeLike_ [ , _options_
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _fields_ be ? PrepareTemporalFields(_dateTime_, _fieldNames_, «»).
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDateTime_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»).
1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
1. Assert: ! ValidateISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]]) is *true*.
1. Return ? CreateTemporalDateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _calendar_).
Expand Down
3 changes: 3 additions & 0 deletions spec/plainmonthday.html
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ <h1>Temporal.PlainMonthDay.prototype.with ( _temporalMonthDayLike_ [ , _options_
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _fields_ be ? PrepareTemporalFields(_monthDay_, _fieldNames_, «»).
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialMonthDay_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»).
1. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -243,6 +244,8 @@ <h1>Temporal.PlainMonthDay.prototype.toPlainDate ( _item_ )</h1>
1. Let _inputFieldNames_ be ? CalendarFields(_calendar_, « *"year"* »).
1. Let _inputFields_ be ? PrepareTemporalFields(_item_, _inputFieldNames_, «»).
1. Let _mergedFields_ be ? CalendarMergeFields(_calendar_, _fields_, _inputFields_).
1. Let _mergedFieldNames_ be the List containing all the elements of _receiverFieldNames_ followed by all the elements of _inputFieldNames_, with duplicate elements removed.
1. Set _mergedFields_ to ? PrepareTemporalFields(_mergedFields_, _mergedFieldNames_, «»).
1. Let _options_ be ! OrdinaryObjectCreate(%Object.prototype%).
1. Perform ! CreateDataPropertyOrThrow(_options_, *"overflow"*, *"reject"*).
1. Return ? DateFromFields(_calendar_, _mergedFields_, _options_).
Expand Down
3 changes: 3 additions & 0 deletions spec/plainyearmonth.html
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ <h1>Temporal.PlainYearMonth.prototype.with ( _temporalYearMonthLike_ [ , _option
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _fields_ be ? PrepareTemporalFields(_yearMonth_, _fieldNames_, «»).
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialYearMonth_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»).
1. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -455,6 +456,8 @@ <h1>Temporal.PlainYearMonth.prototype.toPlainDate ( _item_ )</h1>
1. Let _inputFieldNames_ be ? CalendarFields(_calendar_, « *"day"* »).
1. Let _inputFields_ be ? PrepareTemporalFields(_item_, _inputFieldNames_, «»).
1. Let _mergedFields_ be ? CalendarMergeFields(_calendar_, _fields_, _inputFields_).
1. Let _mergedFieldNames_ be the List containing all the elements of _receiverFieldNames_ followed by all the elements of _inputFieldNames_, with duplicate elements removed.
1. Set _mergedFields_ to ? PrepareTemporalFields(_mergedFields_, _mergedFieldNames_, «»).
1. Let _options_ be ! OrdinaryObjectCreate(%Object.prototype%).
1. Perform ! CreateDataPropertyOrThrow(_options_, *"overflow"*, *"reject"*).
1. Return ? DateFromFields(_calendar_, _mergedFields_, _options_).
Expand Down
1 change: 1 addition & 0 deletions spec/zoneddatetime.html
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ <h1>Temporal.ZonedDateTime.prototype.with ( _temporalZonedDateTimeLike_ [ , _opt
1. Append *"timeZone"* to _fieldNames_.
1. Let _fields_ be ? PrepareTemporalFields(_zonedDateTime_, _fieldNames_, « *"timeZone"* »).
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialZonedDateTime_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « *"timeZone"* »).
1. Let _offsetString_ be ? Get(_partialZonedDateTime_, *"offset"*).
1. If _offsetString_ is not *undefined*, then
1. Perform ? Set(_fields_, *"offset"*, _offsetString_).
Expand Down

0 comments on commit 8ee543e

Please sign in to comment.