Skip to content

Commit 8b61c1b

Browse files
committed
Create options objects with null prototype
In NormalizeOptionsObject, which comes from ECMA-402 originally, when an options parameter is undefined, an object with null prototype is created. Make everywhere else that an options parameter is synthesized, consistent with that, so create objects with null prototype rather than {}. Ensure that separate objects are created and not re-used once they have been passed in to user code. (We continue to return plain objects whose prototype is Object.prototype from methods such as getISOFields()) See: #1424
1 parent 3e6cadd commit 8b61c1b

File tree

3 files changed

+74
-48
lines changed

3 files changed

+74
-48
lines changed

lib/ecmascript.mjs

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,8 @@ export const ES = ObjectAssign({}, ES2020, {
881881
calendar = ES.GetOptionalTemporalCalendar(relativeTo);
882882
const fieldNames = ES.CalendarFields(calendar, ['day', 'month', 'monthCode', 'year']);
883883
const fields = ES.ToTemporalDateTimeFields(relativeTo, fieldNames);
884+
const dateOptions = ObjectCreate(null);
885+
dateOptions.overflow = 'constrain';
884886
({
885887
year,
886888
month,
@@ -891,7 +893,7 @@ export const ES = ObjectAssign({}, ES2020, {
891893
millisecond,
892894
microsecond,
893895
nanosecond
894-
} = ES.InterpretTemporalDateTimeFields(calendar, fields, { overflow: 'constrain' }));
896+
} = ES.InterpretTemporalDateTimeFields(calendar, fields, dateOptions));
895897
offset = relativeTo.offset;
896898
timeZone = relativeTo.timeZone;
897899
} else {
@@ -1161,7 +1163,7 @@ export const ES = ObjectAssign({}, ES2020, {
11611163
return ES.PrepareTemporalFields(bag, entries);
11621164
},
11631165

1164-
ToTemporalDate: (item, options = {}) => {
1166+
ToTemporalDate: (item, options = ObjectCreate(null)) => {
11651167
if (ES.Type(item) === 'Object') {
11661168
if (ES.IsTemporalDate(item)) return item;
11671169
if (ES.IsTemporalZonedDateTime(item)) {
@@ -1207,7 +1209,7 @@ export const ES = ObjectAssign({}, ES2020, {
12071209
));
12081210
return { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond };
12091211
},
1210-
ToTemporalDateTime: (item, options = {}) => {
1212+
ToTemporalDateTime: (item, options = ObjectCreate(null)) => {
12111213
let year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar;
12121214
if (ES.Type(item) === 'Object') {
12131215
if (ES.IsTemporalDateTime(item)) return item;
@@ -1343,7 +1345,7 @@ export const ES = ObjectAssign({}, ES2020, {
13431345
const TemporalInstant = GetIntrinsic('%Temporal.Instant%');
13441346
return new TemporalInstant(ns);
13451347
},
1346-
ToTemporalMonthDay: (item, options = {}) => {
1348+
ToTemporalMonthDay: (item, options = ObjectCreate(null)) => {
13471349
if (ES.Type(item) === 'Object') {
13481350
if (ES.IsTemporalMonthDay(item)) return item;
13491351
let calendar, calendarAbsent;
@@ -1377,7 +1379,8 @@ export const ES = ObjectAssign({}, ES2020, {
13771379
return ES.CreateTemporalMonthDay(month, day, calendar);
13781380
}
13791381
const result = ES.CreateTemporalMonthDay(month, day, calendar, referenceISOYear);
1380-
return ES.MonthDayFromFields(calendar, result, {});
1382+
const canonicalOptions = ObjectCreate(null);
1383+
return ES.MonthDayFromFields(calendar, result, canonicalOptions);
13811384
},
13821385
ToTemporalTime: (item, overflow = 'constrain') => {
13831386
let hour, minute, second, millisecond, microsecond, nanosecond, calendar;
@@ -1427,7 +1430,7 @@ export const ES = ObjectAssign({}, ES2020, {
14271430
const TemporalPlainTime = GetIntrinsic('%Temporal.PlainTime%');
14281431
return new TemporalPlainTime(hour, minute, second, millisecond, microsecond, nanosecond);
14291432
},
1430-
ToTemporalYearMonth: (item, options = {}) => {
1433+
ToTemporalYearMonth: (item, options = ObjectCreate(null)) => {
14311434
if (ES.Type(item) === 'Object') {
14321435
if (ES.IsTemporalYearMonth(item)) return item;
14331436
const calendar = ES.GetOptionalTemporalCalendar(item);
@@ -1446,7 +1449,8 @@ export const ES = ObjectAssign({}, ES2020, {
14461449
return ES.CreateTemporalYearMonth(year, month, calendar);
14471450
}
14481451
const result = ES.CreateTemporalYearMonth(year, month, calendar, referenceISODay);
1449-
return ES.YearMonthFromFields(calendar, result, {});
1452+
const canonicalOptions = ObjectCreate(null);
1453+
return ES.YearMonthFromFields(calendar, result, canonicalOptions);
14501454
},
14511455
InterpretISODateTimeOffset: (
14521456
year,
@@ -1512,7 +1516,7 @@ export const ES = ObjectAssign({}, ES2020, {
15121516
const instant = ES.BuiltinTimeZoneGetInstantFor(timeZone, dt, disambiguation);
15131517
return GetSlot(instant, EPOCHNANOSECONDS);
15141518
},
1515-
ToTemporalZonedDateTime: (item, options = {}) => {
1519+
ToTemporalZonedDateTime: (item, options = ObjectCreate(null)) => {
15161520
let year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, timeZone, offset, calendar;
15171521
if (ES.Type(item) === 'Object') {
15181522
if (ES.IsTemporalZonedDateTime(item)) return item;
@@ -2868,14 +2872,12 @@ export const ES = ObjectAssign({}, ES2020, {
28682872
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
28692873
const dateUntil = ES.GetMethod(calendar, 'dateUntil');
28702874
while (MathAbs(years) > 0) {
2871-
const newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, {}, dateAdd);
2872-
const oneYearMonths = ES.CalendarDateUntil(
2873-
calendar,
2874-
relativeTo,
2875-
newRelativeTo,
2876-
{ largestUnit: 'months' },
2877-
dateUntil
2878-
).months;
2875+
const addOptions = ObjectCreate(null);
2876+
const newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, addOptions, dateAdd);
2877+
const untilOptions = ObjectCreate(null);
2878+
untilOptions.largestUnit = 'months';
2879+
const oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil)
2880+
.months;
28792881
relativeTo = newRelativeTo;
28802882
months += oneYearMonths;
28812883
years -= sign;
@@ -2972,27 +2974,21 @@ export const ES = ObjectAssign({}, ES2020, {
29722974

29732975
// balance months up to years
29742976
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
2975-
newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, {}, dateAdd);
2977+
const addOptions = ObjectCreate(null);
2978+
newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, addOptions, dateAdd);
29762979
const dateUntil = ES.GetMethod(calendar, 'dateUntil');
2977-
let oneYearMonths = ES.CalendarDateUntil(
2978-
calendar,
2979-
relativeTo,
2980-
newRelativeTo,
2981-
{ largestUnit: 'months' },
2982-
dateUntil
2983-
).months;
2980+
const untilOptions = ObjectCreate(null);
2981+
untilOptions.largestUnit = 'months';
2982+
let oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil).months;
29842983
while (MathAbs(months) >= MathAbs(oneYearMonths)) {
29852984
months -= oneYearMonths;
29862985
years += sign;
29872986
relativeTo = newRelativeTo;
2988-
newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, {}, dateAdd);
2989-
oneYearMonths = ES.CalendarDateUntil(
2990-
calendar,
2991-
relativeTo,
2992-
newRelativeTo,
2993-
{ largestUnit: 'months' },
2994-
dateUntil
2995-
).months;
2987+
const addOptions = ObjectCreate(null);
2988+
newRelativeTo = ES.CalendarDateAdd(calendar, relativeTo, oneYear, addOptions, dateAdd);
2989+
const untilOptions = ObjectCreate(null);
2990+
untilOptions.largestUnit = 'months';
2991+
oneYearMonths = ES.CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil).months;
29962992
}
29972993
break;
29982994
}
@@ -3320,7 +3316,7 @@ export const ES = ObjectAssign({}, ES2020, {
33203316
ns2,
33213317
calendar,
33223318
largestUnit,
3323-
options = {}
3319+
options = ObjectCreate(null)
33243320
) => {
33253321
let { deltaDays, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.DifferenceTime(
33263322
h1,
@@ -3555,13 +3551,15 @@ export const ES = ObjectAssign({}, ES2020, {
35553551
const dateDuration1 = new TemporalDuration(y1, mon1, w1, d1, 0, 0, 0, 0, 0, 0);
35563552
const dateDuration2 = new TemporalDuration(y2, mon2, w2, d2, 0, 0, 0, 0, 0, 0);
35573553
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
3558-
const intermediate = ES.CalendarDateAdd(calendar, datePart, dateDuration1, {}, dateAdd);
3559-
const end = ES.CalendarDateAdd(calendar, intermediate, dateDuration2, {}, dateAdd);
3554+
const firstAddOptions = ObjectCreate(null);
3555+
const intermediate = ES.CalendarDateAdd(calendar, datePart, dateDuration1, firstAddOptions, dateAdd);
3556+
const secondAddOptions = ObjectCreate(null);
3557+
const end = ES.CalendarDateAdd(calendar, intermediate, dateDuration2, secondAddOptions, dateAdd);
35603558

35613559
const dateLargestUnit = ES.LargerOfTwoTemporalDurationUnits('days', largestUnit);
3562-
({ years, months, weeks, days } = ES.CalendarDateUntil(calendar, datePart, end, {
3563-
largestUnit: dateLargestUnit
3564-
}));
3560+
const differenceOptions = ObjectCreate(null);
3561+
differenceOptions.largestUnit = dateLargestUnit;
3562+
({ years, months, weeks, days } = ES.CalendarDateUntil(calendar, datePart, end, differenceOptions));
35653563
// Signs of date part and time part may not agree; balance them together
35663564
({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceDuration(
35673565
days,
@@ -3891,7 +3889,8 @@ export const ES = ObjectAssign({}, ES2020, {
38913889
).days;
38923890
},
38933891
MoveRelativeDate: (calendar, relativeTo, duration) => {
3894-
const later = ES.CalendarDateAdd(calendar, relativeTo, duration, {});
3892+
const options = ObjectCreate(null);
3893+
const later = ES.CalendarDateAdd(calendar, relativeTo, duration, options);
38953894
const days = ES.DaysUntil(relativeTo, later);
38963895
relativeTo = ES.CreateTemporalDateTime(
38973896
GetSlot(later, ISO_YEAR),
@@ -4104,18 +4103,30 @@ export const ES = ObjectAssign({}, ES2020, {
41044103
// relativeTo + years, relativeTo + { years, months, weeks })
41054104
const yearsDuration = new TemporalDuration(years);
41064105
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
4107-
const yearsLater = ES.CalendarDateAdd(calendar, relativeTo, yearsDuration, {}, dateAdd);
4106+
const firstAddOptions = ObjectCreate(null);
4107+
const yearsLater = ES.CalendarDateAdd(calendar, relativeTo, yearsDuration, firstAddOptions, dateAdd);
41084108
const yearsMonthsWeeks = new TemporalDuration(years, months, weeks);
4109-
const yearsMonthsWeeksLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonthsWeeks, {}, dateAdd);
4109+
const secondAddOptions = ObjectCreate(null);
4110+
const yearsMonthsWeeksLater = ES.CalendarDateAdd(
4111+
calendar,
4112+
relativeTo,
4113+
yearsMonthsWeeks,
4114+
secondAddOptions,
4115+
dateAdd
4116+
);
41104117
const monthsWeeksInDays = ES.DaysUntil(yearsLater, yearsMonthsWeeksLater);
41114118
relativeTo = yearsLater;
41124119
days += monthsWeeksInDays;
41134120

4114-
const daysLater = ES.CalendarDateAdd(calendar, relativeTo, { days }, {}, dateAdd);
4115-
const yearsPassed = ES.CalendarDateUntil(calendar, relativeTo, daysLater, { largestUnit: 'years' }).years;
4121+
const thirdAddOptions = ObjectCreate(null);
4122+
const daysLater = ES.CalendarDateAdd(calendar, relativeTo, { days }, thirdAddOptions, dateAdd);
4123+
const untilOptions = ObjectCreate(null);
4124+
untilOptions.largestUnit = 'years';
4125+
const yearsPassed = ES.CalendarDateUntil(calendar, relativeTo, daysLater, untilOptions).years;
41164126
years += yearsPassed;
41174127
const oldRelativeTo = relativeTo;
4118-
relativeTo = ES.CalendarDateAdd(calendar, relativeTo, { years: yearsPassed }, {}, dateAdd);
4128+
const fourthAddOptions = ObjectCreate(null);
4129+
relativeTo = ES.CalendarDateAdd(calendar, relativeTo, { years: yearsPassed }, fourthAddOptions, dateAdd);
41194130
const daysPassed = ES.DaysUntil(oldRelativeTo, relativeTo);
41204131
days -= daysPassed;
41214132
const oneYear = new TemporalDuration(days < 0 ? -1 : 1);
@@ -4143,9 +4154,17 @@ export const ES = ObjectAssign({}, ES2020, {
41434154
// { years, months }, relativeTo + { years, months, weeks })
41444155
const yearsMonths = new TemporalDuration(years, months);
41454156
const dateAdd = ES.GetMethod(calendar, 'dateAdd');
4146-
const yearsMonthsLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonths, {}, dateAdd);
4157+
const firstAddOptions = ObjectCreate(null);
4158+
const yearsMonthsLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonths, firstAddOptions, dateAdd);
41474159
const yearsMonthsWeeks = new TemporalDuration(years, months, weeks);
4148-
const yearsMonthsWeeksLater = ES.CalendarDateAdd(calendar, relativeTo, yearsMonthsWeeks, {}, dateAdd);
4160+
const secondAddOptions = ObjectCreate(null);
4161+
const yearsMonthsWeeksLater = ES.CalendarDateAdd(
4162+
calendar,
4163+
relativeTo,
4164+
yearsMonthsWeeks,
4165+
secondAddOptions,
4166+
dateAdd
4167+
);
41494168
const weeksInDays = ES.DaysUntil(yearsMonthsLater, yearsMonthsWeeksLater);
41504169
relativeTo = yearsMonthsLater;
41514170
days += weeksInDays;

lib/plainmonthday.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { DateTimeFormat } from './intl.mjs';
33
import { MakeIntrinsicClass } from './intrinsicclass.mjs';
44
import { ISO_MONTH, ISO_DAY, ISO_YEAR, CALENDAR, TIME_ZONE, GetSlot, HasSlot } from './slots.mjs';
55

6+
const ObjectCreate = Object.create;
7+
68
export class PlainMonthDay {
79
constructor(isoMonth, isoDay, calendar = ES.GetISO8601Calendar(), referenceISOYear = 1972) {
810
isoMonth = ES.ToInteger(isoMonth);
@@ -114,7 +116,8 @@ export class PlainMonthDay {
114116
}
115117
});
116118
mergedFields = ES.PrepareTemporalFields(mergedFields, mergedEntries);
117-
return ES.DateFromFields(calendar, mergedFields);
119+
const options = ObjectCreate(null);
120+
return ES.DateFromFields(calendar, mergedFields, options);
118121
}
119122
getISOFields() {
120123
if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');

lib/plainyearmonth.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { DateTimeFormat } from './intl.mjs';
33
import { GetIntrinsic, MakeIntrinsicClass } from './intrinsicclass.mjs';
44
import { ISO_YEAR, ISO_MONTH, ISO_DAY, CALENDAR, TIME_ZONE, GetSlot, HasSlot } from './slots.mjs';
55

6+
const ObjectCreate = Object.create;
7+
68
export class PlainYearMonth {
79
constructor(isoYear, isoMonth, calendar = ES.GetISO8601Calendar(), referenceISODay = 1) {
810
isoYear = ES.ToInteger(isoYear);
@@ -337,7 +339,9 @@ export class PlainYearMonth {
337339
}
338340
});
339341
mergedFields = ES.PrepareTemporalFields(mergedFields, mergedEntries);
340-
return ES.DateFromFields(calendar, mergedFields, { overflow: 'reject' });
342+
const options = ObjectCreate(null);
343+
options.overflow = 'reject';
344+
return ES.DateFromFields(calendar, mergedFields, options);
341345
}
342346
getISOFields() {
343347
if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');

0 commit comments

Comments
 (0)