[Temporal] Add Temporal.PlainDate.from
Bug: v8:11544 Change-Id: I781119561db5ec05b12b9bca31c98403355e35ac Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3378882 Reviewed-by: Shu-yu Guo <syg@chromium.org> Commit-Queue: Frank Tang <ftang@chromium.org> Cr-Commit-Position: refs/heads/main@{#79396}
This commit is contained in:
parent
e7b7a3df00
commit
afe71f3936
@ -1661,6 +1661,7 @@ namespace internal {
|
||||
CPP(TemporalCalendarPrototypeToJSON) \
|
||||
\
|
||||
/* "Private" (created but not exposed) Bulitins needed by Temporal */ \
|
||||
TFJ(StringFixedArrayFromIterable, kJSArgcReceiverSlots, kIterable) \
|
||||
TFJ(TemporalInstantFixedArrayFromIterable, kJSArgcReceiverSlots, kIterable)
|
||||
|
||||
#define BUILTIN_LIST_BASE(CPP, TFJ, TFC, TFS, TFH, ASM) \
|
||||
|
@ -218,7 +218,7 @@ TF_BUILTIN(IterableToFixedArrayForWasm, IteratorBuiltinsAssembler) {
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
TNode<JSArray> IteratorBuiltinsAssembler::StringListFromIterable(
|
||||
TNode<FixedArray> IteratorBuiltinsAssembler::StringListFromIterable(
|
||||
TNode<Context> context, TNode<Object> iterable) {
|
||||
Label done(this);
|
||||
GrowableFixedArray list(state());
|
||||
@ -279,7 +279,7 @@ TNode<JSArray> IteratorBuiltinsAssembler::StringListFromIterable(
|
||||
|
||||
BIND(&done);
|
||||
// 6. Return list.
|
||||
return list.ToJSArray(context);
|
||||
return list.ToFixedArray();
|
||||
}
|
||||
|
||||
TF_BUILTIN(StringListFromIterable, IteratorBuiltinsAssembler) {
|
||||
@ -289,6 +289,13 @@ TF_BUILTIN(StringListFromIterable, IteratorBuiltinsAssembler) {
|
||||
Return(StringListFromIterable(context, iterable));
|
||||
}
|
||||
|
||||
TF_BUILTIN(StringFixedArrayFromIterable, IteratorBuiltinsAssembler) {
|
||||
auto context = Parameter<Context>(Descriptor::kContext);
|
||||
auto iterable = Parameter<Object>(Descriptor::kIterable);
|
||||
|
||||
Return(StringListFromIterable(context, iterable));
|
||||
}
|
||||
|
||||
// This builtin always returns a new JSArray and is thus safe to use even in the
|
||||
// presence of code that may call back into user-JS. This builtin will take the
|
||||
// fast path if the iterable is a fast array and the Array prototype and the
|
||||
|
@ -67,8 +67,8 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
|
||||
|
||||
// Currently at https://tc39.github.io/proposal-intl-list-format/
|
||||
// #sec-createstringlistfromiterable
|
||||
TNode<JSArray> StringListFromIterable(TNode<Context> context,
|
||||
TNode<Object> iterable);
|
||||
TNode<FixedArray> StringListFromIterable(TNode<Context> context,
|
||||
TNode<Object> iterable);
|
||||
|
||||
void FastIterableToList(TNode<Context> context, TNode<Object> iterable,
|
||||
TVariable<JSArray>* var_result, Label* slow);
|
||||
|
@ -38,8 +38,6 @@ namespace internal {
|
||||
JSTemporal##T::NowISO(isolate, args.atOrUndefined(isolate, 1))); \
|
||||
}
|
||||
|
||||
/* Temporal #sec-temporal.plaindate.from */
|
||||
TO_BE_IMPLEMENTED(TemporalPlainDateFrom)
|
||||
/* Temporal #sec-temporal.plaindate.compare */
|
||||
TO_BE_IMPLEMENTED(TemporalPlainDateCompare)
|
||||
/* Temporal #sec-temporal.plaindate.prototype.toplainyearmonth */
|
||||
@ -454,6 +452,15 @@ TO_BE_IMPLEMENTED(TemporalZonedDateTimePrototypeToLocaleString)
|
||||
args.atOrUndefined(isolate, 3))); \
|
||||
}
|
||||
|
||||
#define TEMPORAL_METHOD2(T, METHOD) \
|
||||
BUILTIN(Temporal##T##METHOD) { \
|
||||
HandleScope scope(isolate); \
|
||||
RETURN_RESULT_OR_FAILURE( \
|
||||
isolate, \
|
||||
JSTemporal##T ::METHOD(isolate, args.atOrUndefined(isolate, 1), \
|
||||
args.atOrUndefined(isolate, 2))); \
|
||||
}
|
||||
|
||||
#define TEMPORAL_VALUE_OF(T) \
|
||||
BUILTIN(Temporal##T##PrototypeValueOf) { \
|
||||
HandleScope scope(isolate); \
|
||||
@ -561,6 +568,7 @@ BUILTIN(TemporalPlainDateConstructor) {
|
||||
args.atOrUndefined(isolate, 3), // iso_day
|
||||
args.atOrUndefined(isolate, 4))); // calendar_like
|
||||
}
|
||||
TEMPORAL_METHOD2(PlainDate, From)
|
||||
TEMPORAL_GET(PlainDate, Calendar, calendar)
|
||||
TEMPORAL_GET_BY_FORWARD_CALENDAR(PlainDate, Year, year)
|
||||
TEMPORAL_GET_BY_FORWARD_CALENDAR(PlainDate, Month, month)
|
||||
|
@ -5298,6 +5298,15 @@ void Genesis::InitializeGlobal_harmony_temporal() {
|
||||
#undef INSTALL_TEMPORAL_CTOR_AND_PROTOTYPE
|
||||
#undef INSTALL_TEMPORAL_FUNC
|
||||
|
||||
// The StringListFromIterable functions is created but not
|
||||
// exposed, as it is used internally by CalendarFields.
|
||||
{
|
||||
Handle<JSFunction> func = SimpleCreateFunction(
|
||||
isolate_,
|
||||
factory()->InternalizeUtf8String("StringFixedArrayFromIterable"),
|
||||
Builtin::kStringFixedArrayFromIterable, 1, false);
|
||||
native_context()->set_string_fixed_array_from_iterable(*func);
|
||||
}
|
||||
// The TemporalInsantFixedArrayFromIterable functions is created but not
|
||||
// exposed, as it is used internally by GetPossibleInstantsFor.
|
||||
{
|
||||
|
@ -31,8 +31,6 @@
|
||||
V(_, direction_string, "direction") \
|
||||
V(_, endRange_string, "endRange") \
|
||||
V(_, engineering_string, "engineering") \
|
||||
V(_, era_string, "era") \
|
||||
V(_, eraYear_string, "eraYear") \
|
||||
V(_, exceptZero_string, "exceptZero") \
|
||||
V(_, expand_string, "expand") \
|
||||
V(_, exponentInteger_string, "exponentInteger") \
|
||||
@ -228,6 +226,8 @@
|
||||
V(_, epochMilliseconds_string, "epochMilliseconds") \
|
||||
V(_, epochNanoseconds_string, "epochNanoseconds") \
|
||||
V(_, epochSeconds_string, "epochSeconds") \
|
||||
V(_, era_string, "era") \
|
||||
V(_, eraYear_string, "eraYear") \
|
||||
V(_, errors_string, "errors") \
|
||||
V(_, error_to_string, "[object Error]") \
|
||||
V(_, eval_string, "eval") \
|
||||
|
@ -210,6 +210,8 @@ enum ContextLookupFlags {
|
||||
temporal_zoned_date_time_function) \
|
||||
V(TEMPORAL_INSTANT_FIXED_ARRAY_FROM_ITERABLE_FUNCTION_INDEX, JSFunction, \
|
||||
temporal_instant_fixed_array_from_iterable) \
|
||||
V(STRING_FIXED_ARRAY_FROM_ITERABLE_FUNCTION_INDEX, JSFunction, \
|
||||
string_fixed_array_from_iterable) \
|
||||
/* Context maps */ \
|
||||
V(NATIVE_CONTEXT_MAP_INDEX, Map, native_context_map) \
|
||||
V(FUNCTION_CONTEXT_MAP_INDEX, Map, function_context_map) \
|
||||
|
@ -197,19 +197,13 @@ Handle<String> JSListFormat::TypeAsString() const {
|
||||
|
||||
namespace {
|
||||
|
||||
// Extract String from JSArray into array of UnicodeString
|
||||
// Extract String from FixedArray into array of UnicodeString
|
||||
Maybe<std::vector<icu::UnicodeString>> ToUnicodeStringArray(
|
||||
Isolate* isolate, Handle<JSArray> array) {
|
||||
// Thanks to iterable-to-list preprocessing, we never see dictionary-mode
|
||||
// arrays here, so the loop below can construct an entry from the index.
|
||||
DCHECK(array->HasFastElements(isolate));
|
||||
auto* accessor = array->GetElementsAccessor();
|
||||
size_t length = accessor->NumberOfElements(*array);
|
||||
|
||||
Isolate* isolate, Handle<FixedArray> array) {
|
||||
int length = array->length();
|
||||
std::vector<icu::UnicodeString> result;
|
||||
for (InternalIndex entry : InternalIndex::Range(length)) {
|
||||
DCHECK(accessor->HasEntry(*array, entry));
|
||||
Handle<Object> item = accessor->Get(array, entry);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Handle<Object> item = FixedArray::get(*array, i, isolate);
|
||||
DCHECK(item->IsString());
|
||||
Handle<String> item_str = Handle<String>::cast(item);
|
||||
if (!item_str->IsFlat()) item_str = String::Flatten(isolate, item_str);
|
||||
@ -220,7 +214,7 @@ Maybe<std::vector<icu::UnicodeString>> ToUnicodeStringArray(
|
||||
|
||||
template <typename T>
|
||||
MaybeHandle<T> FormatListCommon(
|
||||
Isolate* isolate, Handle<JSListFormat> format, Handle<JSArray> list,
|
||||
Isolate* isolate, Handle<JSListFormat> format, Handle<FixedArray> list,
|
||||
const std::function<MaybeHandle<T>(Isolate*, const icu::FormattedValue&)>&
|
||||
formatToResult) {
|
||||
DCHECK(!list->IsUndefined());
|
||||
@ -283,14 +277,14 @@ MaybeHandle<JSArray> FormattedListToJSArray(
|
||||
// ecma402 #sec-formatlist
|
||||
MaybeHandle<String> JSListFormat::FormatList(Isolate* isolate,
|
||||
Handle<JSListFormat> format,
|
||||
Handle<JSArray> list) {
|
||||
Handle<FixedArray> list) {
|
||||
return FormatListCommon<String>(isolate, format, list,
|
||||
Intl::FormattedToString);
|
||||
}
|
||||
|
||||
// ecma42 #sec-formatlisttoparts
|
||||
MaybeHandle<JSArray> JSListFormat::FormatListToParts(
|
||||
Isolate* isolate, Handle<JSListFormat> format, Handle<JSArray> list) {
|
||||
Isolate* isolate, Handle<JSListFormat> format, Handle<FixedArray> list) {
|
||||
return FormatListCommon<JSArray>(isolate, format, list,
|
||||
FormattedListToJSArray);
|
||||
}
|
||||
|
@ -46,12 +46,12 @@ class JSListFormat
|
||||
// ecma402 #sec-formatlist
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> FormatList(
|
||||
Isolate* isolate, Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list);
|
||||
Handle<FixedArray> list);
|
||||
|
||||
// ecma42 #sec-formatlisttoparts
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> FormatListToParts(
|
||||
Isolate* isolate, Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list);
|
||||
Handle<FixedArray> list);
|
||||
|
||||
V8_EXPORT_PRIVATE static const std::set<std::string>& GetAvailableLocales();
|
||||
|
||||
|
@ -69,6 +69,17 @@ struct DateTimeRecordCommon {
|
||||
int32_t nanosecond;
|
||||
};
|
||||
|
||||
struct DateRecord {
|
||||
int32_t year;
|
||||
int32_t month;
|
||||
int32_t day;
|
||||
Handle<String> calendar;
|
||||
};
|
||||
|
||||
struct DateTimeRecord : public DateTimeRecordCommon {
|
||||
Handle<String> calendar;
|
||||
};
|
||||
|
||||
struct DurationRecord {
|
||||
int64_t years;
|
||||
int64_t months;
|
||||
@ -95,12 +106,19 @@ V8_WARN_UNUSED_RESULT Handle<String> UnitToString(Isolate* isolate, Unit unit);
|
||||
// #sec-temporal-totemporaldisambiguation
|
||||
enum class Disambiguation { kCompatible, kEarlier, kLater, kReject };
|
||||
|
||||
// #sec-temporal-totemporaloverflow
|
||||
enum class ShowOverflow { kConstrain, kReject };
|
||||
|
||||
// ISO8601 String Parsing
|
||||
|
||||
// #sec-temporal-parsetemporalcalendarstring
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<String> ParseTemporalCalendarString(
|
||||
Isolate* isolate, Handle<String> iso_string);
|
||||
|
||||
// #sec-temporal-parsetemporaldatestring
|
||||
V8_WARN_UNUSED_RESULT Maybe<DateRecord> ParseTemporalDateString(
|
||||
Isolate* isolate, Handle<String> iso_string);
|
||||
|
||||
// #sec-temporal-parsetemporaltimezone
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<String> ParseTemporalTimeZone(
|
||||
Isolate* isolate, Handle<String> string);
|
||||
@ -229,19 +247,32 @@ int64_t TotalDurationNanoseconds(Isolate* isolate, int64_t days, int64_t hours,
|
||||
|
||||
// Calendar Operations
|
||||
|
||||
// #sec-temporal-calendardateadd
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalPlainDate> CalendarDateAdd(
|
||||
Isolate* isolate, Handle<JSReceiver> calendar, Handle<Object> date,
|
||||
Handle<Object> durations, Handle<Object> options, Handle<Object> date_add);
|
||||
|
||||
// #sec-temporal-calendardateuntil
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalDuration> CalendarDateUntil(
|
||||
Isolate* isolate, Handle<JSReceiver> calendar, Handle<Object> one,
|
||||
Handle<Object> two, Handle<Object> options, Handle<Object> date_until);
|
||||
|
||||
// #sec-temporal-calendarfields
|
||||
MaybeHandle<FixedArray> CalendarFields(Isolate* isolate,
|
||||
Handle<JSReceiver> calendar,
|
||||
Handle<FixedArray> field_names);
|
||||
|
||||
// #sec-temporal-getoffsetnanosecondsfor
|
||||
V8_WARN_UNUSED_RESULT Maybe<int64_t> GetOffsetNanosecondsFor(
|
||||
Isolate* isolate, Handle<JSReceiver> time_zone, Handle<Object> instant,
|
||||
const char* method_name);
|
||||
|
||||
// #sec-temporal-totemporalcalendarwithisodefault
|
||||
MaybeHandle<JSReceiver> ToTemporalCalendarWithISODefault(
|
||||
Isolate* isolate, Handle<Object> temporal_calendar_like,
|
||||
const char* method_name);
|
||||
|
||||
// #sec-temporal-isbuiltincalendar
|
||||
bool IsBuiltinCalendar(Isolate* isolate, Handle<String> id);
|
||||
|
||||
// Internal Helper Function
|
||||
@ -254,6 +285,14 @@ bool IsValidTimeZoneName(Isolate* isolate, Handle<String> time_zone);
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<String> CanonicalizeTimeZoneName(
|
||||
Isolate* isolate, Handle<String> identifier);
|
||||
|
||||
// #sec-temporal-tointegerthrowoninfinity
|
||||
MaybeHandle<Object> ToIntegerThrowOnInfinity(Isolate* isolate,
|
||||
Handle<Object> argument);
|
||||
|
||||
// #sec-temporal-topositiveinteger
|
||||
MaybeHandle<Object> ToPositiveInteger(Isolate* isolate,
|
||||
Handle<Object> argument);
|
||||
|
||||
inline int64_t floor_divide(int64_t a, int64_t b) {
|
||||
return (((a) / (b)) + ((((a) < 0) && (((a) % (b)) != 0)) ? -1 : 0));
|
||||
}
|
||||
@ -1241,7 +1280,7 @@ MaybeHandle<JSTemporalInstant> DisambiguatePossibleInstants(
|
||||
date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(),
|
||||
date_time->iso_second(), date_time->iso_millisecond(),
|
||||
date_time->iso_microsecond(), date_time->iso_nanosecond(),
|
||||
Handle<JSReceiver>(date_time->calendar(), isolate),
|
||||
handle(date_time->calendar(), isolate),
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds},
|
||||
isolate->factory()->undefined_value());
|
||||
MAYBE_RETURN(maybe_earlier, Handle<JSTemporalInstant>());
|
||||
@ -1259,7 +1298,7 @@ MaybeHandle<JSTemporalInstant> DisambiguatePossibleInstants(
|
||||
isolate, earlier.year, earlier.month, earlier.day, earlier.hour,
|
||||
earlier.minute, earlier.second, earlier.millisecond,
|
||||
earlier.microsecond, earlier.nanosecond,
|
||||
Handle<JSReceiver>(date_time->calendar(), isolate)),
|
||||
handle(date_time->calendar(), isolate)),
|
||||
JSTemporalInstant);
|
||||
|
||||
// c. Set possibleInstants to ? GetPossibleInstantsFor(timeZone,
|
||||
@ -1292,7 +1331,7 @@ MaybeHandle<JSTemporalInstant> DisambiguatePossibleInstants(
|
||||
date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(),
|
||||
date_time->iso_second(), date_time->iso_millisecond(),
|
||||
date_time->iso_microsecond(), date_time->iso_nanosecond(),
|
||||
Handle<JSReceiver>(date_time->calendar(), isolate),
|
||||
handle(date_time->calendar(), isolate),
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds},
|
||||
isolate->factory()->undefined_value());
|
||||
MAYBE_RETURN(maybe_later, Handle<JSTemporalInstant>());
|
||||
@ -1310,7 +1349,7 @@ MaybeHandle<JSTemporalInstant> DisambiguatePossibleInstants(
|
||||
temporal::CreateTemporalDateTime(
|
||||
isolate, later.year, later.month, later.day, later.hour, later.minute,
|
||||
later.second, later.millisecond, later.microsecond, later.nanosecond,
|
||||
Handle<JSReceiver>(date_time->calendar(), isolate)),
|
||||
handle(date_time->calendar(), isolate)),
|
||||
JSTemporalInstant);
|
||||
// 17. Set possibleInstants to ? GetPossibleInstantsFor(timeZone,
|
||||
// laterDateTime).
|
||||
@ -1331,6 +1370,215 @@ MaybeHandle<JSTemporalInstant> DisambiguatePossibleInstants(
|
||||
return Handle<JSTemporalInstant>::cast(ret_obj);
|
||||
}
|
||||
|
||||
// #sec-temporal-gettemporalcalendarwithisodefault
|
||||
MaybeHandle<JSReceiver> GetTemporalCalendarWithISODefault(
|
||||
Isolate* isolate, Handle<JSReceiver> item, const char* method_name) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
// 1. If item has an [[InitializedTemporalDate]],
|
||||
// [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]],
|
||||
// [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or
|
||||
// [[InitializedTemporalZonedDateTime]] internal slot, then a. Return
|
||||
// item.[[Calendar]].
|
||||
if (item->IsJSTemporalPlainDate()) {
|
||||
return handle(Handle<JSTemporalPlainDate>::cast(item)->calendar(), isolate);
|
||||
}
|
||||
if (item->IsJSTemporalPlainDateTime()) {
|
||||
return handle(Handle<JSTemporalPlainDateTime>::cast(item)->calendar(),
|
||||
isolate);
|
||||
}
|
||||
if (item->IsJSTemporalPlainMonthDay()) {
|
||||
return handle(Handle<JSTemporalPlainMonthDay>::cast(item)->calendar(),
|
||||
isolate);
|
||||
}
|
||||
if (item->IsJSTemporalPlainTime()) {
|
||||
return handle(Handle<JSTemporalPlainTime>::cast(item)->calendar(), isolate);
|
||||
}
|
||||
if (item->IsJSTemporalPlainYearMonth()) {
|
||||
return handle(Handle<JSTemporalPlainYearMonth>::cast(item)->calendar(),
|
||||
isolate);
|
||||
}
|
||||
if (item->IsJSTemporalZonedDateTime()) {
|
||||
return handle(Handle<JSTemporalZonedDateTime>::cast(item)->calendar(),
|
||||
isolate);
|
||||
}
|
||||
|
||||
// 2. Let calendar be ? Get(item, "calendar").
|
||||
Handle<Object> calendar;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, calendar,
|
||||
JSReceiver::GetProperty(isolate, item, factory->calendar_string()),
|
||||
JSReceiver);
|
||||
// 3. Return ? ToTemporalCalendarWithISODefault(calendar).
|
||||
return ToTemporalCalendarWithISODefault(isolate, calendar, method_name);
|
||||
}
|
||||
|
||||
enum class RequiredFields { kNone, kTimeZone, kTimeZoneAndOffset, kDay };
|
||||
|
||||
// The common part of PrepareTemporalFields and PreparePartialTemporalFields
|
||||
// #sec-temporal-preparetemporalfields
|
||||
// #sec-temporal-preparepartialtemporalfields
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> PrepareTemporalFieldsOrPartial(
|
||||
Isolate* isolate, Handle<JSReceiver> fields, Handle<FixedArray> field_names,
|
||||
RequiredFields required, bool partial) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
// 1. Assert: Type(fields) is Object.
|
||||
// 2. Let result be ! OrdinaryObjectCreate(%Object.prototype%).
|
||||
Handle<JSObject> result =
|
||||
isolate->factory()->NewJSObject(isolate->object_function());
|
||||
// 3. For each value property of fieldNames, do
|
||||
int length = field_names->length();
|
||||
bool any = false;
|
||||
for (int i = 0; i < length; i++) {
|
||||
Handle<Object> property_obj = Handle<Object>(field_names->get(i), isolate);
|
||||
Handle<String> property = Handle<String>::cast(property_obj);
|
||||
// a. Let value be ? Get(fields, property).
|
||||
Handle<Object> value;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, value, JSReceiver::GetProperty(isolate, fields, property),
|
||||
JSObject);
|
||||
|
||||
// b. If value is undefined, then
|
||||
if (value->IsUndefined()) {
|
||||
// This part is only for PrepareTemporalFields
|
||||
// Skip for the case of PreparePartialTemporalFields.
|
||||
if (partial) continue;
|
||||
|
||||
// i. If requiredFields contains property, then
|
||||
if ((required == RequiredFields::kDay &&
|
||||
String::Equals(isolate, property, factory->day_string())) ||
|
||||
((required == RequiredFields::kTimeZone ||
|
||||
required == RequiredFields::kTimeZoneAndOffset) &&
|
||||
String::Equals(isolate, property, factory->timeZone_string())) ||
|
||||
(required == RequiredFields::kTimeZoneAndOffset &&
|
||||
String::Equals(isolate, property, factory->offset_string()))) {
|
||||
// 1. Throw a TypeError exception.
|
||||
THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(),
|
||||
JSObject);
|
||||
}
|
||||
// ii. Else,
|
||||
// 1. If property is in the Property column of Table 13, then
|
||||
// a. Set value to the corresponding Default value of the same row.
|
||||
if (String::Equals(isolate, property, factory->hour_string()) ||
|
||||
String::Equals(isolate, property, factory->minute_string()) ||
|
||||
String::Equals(isolate, property, factory->second_string()) ||
|
||||
String::Equals(isolate, property, factory->millisecond_string()) ||
|
||||
String::Equals(isolate, property, factory->microsecond_string()) ||
|
||||
String::Equals(isolate, property, factory->nanosecond_string())) {
|
||||
value = Handle<Object>(Smi::zero(), isolate);
|
||||
}
|
||||
} else {
|
||||
// For both PrepareTemporalFields and PreparePartialTemporalFields
|
||||
any = partial;
|
||||
// c. Else,
|
||||
// i. If property is in the Property column of Table 13 and there is a
|
||||
// Conversion value in the same row, then
|
||||
// 1. Let Conversion represent the abstract operation named by the
|
||||
// Conversion value of the same row.
|
||||
// 2. Set value to ? Conversion(value).
|
||||
if (String::Equals(isolate, property, factory->month_string()) ||
|
||||
String::Equals(isolate, property, factory->day_string())) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
|
||||
ToPositiveInteger(isolate, value), JSObject);
|
||||
} else if (String::Equals(isolate, property, factory->year_string()) ||
|
||||
String::Equals(isolate, property, factory->hour_string()) ||
|
||||
String::Equals(isolate, property, factory->minute_string()) ||
|
||||
String::Equals(isolate, property, factory->second_string()) ||
|
||||
String::Equals(isolate, property,
|
||||
factory->millisecond_string()) ||
|
||||
String::Equals(isolate, property,
|
||||
factory->microsecond_string()) ||
|
||||
String::Equals(isolate, property,
|
||||
factory->nanosecond_string()) ||
|
||||
String::Equals(isolate, property, factory->eraYear_string())) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, value, ToIntegerThrowOnInfinity(isolate, value), JSObject);
|
||||
} else if (String::Equals(isolate, property,
|
||||
factory->monthCode_string()) ||
|
||||
String::Equals(isolate, property, factory->offset_string()) ||
|
||||
String::Equals(isolate, property, factory->era_string())) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
|
||||
Object::ToString(isolate, value), JSObject);
|
||||
}
|
||||
}
|
||||
|
||||
// d. Perform ! CreateDataPropertyOrThrow(result, property, value).
|
||||
CHECK(JSReceiver::CreateDataProperty(isolate, result, property, value,
|
||||
Just(kThrowOnError))
|
||||
.FromJust());
|
||||
}
|
||||
|
||||
// Only for PreparePartialTemporalFields
|
||||
if (partial) {
|
||||
// 5. If any is false, then
|
||||
if (!any) {
|
||||
// a. Throw a TypeError exception.
|
||||
THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), JSObject);
|
||||
}
|
||||
}
|
||||
// 4. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
// #sec-temporal-preparetemporalfields
|
||||
V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> PrepareTemporalFields(
|
||||
Isolate* isolate, Handle<JSReceiver> fields, Handle<FixedArray> field_names,
|
||||
RequiredFields required) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
|
||||
return PrepareTemporalFieldsOrPartial(isolate, fields, field_names, required,
|
||||
false);
|
||||
}
|
||||
|
||||
// Template for DateFromFields, YearMonthFromFields, and MonthDayFromFields
|
||||
template <typename T>
|
||||
MaybeHandle<T> FromFields(Isolate* isolate, Handle<JSReceiver> calendar,
|
||||
Handle<JSReceiver> fields, Handle<Object> options,
|
||||
Handle<String> property, InstanceType type) {
|
||||
Handle<Object> function;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, function, Object::GetProperty(isolate, calendar, property), T);
|
||||
if (!function->IsCallable()) {
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kCalledNonCallable, property),
|
||||
T);
|
||||
}
|
||||
Handle<Object> argv[] = {fields, options};
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, result, Execution::Call(isolate, function, calendar, 2, argv),
|
||||
T);
|
||||
if ((!result->IsHeapObject()) ||
|
||||
HeapObject::cast(*result).map().instance_type() != type) {
|
||||
THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), T);
|
||||
}
|
||||
return Handle<T>::cast(result);
|
||||
}
|
||||
|
||||
MaybeHandle<JSTemporalPlainDate> DateFromFields(Isolate* isolate,
|
||||
Handle<JSReceiver> calendar,
|
||||
Handle<JSReceiver> fields,
|
||||
Handle<Object> options) {
|
||||
return FromFields<JSTemporalPlainDate>(
|
||||
isolate, calendar, fields, options,
|
||||
isolate->factory()->dateFromFields_string(), JS_TEMPORAL_PLAIN_DATE_TYPE);
|
||||
}
|
||||
|
||||
// IMPL_FROM_FIELDS_ABSTRACT_OPERATION(Date, date, JS_TEMPORAL_PLAIN_DATE_TYPE)
|
||||
#undef IMPL_FROM_FIELDS_ABSTRACT_OPERATION
|
||||
// #sec-temporal-totemporaloverflow
|
||||
Maybe<ShowOverflow> ToTemporalOverflow(Isolate* isolate,
|
||||
Handle<JSReceiver> options,
|
||||
const char* method_name) {
|
||||
return GetStringOption<ShowOverflow>(
|
||||
isolate, options, "overflow", method_name, {"constrain", "reject"},
|
||||
{ShowOverflow::kConstrain, ShowOverflow::kReject},
|
||||
ShowOverflow::kConstrain);
|
||||
}
|
||||
|
||||
// #sec-temporal-builtintimezonegetinstantfor
|
||||
MaybeHandle<JSTemporalInstant> BuiltinTimeZoneGetInstantFor(
|
||||
Isolate* isolate, Handle<JSReceiver> time_zone,
|
||||
@ -1365,10 +1613,9 @@ MaybeHandle<JSReceiver> ToTemporalCalendar(
|
||||
// [[InitializedTemporalZonedDateTime]] internal slot, then i. Return
|
||||
// temporalCalendarLike.[[Calendar]].
|
||||
|
||||
#define EXTRACT_CALENDAR(T, obj) \
|
||||
if (obj->IsJSTemporal##T()) { \
|
||||
return Handle<JSReceiver>(Handle<JSTemporal##T>::cast(obj)->calendar(), \
|
||||
isolate); \
|
||||
#define EXTRACT_CALENDAR(T, obj) \
|
||||
if (obj->IsJSTemporal##T()) { \
|
||||
return handle(Handle<JSTemporal##T>::cast(obj)->calendar(), isolate); \
|
||||
}
|
||||
|
||||
EXTRACT_CALENDAR(PlainDate, temporal_calendar_like)
|
||||
@ -1444,9 +1691,133 @@ MaybeHandle<JSReceiver> ToTemporalCalendarWithISODefault(
|
||||
method_name);
|
||||
}
|
||||
|
||||
// #sec-temporal-totemporaldate
|
||||
MaybeHandle<JSTemporalPlainDate> ToTemporalDate(Isolate* isolate,
|
||||
Handle<Object> item_obj,
|
||||
Handle<JSReceiver> options,
|
||||
const char* method_name) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
// 2. Assert: Type(options) is Object.
|
||||
// 3. If Type(item) is Object, then
|
||||
if (item_obj->IsJSReceiver()) {
|
||||
Handle<JSReceiver> item = Handle<JSReceiver>::cast(item_obj);
|
||||
// a. If item has an [[InitializedTemporalDate]] internal slot, then
|
||||
// i. Return item.
|
||||
if (item->IsJSTemporalPlainDate()) {
|
||||
return Handle<JSTemporalPlainDate>::cast(item);
|
||||
}
|
||||
// b. If item has an [[InitializedTemporalZonedDateTime]] internal slot,
|
||||
// then
|
||||
if (item->IsJSTemporalZonedDateTime()) {
|
||||
// i. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]).
|
||||
Handle<JSTemporalZonedDateTime> zoned_date_time =
|
||||
Handle<JSTemporalZonedDateTime>::cast(item);
|
||||
Handle<JSTemporalInstant> instant;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, instant,
|
||||
temporal::CreateTemporalInstant(
|
||||
isolate, Handle<BigInt>(zoned_date_time->nanoseconds(), isolate)),
|
||||
JSTemporalPlainDate);
|
||||
// ii. Let plainDateTime be ?
|
||||
// BuiltinTimeZoneGetPlainDateTimeFor(item.[[TimeZone]],
|
||||
// instant, item.[[Calendar]]).
|
||||
Handle<JSTemporalPlainDateTime> plain_date_time;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, plain_date_time,
|
||||
temporal::BuiltinTimeZoneGetPlainDateTimeFor(
|
||||
isolate,
|
||||
Handle<JSReceiver>(zoned_date_time->time_zone(), isolate),
|
||||
instant, Handle<JSReceiver>(zoned_date_time->calendar(), isolate),
|
||||
method_name),
|
||||
JSTemporalPlainDate);
|
||||
// iii. Return ! CreateTemporalDate(plainDateTime.[[ISOYear]],
|
||||
// plainDateTime.[[ISOMonth]], plainDateTime.[[ISODay]],
|
||||
// plainDateTime.[[Calendar]]).
|
||||
return CreateTemporalDate(
|
||||
isolate, plain_date_time->iso_year(), plain_date_time->iso_month(),
|
||||
plain_date_time->iso_day(),
|
||||
Handle<JSReceiver>(plain_date_time->calendar(), isolate));
|
||||
}
|
||||
|
||||
// c. If item has an [[InitializedTemporalDateTime]] internal slot, then
|
||||
// i. Return ! CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]],
|
||||
// item.[[ISODay]], item.[[Calendar]]).
|
||||
if (item->IsJSTemporalPlainDateTime()) {
|
||||
Handle<JSTemporalPlainDateTime> date_time =
|
||||
Handle<JSTemporalPlainDateTime>::cast(item);
|
||||
return CreateTemporalDate(isolate, date_time->iso_year(),
|
||||
date_time->iso_month(), date_time->iso_day(),
|
||||
handle(date_time->calendar(), isolate));
|
||||
}
|
||||
|
||||
// d. Let calendar be ? GetTemporalCalendarWithISODefault(item).
|
||||
Handle<JSReceiver> calendar;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, calendar,
|
||||
GetTemporalCalendarWithISODefault(isolate, item, method_name),
|
||||
JSTemporalPlainDate);
|
||||
// e. Let fieldNames be ? CalendarFields(calendar, « "day", "month",
|
||||
// "monthCode", "year" »).
|
||||
Handle<FixedArray> field_names = factory->NewFixedArray(4);
|
||||
field_names->set(0, *(factory->day_string()));
|
||||
field_names->set(1, *(factory->month_string()));
|
||||
field_names->set(2, *(factory->monthCode_string()));
|
||||
field_names->set(3, *(factory->year_string()));
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, field_names,
|
||||
CalendarFields(isolate, calendar, field_names),
|
||||
JSTemporalPlainDate);
|
||||
// f. Let fields be ? PrepareTemporalFields(item,
|
||||
// fieldNames, «»).
|
||||
Handle<JSReceiver> fields;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, fields,
|
||||
PrepareTemporalFields(isolate, item, field_names,
|
||||
RequiredFields::kNone),
|
||||
JSTemporalPlainDate);
|
||||
// g. Return ? DateFromFields(calendar, fields, options).
|
||||
return DateFromFields(isolate, calendar, fields, options);
|
||||
}
|
||||
// 4. Perform ? ToTemporalOverflow(options).
|
||||
Maybe<ShowOverflow> maybe_overflow =
|
||||
ToTemporalOverflow(isolate, options, method_name);
|
||||
MAYBE_RETURN(maybe_overflow, Handle<JSTemporalPlainDate>());
|
||||
|
||||
// 5. Let string be ? ToString(item).
|
||||
Handle<String> string;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, string,
|
||||
Object::ToString(isolate, item_obj),
|
||||
JSTemporalPlainDate);
|
||||
// 6. Let result be ? ParseTemporalDateString(string).
|
||||
Maybe<DateRecord> maybe_result = ParseTemporalDateString(isolate, string);
|
||||
MAYBE_RETURN(maybe_result, MaybeHandle<JSTemporalPlainDate>());
|
||||
DateRecord result = maybe_result.FromJust();
|
||||
|
||||
// 7. Assert: ! IsValidISODate(result.[[Year]], result.[[Month]],
|
||||
// result.[[Day]]) is true.
|
||||
DCHECK(IsValidISODate(isolate, result.year, result.month, result.day));
|
||||
// 8. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]).
|
||||
Handle<Object> calendar_string;
|
||||
if (result.calendar->length() == 0) {
|
||||
calendar_string = factory->undefined_value();
|
||||
} else {
|
||||
calendar_string = result.calendar;
|
||||
}
|
||||
Handle<JSReceiver> calendar;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, calendar,
|
||||
ToTemporalCalendarWithISODefault(isolate, calendar_string, method_name),
|
||||
JSTemporalPlainDate);
|
||||
// 9. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]],
|
||||
// result.[[Day]], calendar).
|
||||
return CreateTemporalDate(isolate, result.year, result.month, result.day,
|
||||
calendar);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace temporal {
|
||||
|
||||
// #sec-temporal-totemporaltimezone
|
||||
MaybeHandle<JSReceiver> ToTemporalTimeZone(
|
||||
Isolate* isolate, Handle<Object> temporal_time_zone_like,
|
||||
@ -1462,7 +1833,7 @@ MaybeHandle<JSReceiver> ToTemporalTimeZone(
|
||||
// i. Return temporalTimeZoneLike.[[TimeZone]].
|
||||
Handle<JSTemporalZonedDateTime> zoned_date_time =
|
||||
Handle<JSTemporalZonedDateTime>::cast(temporal_time_zone_like);
|
||||
return Handle<JSReceiver>(zoned_date_time->time_zone(), isolate);
|
||||
return handle(zoned_date_time->time_zone(), isolate);
|
||||
}
|
||||
Handle<JSReceiver> obj = Handle<JSReceiver>::cast(temporal_time_zone_like);
|
||||
// b. If ? HasProperty(temporalTimeZoneLike, "timeZone") is false,
|
||||
@ -1658,6 +2029,130 @@ MaybeHandle<String> BuiltinTimeZoneGetOffsetStringFor(
|
||||
return FormatTimeZoneOffsetString(isolate, offset_nanoseconds);
|
||||
}
|
||||
|
||||
// #sec-temporal-parseisodatetime
|
||||
Maybe<DateTimeRecord> ParseISODateTime(Isolate* isolate,
|
||||
Handle<String> iso_string,
|
||||
const ParsedISO8601Result& parsed) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
|
||||
DateTimeRecord result;
|
||||
// 5. Set year to ! ToIntegerOrInfinity(year).
|
||||
result.year = parsed.date_year;
|
||||
// 6. If month is undefined, then
|
||||
if (parsed.date_month_is_undefined()) {
|
||||
// a. Set month to 1.
|
||||
result.month = 1;
|
||||
// 7. Else,
|
||||
} else {
|
||||
// a. Set month to ! ToIntegerOrInfinity(month).
|
||||
result.month = parsed.date_month;
|
||||
}
|
||||
|
||||
// 8. If day is undefined, then
|
||||
if (parsed.date_day_is_undefined()) {
|
||||
// a. Set day to 1.
|
||||
result.day = 1;
|
||||
// 9. Else,
|
||||
} else {
|
||||
// a. Set day to ! ToIntegerOrInfinity(day).
|
||||
result.day = parsed.date_day;
|
||||
}
|
||||
// 10. Set hour to ! ToIntegerOrInfinity(hour).
|
||||
result.hour = parsed.time_hour_is_undefined() ? 0 : parsed.time_hour;
|
||||
// 11. Set minute to ! ToIntegerOrInfinity(minute).
|
||||
result.minute = parsed.time_minute_is_undefined() ? 0 : parsed.time_minute;
|
||||
// 12. Set second to ! ToIntegerOrInfinity(second).
|
||||
result.second = parsed.time_second_is_undefined() ? 0 : parsed.time_second;
|
||||
// 13. If second is 60, then
|
||||
if (result.second == 60) {
|
||||
// a. Set second to 59.
|
||||
result.second = 59;
|
||||
}
|
||||
// 14. If fraction is not undefined, then
|
||||
if (!parsed.time_nanosecond_is_undefined()) {
|
||||
// a. Set fraction to the string-concatenation of the previous value of
|
||||
// fraction and the string "000000000".
|
||||
// b. Let millisecond be the String value equal to the substring of fraction
|
||||
// from 0 to 3. c. Set millisecond to ! ToIntegerOrInfinity(millisecond).
|
||||
result.millisecond = parsed.time_nanosecond / 1000000;
|
||||
// d. Let microsecond be the String value equal to the substring of fraction
|
||||
// from 3 to 6. e. Set microsecond to ! ToIntegerOrInfinity(microsecond).
|
||||
result.microsecond = (parsed.time_nanosecond / 1000) % 1000;
|
||||
// f. Let nanosecond be the String value equal to the substring of fraction
|
||||
// from 6 to 9. g. Set nanosecond to ! ToIntegerOrInfinity(nanosecond).
|
||||
result.nanosecond = (parsed.time_nanosecond % 1000);
|
||||
// 15. Else,
|
||||
} else {
|
||||
// a. Let millisecond be 0.
|
||||
result.millisecond = 0;
|
||||
// b. Let microsecond be 0.
|
||||
result.microsecond = 0;
|
||||
// c. Let nanosecond be 0.
|
||||
result.nanosecond = 0;
|
||||
}
|
||||
// 16. If ! IsValidISODate(year, month, day) is false, throw a RangeError
|
||||
// exception.
|
||||
if (!IsValidISODate(isolate, result.year, result.month, result.day)) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(),
|
||||
Nothing<DateTimeRecord>());
|
||||
}
|
||||
// 17. If ! IsValidTime(hour, minute, second, millisecond, microsecond,
|
||||
// nanosecond) is false, throw a RangeError exception.
|
||||
if (!IsValidTime(isolate, result.hour, result.minute, result.second,
|
||||
result.millisecond, result.microsecond, result.nanosecond)) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(),
|
||||
Nothing<DateTimeRecord>());
|
||||
}
|
||||
// 18. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day,
|
||||
// [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]:
|
||||
// millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond,
|
||||
// [[Calendar]]: calendar }.
|
||||
if (parsed.calendar_name_length == 0) {
|
||||
result.calendar = isolate->factory()->empty_string();
|
||||
} else {
|
||||
result.calendar = isolate->factory()->NewSubString(
|
||||
iso_string, parsed.calendar_name_start,
|
||||
parsed.calendar_name_start + parsed.calendar_name_length);
|
||||
}
|
||||
return Just(result);
|
||||
}
|
||||
|
||||
// #sec-temporal-parsetemporaldatestring
|
||||
Maybe<DateRecord> ParseTemporalDateString(Isolate* isolate,
|
||||
Handle<String> iso_string) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
// 1. Assert: Type(isoString) is String.
|
||||
// 2. If isoString does not satisfy the syntax of a TemporalDateString
|
||||
// (see 13.33), then
|
||||
Maybe<ParsedISO8601Result> maybe_parsed =
|
||||
TemporalParser::ParseTemporalDateString(isolate, iso_string);
|
||||
if (maybe_parsed.IsNothing()) {
|
||||
// a. Throw a *RangeError* exception.
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(),
|
||||
Nothing<DateRecord>());
|
||||
}
|
||||
MAYBE_RETURN(maybe_parsed, Nothing<DateRecord>());
|
||||
|
||||
ParsedISO8601Result parsed = maybe_parsed.FromJust();
|
||||
// 3. If _isoString_ contains a |UTCDesignator|, then
|
||||
if (parsed.utc_designator) {
|
||||
// a. Throw a *RangeError* exception.
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(),
|
||||
Nothing<DateRecord>());
|
||||
}
|
||||
// 3. Let result be ? ParseISODateTime(isoString).
|
||||
Maybe<DateTimeRecord> maybe_result =
|
||||
ParseISODateTime(isolate, iso_string, parsed);
|
||||
|
||||
MAYBE_RETURN(maybe_result, Nothing<DateRecord>());
|
||||
DateTimeRecord result = maybe_result.FromJust();
|
||||
// 4. Return the Record { [[Year]]: result.[[Year]], [[Month]]:
|
||||
// result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]:
|
||||
// result.[[Calendar]] }.
|
||||
DateRecord ret = {result.year, result.month, result.day, result.calendar};
|
||||
return Just(ret);
|
||||
}
|
||||
|
||||
// #sec-temporal-parsetemporaltimezonestring
|
||||
Maybe<TimeZoneRecord> ParseTemporalTimeZoneString(Isolate* isolate,
|
||||
Handle<String> iso_string) {
|
||||
@ -1903,6 +2398,39 @@ MaybeHandle<String> ParseTemporalCalendarString(Isolate* isolate,
|
||||
return id;
|
||||
}
|
||||
|
||||
// #sec-temporal-calendarfields
|
||||
MaybeHandle<FixedArray> CalendarFields(Isolate* isolate,
|
||||
Handle<JSReceiver> calendar,
|
||||
Handle<FixedArray> field_names) {
|
||||
// 1. Let fields be ? GetMethod(calendar, "fields").
|
||||
Handle<Object> fields;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, fields,
|
||||
Object::GetMethod(calendar, isolate->factory()->fields_string()),
|
||||
FixedArray);
|
||||
// 2. Let fieldsArray be ! CreateArrayFromList(fieldNames).
|
||||
Handle<Object> fields_array =
|
||||
isolate->factory()->NewJSArrayWithElements(field_names);
|
||||
// 3. If fields is not undefined, then
|
||||
if (!fields->IsUndefined()) {
|
||||
// a. Set fieldsArray to ? Call(fields, calendar, « fieldsArray »).
|
||||
Handle<Object> argv[] = {fields_array};
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, fields_array,
|
||||
Execution::Call(isolate, fields, calendar, 1, argv), FixedArray);
|
||||
}
|
||||
// 4. Return ? IterableToListOfType(fieldsArray, « String »).
|
||||
Handle<Object> argv[] = {fields_array};
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, fields_array,
|
||||
Execution::CallBuiltin(isolate,
|
||||
isolate->string_fixed_array_from_iterable(),
|
||||
fields_array, 1, argv),
|
||||
FixedArray);
|
||||
DCHECK(fields_array->IsFixedArray());
|
||||
return Handle<FixedArray>::cast(fields_array);
|
||||
}
|
||||
|
||||
MaybeHandle<JSTemporalPlainDate> CalendarDateAdd(Isolate* isolate,
|
||||
Handle<JSReceiver> calendar,
|
||||
Handle<Object> date,
|
||||
@ -2033,9 +2561,7 @@ Maybe<int64_t> GetOffsetNanosecondsFor(Isolate* isolate,
|
||||
return Just(offset_nanoseconds_int);
|
||||
}
|
||||
|
||||
MaybeHandle<Object> ToIntegerThrowOnInfinity(Isolate* isolate,
|
||||
Handle<Object> argument);
|
||||
|
||||
// #sec-temporal-topositiveinteger
|
||||
MaybeHandle<Object> ToPositiveInteger(Isolate* isolate,
|
||||
Handle<Object> argument) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
@ -2315,6 +2841,7 @@ MaybeHandle<JSObject> MergeLargestUnitOption(Isolate* isolate,
|
||||
return merged;
|
||||
}
|
||||
|
||||
// #sec-temporal-tointegerthrowoninfinity
|
||||
MaybeHandle<Object> ToIntegerThrowOnInfinity(Isolate* isolate,
|
||||
Handle<Object> argument) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
@ -2330,6 +2857,7 @@ MaybeHandle<Object> ToIntegerThrowOnInfinity(Isolate* isolate,
|
||||
return argument;
|
||||
}
|
||||
|
||||
// #sec-temporal-largeroftwotemporalunits
|
||||
Unit LargerOfTwoTemporalUnits(Isolate* isolate, Unit u1, Unit u2) {
|
||||
// 1. If either u1 or u2 is "year", return "year".
|
||||
if (u1 == Unit::kYear || u2 == Unit::kYear) return Unit::kYear;
|
||||
@ -3977,6 +4505,33 @@ MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::NowISO(
|
||||
Handle<JSReceiver>(date_time->calendar(), isolate));
|
||||
}
|
||||
|
||||
// #sec-temporal.plaindate.from
|
||||
MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::From(
|
||||
Isolate* isolate, Handle<Object> item, Handle<Object> options_obj) {
|
||||
const char* method_name = "Temporal.PlainDate.from";
|
||||
// 1. Set options to ? GetOptionsObject(options).
|
||||
Handle<JSReceiver> options;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, options, GetOptionsObject(isolate, options_obj, method_name),
|
||||
JSTemporalPlainDate);
|
||||
// 2. If Type(item) is Object and item has an [[InitializedTemporalDate]]
|
||||
// internal slot, then
|
||||
if (item->IsJSTemporalPlainDate()) {
|
||||
// a. Perform ? ToTemporalOverflow(options).
|
||||
Maybe<ShowOverflow> maybe_overflow =
|
||||
ToTemporalOverflow(isolate, options, method_name);
|
||||
MAYBE_RETURN(maybe_overflow, Handle<JSTemporalPlainDate>());
|
||||
// b. Return ? CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]],
|
||||
// item.[[ISODay]], item.[[Calendar]]).
|
||||
Handle<JSTemporalPlainDate> date = Handle<JSTemporalPlainDate>::cast(item);
|
||||
return CreateTemporalDate(isolate, date->iso_year(), date->iso_month(),
|
||||
date->iso_day(),
|
||||
Handle<JSReceiver>(date->calendar(), isolate));
|
||||
}
|
||||
// 3. Return ? ToTemporalDate(item, options).
|
||||
return ToTemporalDate(isolate, item, options, method_name);
|
||||
}
|
||||
|
||||
#define DEFINE_INT_FIELD(obj, str, field, item) \
|
||||
CHECK(JSReceiver::CreateDataProperty( \
|
||||
isolate, obj, factory->str##_string(), \
|
||||
|
@ -123,6 +123,10 @@ class JSTemporalPlainDate
|
||||
Isolate* isolate, Handle<JSTemporalPlainDate> plain_date,
|
||||
Handle<Object> calendar_like);
|
||||
|
||||
// #sec-temporal.plaindate.from
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<JSTemporalPlainDate> From(
|
||||
Isolate* isolate, Handle<Object> item, Handle<Object> options);
|
||||
|
||||
// #sec-temporal.plaindate.prototype.getisofields
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> GetISOFields(
|
||||
Isolate* isolate, Handle<JSTemporalPlainDate> plain_date);
|
||||
|
@ -37,7 +37,7 @@ RUNTIME_FUNCTION(Runtime_FormatList) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSListFormat, list_format, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, list, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(FixedArray, list, 1);
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, JSListFormat::FormatList(isolate, list_format, list));
|
||||
}
|
||||
@ -47,7 +47,7 @@ RUNTIME_FUNCTION(Runtime_FormatListToParts) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSListFormat, list_format, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, list, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(FixedArray, list, 1);
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, JSListFormat::FormatListToParts(isolate, list_format, list));
|
||||
}
|
||||
|
@ -986,17 +986,10 @@
|
||||
'built-ins/Temporal/PlainDate/from/argument-plaindate': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-plaindatetime': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-string': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-string-invalid': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-string-with-utc-designator': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/calendar-fields-iterable': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/calendar-temporal-object': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/infinity-throws-rangeerror': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/limits': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/options-invalid': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/options-undefined': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/order-of-operations': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/overflow-invalid-string': [FAIL],
|
||||
@ -1175,7 +1168,6 @@
|
||||
'built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/until/weeks-months': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/valueOf/basic': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/weekOfYear/basic': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/with/basic': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/with/branding': [FAIL],
|
||||
@ -2492,7 +2484,6 @@
|
||||
'built-ins/Temporal/PlainDate/from/argument-object-invalid': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-object-valid': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-string-overflow': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/argument-string-trailing-junk': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/from/year-zero': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/add/argument-invalid-duration': [FAIL],
|
||||
'built-ins/Temporal/PlainDate/prototype/add/argument-missing-properties': [FAIL],
|
||||
|
Loading…
Reference in New Issue
Block a user