Commit 519267b3 authored by Frank Tang's avatar Frank Tang Committed by V8 LUCI CQ

[Temporal] Add Calendar.prototype.mergeFields

Add AO: DefaultMergeFields
Spec Text:
https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.mergefields
https://tc39.es/proposal-temporal/#sec-temporal-defaultmergefields


Bug: v8:11544
Change-Id: I270f8bffb79e57ef50736ae7ce87cfa53f9cafb1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3388428Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79795}
parent 95dfb560
......@@ -318,8 +318,6 @@ TO_BE_IMPLEMENTED(TemporalCalendarPrototypeMonthCode)
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeDay)
/* Temporal #sec-temporal.calendar.prototype.weekofyear */
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeWeekOfYear)
/* Temporal #sec-temporal.calendar.prototype.mergefields */
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeMergeFields)
/* Temporal #sec-temporal.calendar.prototype.tojson */
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeToJSON)
......@@ -794,14 +792,15 @@ TEMPORAL_GET_BIGINT_AFTER_DIVID(Instant, EpochMicroseconds, nanoseconds, 1000,
// Calendar
TEMPORAL_CONSTRUCTOR1(Calendar)
TEMPORAL_PROTOTYPE_METHOD2(Calendar, DateFromFields, dateFromFields)
TEMPORAL_ID_BY_TO_STRING(Calendar)
TEMPORAL_PROTOTYPE_METHOD2(Calendar, DateFromFields, dateFromFields)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, DaysInMonth, daysInMonth)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, DaysInWeek, daysInWeek)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, DaysInYear, daysInYear)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, DayOfWeek, dayOfWeek)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, DayOfYear, dayOfYear)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, InLeapYear, inLeapYear)
TEMPORAL_PROTOTYPE_METHOD2(Calendar, MergeFields, mergeFields)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, MonthsInYear, monthsInYear)
TEMPORAL_PROTOTYPE_METHOD1(Calendar, Year, year)
TEMPORAL_TO_STRING(Calendar)
......
......@@ -2899,6 +2899,116 @@ MaybeHandle<JSTemporalDuration> CalendarDateUntil(
return Handle<JSTemporalDuration>::cast(duration);
}
// #sec-temporal-defaultmergefields
MaybeHandle<JSReceiver> DefaultMergeFields(
Isolate* isolate, Handle<JSReceiver> fields,
Handle<JSReceiver> additional_fields) {
Factory* factory = isolate->factory();
// 1. Let merged be ! OrdinaryObjectCreate(%Object.prototype%).
Handle<JSObject> merged =
isolate->factory()->NewJSObject(isolate->object_function());
// 2. Let originalKeys be ? EnumerableOwnPropertyNames(fields, key).
Handle<FixedArray> original_keys;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, original_keys,
KeyAccumulator::GetKeys(fields, KeyCollectionMode::kOwnOnly,
ENUMERABLE_STRINGS,
GetKeysConversion::kConvertToString),
JSReceiver);
// 3. For each element nextKey of originalKeys, do
for (int i = 0; i < original_keys->length(); i++) {
// a. If nextKey is not "month" or "monthCode", then
Handle<Object> next_key = handle(original_keys->get(i), isolate);
DCHECK(next_key->IsString());
Handle<String> next_key_string = Handle<String>::cast(next_key);
if (!(String::Equals(isolate, factory->month_string(), next_key_string) ||
String::Equals(isolate, factory->monthCode_string(),
next_key_string))) {
// i. Let propValue be ? Get(fields, nextKey).
Handle<Object> prop_value;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, prop_value,
JSReceiver::GetPropertyOrElement(isolate, fields, next_key_string),
JSReceiver);
// ii. If propValue is not undefined, then
if (!prop_value->IsUndefined()) {
// 1. Perform ! CreateDataPropertyOrThrow(merged, nextKey,
// propValue).
CHECK(JSReceiver::CreateDataProperty(isolate, merged, next_key_string,
prop_value, Just(kDontThrow))
.FromJust());
}
}
}
// 4. Let newKeys be ? EnumerableOwnPropertyNames(additionalFields, key).
Handle<FixedArray> new_keys;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, new_keys,
KeyAccumulator::GetKeys(additional_fields, KeyCollectionMode::kOwnOnly,
ENUMERABLE_STRINGS,
GetKeysConversion::kConvertToString),
JSReceiver);
bool new_keys_has_month_or_month_code = false;
// 5. For each element nextKey of newKeys, do
for (int i = 0; i < new_keys->length(); i++) {
Handle<Object> next_key = handle(new_keys->get(i), isolate);
DCHECK(next_key->IsString());
Handle<String> next_key_string = Handle<String>::cast(next_key);
// a. Let propValue be ? Get(additionalFields, nextKey).
Handle<Object> prop_value;
ASSIGN_RETURN_ON_EXCEPTION(isolate, prop_value,
JSReceiver::GetPropertyOrElement(
isolate, additional_fields, next_key_string),
JSReceiver);
// b. If propValue is not undefined, then
if (!prop_value->IsUndefined()) {
// 1. Perform ! CreateDataPropertyOrThrow(merged, nextKey, propValue).
Maybe<bool> maybe_created = JSReceiver::CreateDataProperty(
isolate, merged, next_key_string, prop_value, Just(kThrowOnError));
MAYBE_RETURN(maybe_created, Handle<JSReceiver>());
}
new_keys_has_month_or_month_code |=
String::Equals(isolate, factory->month_string(), next_key_string) ||
String::Equals(isolate, factory->monthCode_string(), next_key_string);
}
// 6. If newKeys does not contain either "month" or "monthCode", then
if (!new_keys_has_month_or_month_code) {
// a. Let month be ? Get(fields, "month").
Handle<Object> month;
ASSIGN_RETURN_ON_EXCEPTION(isolate, month,
JSReceiver::GetPropertyOrElement(
isolate, fields, factory->month_string()),
JSReceiver);
// b. If month is not undefined, then
if (!month->IsUndefined()) {
// i. Perform ! CreateDataPropertyOrThrow(merged, "month", month).
CHECK(JSReceiver::CreateDataProperty(isolate, merged,
factory->month_string(), month,
Just(kDontThrow))
.FromJust());
}
// c. Let monthCode be ? Get(fields, "monthCode").
Handle<Object> month_code;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, month_code,
JSReceiver::GetPropertyOrElement(isolate, fields,
factory->monthCode_string()),
JSReceiver);
// d. If monthCode is not undefined, then
if (!month_code->IsUndefined()) {
// i. Perform ! CreateDataPropertyOrThrow(merged, "monthCode", monthCode).
CHECK(JSReceiver::CreateDataProperty(isolate, merged,
factory->monthCode_string(),
month_code, Just(kDontThrow))
.FromJust());
}
}
// 7. Return merged.
return merged;
}
// #sec-temporal-getoffsetnanosecondsfor
Maybe<int64_t> GetOffsetNanosecondsFor(Isolate* isolate,
Handle<JSReceiver> time_zone_obj,
Handle<Object> instant,
......@@ -5330,6 +5440,35 @@ MaybeHandle<JSTemporalPlainDate> JSTemporalCalendar::DateFromFields(
UNREACHABLE();
}
// #sec-temporal.calendar.prototype.mergefields
MaybeHandle<JSReceiver> JSTemporalCalendar::MergeFields(
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
Handle<Object> fields_obj, Handle<Object> additional_fields_obj) {
// 1. Let calendar be the this value.
// 2. Perform ? RequireInternalSlot(calendar,
// [[InitializedTemporalCalendar]]).
// 3. Assert: calendar.[[Identifier]] is "iso8601".
// 4. Set fields to ? ToObject(fields).
Handle<JSReceiver> fields;
ASSIGN_RETURN_ON_EXCEPTION(isolate, fields,
Object::ToObject(isolate, fields_obj), JSReceiver);
// 5. Set additionalFields to ? ToObject(additionalFields).
Handle<JSReceiver> additional_fields;
ASSIGN_RETURN_ON_EXCEPTION(isolate, additional_fields,
Object::ToObject(isolate, additional_fields_obj),
JSReceiver);
// 5. If calendar.[[Identifier]] is "iso8601", then
if (calendar->calendar_index() == 0) {
// a. Return ? DefaultMergeFields(fields, additionalFields).
return DefaultMergeFields(isolate, fields, additional_fields);
}
#ifdef V8_INTL_SUPPORT
// TODO(ftang) add Intl code.
#endif // V8_INTL_SUPPORT
UNREACHABLE();
}
// #sec-temporal.calendar.prototype.tostring
MaybeHandle<String> JSTemporalCalendar::ToString(
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
......
......@@ -97,6 +97,11 @@ class JSTemporalCalendar
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
Handle<Object> fields, Handle<Object> options);
// #sec-temporal.calendar.prototype.mergefields
V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> MergeFields(
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
Handle<Object> fields, Handle<Object> additional_fields);
// #sec-temporal.calendar.prototype.tostring
static MaybeHandle<String> ToString(Isolate* isolate,
Handle<JSTemporalCalendar> calendar,
......
......@@ -49,7 +49,6 @@
'temporal/calendar-date-until': [FAIL],
'temporal/calendar-day': [FAIL],
'temporal/calendar-fields': [FAIL],
'temporal/calendar-merge-fields': [FAIL],
'temporal/calendar-month': [FAIL],
'temporal/calendar-month-code': [FAIL],
'temporal/calendar-month-day-from-fields': [FAIL],
......
......@@ -398,10 +398,6 @@
'built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined': [FAIL],
'built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined': [FAIL],
'built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined': [FAIL],
'built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object': [FAIL],
'built-ins/Temporal/Calendar/prototype/mergeFields/basic': [FAIL],
'built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode': [FAIL],
'built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties': [FAIL],
'built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined': [FAIL],
'built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined': [FAIL],
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic': [FAIL],
......@@ -538,8 +534,6 @@
'built-ins/Temporal/Calendar/prototype/inLeapYear/basic': [FAIL],
'built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-temporal-object': [FAIL],
'built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror': [FAIL],
'built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object': [FAIL],
'built-ins/Temporal/Calendar/prototype/mergeFields/branding': [FAIL],
'built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator': [FAIL],
'built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer': [FAIL],
'built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment