Skip to content

Commit

Permalink
Editorial: Consolidate GetOption usage
Browse files Browse the repository at this point in the history
Under the assumption that it's not a priority to move GetNumberOption
directly from ECMA-402 into ECMA-262, reorganize the GetOption operations:

- Change the _type_ string argument to GetOption, into a List of valid
  types, the last one of which will be coerced to if the value is none of
  them (and also not undefined).

- In the Number case, call ToNumber on the value and throw if it is NaN.

- Inline GetNumberOption as it's only called once.

- Call GetOption in GetStringOrNumberOption.

- Don't delete GetOption, GetNumberOption, and DefaultNumberOption from
  402, as they won't be replaced by anything in 262 at present.

Includes a fix to make the polyfill spec-compliant, and test262 tests
covering usages of GetOption (there are quite a lot of them.)

Closes: #1411
  • Loading branch information
ptomato committed Jun 8, 2021
1 parent 2c8aa80 commit 4b5f104
Show file tree
Hide file tree
Showing 365 changed files with 7,357 additions and 111 deletions.
8 changes: 6 additions & 2 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -680,8 +680,12 @@ export const ES = ObjectAssign({}, ES2020, {
default: // fall through if option not given
}
let digits = options.fractionalSecondDigits;
if (digits === undefined || digits === 'auto') return { precision: 'auto', unit: 'nanosecond', increment: 1 };
digits = ES.ToNumber(digits);
if (digits === undefined) digits = 'auto';
if (ES.Type(digits) !== 'Number') {
digits = ES.ToString(digits);
if (digits === 'auto') return { precision: 'auto', unit: 'nanosecond', increment: 1 };
throw new RangeError(`fractionalSecondDigits must be 'auto' or 0 through 9, not ${digits}`);
}
if (NumberIsNaN(digits) || digits < 0 || digits > 9) {
throw new RangeError(`fractionalSecondDigits must be 'auto' or 0 through 9, not ${digits}`);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.dateadd
description: RangeError thrown when overflow option not one of the allowed string values
info: |
sec-getoption step 10:
10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal.calendar.prototype.dateadd step 7:
7. Let _overflow_ be ? ToTemporalOverflow(_options_).
---*/

const calendar = new Temporal.Calendar("iso8601");
const date = new Temporal.PlainDate(2000, 5, 2, calendar);
const duration = new Temporal.Duration(3, 3, 0, 3);
assert.throws(RangeError, () => calendar.dateAdd(date, duration, { overflow: "other string" }));
24 changes: 24 additions & 0 deletions polyfill/test/Calendar/prototype/dateAdd/overflow-undefined.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.dateadd
description: Fallback value for overflow option
info: |
sec-getoption step 3:
3. If _value_ is *undefined*, return _fallback_.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal.calendar.prototype.dateadd step 7:
7. Let _overflow_ be ? ToTemporalOverflow(_options_).
includes: [temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");
const date = new Temporal.PlainDate(2000, 5, 31, calendar);
const duration = new Temporal.Duration(3, 1);

const explicit = calendar.dateAdd(date, duration, { overflow: undefined });
TemporalHelpers.assertPlainDate(explicit, 2003, 6, "M06", 30, "default overflow is constrain");
const implicit = calendar.dateAdd(date, duration, {});
TemporalHelpers.assertPlainDate(implicit, 2003, 6, "M06", 30, "default overflow is constrain");
23 changes: 23 additions & 0 deletions polyfill/test/Calendar/prototype/dateAdd/overflow-wrong-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.dateadd
description: Type conversions for overflow option
info: |
sec-getoption step 9.a:
a. Set _value_ to ? ToString(_value_).
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal.calendar.prototype.dateadd step 7:
7. Let _overflow_ be ? ToTemporalOverflow(_options_).
includes: [compareArray.js, temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");
const date = new Temporal.PlainDate(2000, 5, 2, calendar);
const duration = new Temporal.Duration(3, 3, 0, 3);
TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
(overflow) => calendar.dateAdd(date, duration, { overflow }),
(result, descr) => TemporalHelpers.assertPlainDate(result, 2003, 8, "M08", 5, descr),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.datefromfields
description: RangeError thrown when overflow option not one of the allowed string values
info: |
sec-getoption step 10:
10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isodatefromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.datefromfields step 6:
6. Let _result_ be ? ISODateFromFields(_fields_, _options_).
---*/

const calendar = new Temporal.Calendar("iso8601");
assert.throws(RangeError, () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, { overflow: "other string" }));
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.datefromfields
description: Fallback value for overflow option
info: |
sec-getoption step 3:
3. If _value_ is *undefined*, return _fallback_.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isodatefromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.datefromfields step 6:
6. Let _result_ be ? ISODateFromFields(_fields_, _options_).
includes: [temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");

const explicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined });
TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 2, "default overflow is constrain");
const implicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, {});
TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 2, "default overflow is constrain");
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.datefromfields
description: Type conversions for overflow option
info: |
sec-getoption step 9.a:
a. Set _value_ to ? ToString(_value_).
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isodatefromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.datefromfields step 6:
6. Let _result_ be ? ISODateFromFields(_fields_, _options_).
includes: [compareArray.js, temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");
TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
(overflow) => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, { overflow }),
(result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2, descr),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.monthdayfromfields
description: RangeError thrown when overflow option not one of the allowed string values
info: |
sec-getoption step 10:
10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isomonthdayfromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.monthdayfromfields step 6:
6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
---*/

const calendar = new Temporal.Calendar("iso8601");
assert.throws(RangeError, () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow: "other string" }));
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.monthdayfromfields
description: Fallback value for overflow option
info: |
sec-getoption step 3:
3. If _value_ is *undefined*, return _fallback_.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isomonthdayfromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.monthdayfromfields step 6:
6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
includes: [temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");

const explicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined });
TemporalHelpers.assertPlainMonthDay(explicit, "M12", 2, "default overflow is constrain");
const implicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, {});
TemporalHelpers.assertPlainMonthDay(implicit, "M12", 2, "default overflow is constrain");
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.monthdayfromfields
description: Type conversions for overflow option
info: |
sec-getoption step 9.a:
a. Set _value_ to ? ToString(_value_).
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isomonthdayfromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.monthdayfromfields step 6:
6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
includes: [compareArray.js, temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");
TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
(overflow) => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }),
(result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2, descr),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.yearmonthfromfields
description: RangeError thrown when overflow option not one of the allowed string values
info: |
sec-getoption step 10:
10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isoyearmonthfromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.yearmonthfromfields step 6:
6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
---*/

const calendar = new Temporal.Calendar("iso8601");
assert.throws(RangeError, () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow: "other string" }));
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.yearmonthfromfields
description: Fallback value for overflow option
info: |
sec-getoption step 3:
3. If _value_ is *undefined*, return _fallback_.
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isoyearmonthfromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.yearmonthfromfields step 6:
6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
includes: [temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");

const explicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, { overflow: undefined });
TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain");
const implicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, {});
TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain");
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.calendar.prototype.yearmonthfromfields
description: Type conversions for overflow option
info: |
sec-getoption step 9.a:
a. Set _value_ to ? ToString(_value_).
sec-temporal-totemporaloverflow step 1:
1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
sec-temporal-isoyearmonthfromfields step 2:
2. Let _overflow_ be ? ToTemporalOverflow(_options_).
sec-temporal.calendar.prototype.yearmonthfromfields step 6:
6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
includes: [compareArray.js, temporalHelpers.js]
---*/

const calendar = new Temporal.Calendar("iso8601");
TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
(overflow) => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }),
(result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05", descr),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.duration.prototype.round
description: RangeError thrown when largestUnit option not one of the allowed string values
---*/

const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
assert.throws(RangeError, () => duration.round({ largestUnit: "other string" }));
20 changes: 20 additions & 0 deletions polyfill/test/Duration/prototype/round/largestunit-undefined.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.duration.prototype.round
description: Fallback value for largestUnit option
includes: [temporalHelpers.js]
---*/

const duration1 = new Temporal.Duration(0, 0, 0, 0, 1, 120, 1, 123, 456, 789);
const explicit1 = duration1.round({ largestUnit: undefined, smallestUnit: "nanosecond" });
TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 3, 0, 1, 123, 456, 789, "default largestUnit is largest in input");
const implicit1 = duration1.round({ smallestUnit: "nanosecond" });
TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 3, 0, 1, 123, 456, 789, "default largestUnit is largest in input");

const duration2 = new Temporal.Duration(0, 0, 0, 0, 0, 120, 1, 123, 456, 789);
const explicit2 = duration2.round({ largestUnit: undefined, smallestUnit: "nanosecond" });
TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 120, 1, 123, 456, 789, "default largestUnit is largest in input");
const implicit2 = duration2.round({ smallestUnit: "nanosecond" });
TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 120, 1, 123, 456, 789, "default largestUnit is largest in input");
14 changes: 14 additions & 0 deletions polyfill/test/Duration/prototype/round/largestunit-wrong-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.duration.prototype.round
description: Type conversions for largestUnit option
includes: [compareArray.js, temporalHelpers.js]
---*/

const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 456, 789);
TemporalHelpers.checkStringOptionWrongType("largestUnit", "minute",
(largestUnit) => duration.round({ largestUnit }),
(result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 754, 56, 123, 456, 789, descr),
);
17 changes: 17 additions & 0 deletions polyfill/test/Duration/prototype/round/roundingincrement-nan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.duration.prototype.round
description: RangeError thrown when roundingIncrement option is NaN
info: |
sec-getoption step 8.b:
b. If _value_ is *NaN*, throw a *RangeError* exception.
sec-temporal-totemporalroundingincrement step 5:
5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
sec-temporal.duration.prototype.round step 18:
18. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
---*/

const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321);
assert.throws(RangeError, () => duration.round({ smallestUnit: 'second', roundingIncrement: NaN }));
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.duration.prototype.round
description: Fallback value for roundingIncrement option
info: |
sec-getoption step 3:
3. If _value_ is *undefined*, return _fallback_.
sec-temporal-totemporalroundingincrement step 5:
5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
sec-temporal.duration.prototype.round step 18:
18. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
includes: [temporalHelpers.js]
---*/

const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321);

const explicit = duration.round({ smallestUnit: 'second', roundingIncrement: undefined });
TemporalHelpers.assertDuration(explicit, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");

const implicit = duration.round({ smallestUnit: 'second' });
TemporalHelpers.assertDuration(implicit, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
Loading

0 comments on commit 4b5f104

Please sign in to comment.