Skip to content

Commit

Permalink
Allow calendar.fields() to accept an iterable
Browse files Browse the repository at this point in the history
Temporal will only ever call the fields() method with an array, but other
callers may want to supply a different iterable (such as a Set).

See: tc39#1427
ptomato committed Apr 17, 2021
1 parent 70bf6fc commit 79fee27
Showing 7 changed files with 53 additions and 10 deletions.
4 changes: 2 additions & 2 deletions docs/calendar.md
Original file line number Diff line number Diff line change
@@ -366,11 +366,11 @@ Temporal.Calendar.from('chinese').dateUntil(
); // => P1M2D
```

### calendar.**fields**(_fields_: array<string>) : Iterable<string>
### calendar.**fields**(_fields_: Iterable<string>) : Iterable<string>

**Parameters:**

- `fields` (array of strings): A list of field names.
- `fields` (array of strings, or other iterable yielding strings): A list of field names.

**Returns:** a new list of field names.

4 changes: 2 additions & 2 deletions polyfill/index.d.ts
Original file line number Diff line number Diff line change
@@ -686,7 +686,7 @@ export namespace Temporal {
| /** @deprecated */ 'day'
>
): Temporal.Duration;
fields?(fields: Array<string>): Iterable<string>;
fields?(fields: Iterable<string>): Iterable<string>;
mergeFields?(fields: Record<string, unknown>, additionalFields: Record<string, unknown>): Record<string, unknown>;
toString(): string;
}
@@ -769,7 +769,7 @@ export namespace Temporal {
| /** @deprecated */ 'day'
>
): Temporal.Duration;
fields(fields: Array<string>): Iterable<string>;
fields(fields: Iterable<string>): Iterable<string>;
mergeFields(fields: Record<string, unknown>, additionalFields: Record<string, unknown>): Record<string, unknown>;
toString(): string;
}
9 changes: 7 additions & 2 deletions polyfill/lib/calendar.mjs
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import { GetIntrinsic, MakeIntrinsicClass, DefineIntrinsic } from './intrinsiccl
import { CALENDAR_ID, ISO_YEAR, ISO_MONTH, ISO_DAY, CreateSlots, GetSlot, HasSlot, SetSlot } from './slots.mjs';

const ArrayIncludes = Array.prototype.includes;
const ArrayPrototypePush = Array.prototype.push;
const ObjectAssign = Object.assign;

const impl = {};
@@ -54,8 +55,12 @@ export class Calendar {
}
fields(fields) {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
fields = ES.CreateListFromArrayLike(fields, ['String']);
return impl[GetSlot(this, CALENDAR_ID)].fields(fields);
const fieldsArray = [];
for (const name of fields) {
if (ES.Type(name) !== 'String') throw new TypeError('invalid fields');
ArrayPrototypePush.call(fieldsArray, name);
}
return impl[GetSlot(this, CALENDAR_ID)].fields(fieldsArray);
}
mergeFields(fields, additionalFields) {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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.fields
info: |
sec-temporal.calendar.prototype.fields step 4:
4. Let _fieldNames_ be ? IterableToList(_fields_).
includes: [compareArray.js]
---*/

const fieldNames = ["day", "month", "monthCode", "year"];
const iterable = {
iteratorExhausted: false,
*[Symbol.iterator]() {
yield* fieldNames;
this.iteratorExhausted = true;
},
};

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

assert.compareArray(result, fieldNames);
assert(iterable.iteratorExhausted);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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.fields
info: |
sec-temporal.calendar.prototype.fields step 5:
5. For each element _fieldName_ of _fieldNames_, do
a. If Type(_fieldName_) is not String, throw a *TypeError* exception.
---*/

const calendar = new Temporal.Calendar("iso8601");
[true, 3, 3n, {}, () => {}, Symbol(), undefined, null].forEach((element) => {
assert.throws(TypeError, () => calendar.fields([element]), "bad input to calendar.fields()");
});
3 changes: 1 addition & 2 deletions spec/calendar.html
Original file line number Diff line number Diff line change
@@ -1032,8 +1032,7 @@ <h1>Temporal.Calendar.prototype.fields ( _fields_ )</h1>
1. Let _calendar_ be the *this* value.
1. Perform ? RequireInternalSlot(_calendar_, [[InitializedTemporalCalendar]]).
1. Assert: _calendar_.[[Identifier]] is *"iso8601"*.
1. Set _fields_ to ? ToObject(_fields_).
1. Let _fieldNames_ be ? CreateListFromArrayLike(_fields_, « String »).
1. Let _fieldNames_ be ? IterableToListOfType(_fields_, « String »).
1. Return ? CreateArrayFromList(_fieldNames_).
</emu-alg>
</emu-clause>
3 changes: 1 addition & 2 deletions spec/intl.html
Original file line number Diff line number Diff line change
@@ -1550,8 +1550,7 @@ <h1>Temporal.Calendar.prototype.fields ( _fields_ )</h1>
<emu-alg>
1. Let _calendar_ be the *this* value.
1. Perform ? RequireInternalSlot(_calendar_, [[InitializedTemporalCalendar]]).
1. Set _fields_ to ? ToObject(_fields_).
1. Let _fieldNames_ be ? CreateListFromArrayLike(_fields_, « String »).
1. Let _fieldNames_ be ? IterableToListOfType(_fields_, « String »).
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. Let _result_ be _fieldNames_.
1. Else,

0 comments on commit 79fee27

Please sign in to comment.