1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 20:05:06 +00:00
serenity/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp
Linus Groh 50428ea8d2 LibJS: Move intrinsics to the realm
Intrinsics, i.e. mostly constructor and prototype objects, but also
things like empty and new object shape now live on a new heap-allocated
JS::Intrinsics object, thus completing the long journey of taking all
the magic away from the global object.
This represents the Realm's [[Intrinsics]] slot in the spec and matches
its existing [[GlobalObject]] / [[GlobalEnv]] slots in terms of
architecture.

In the majority of cases it should now be possibly to fully allocate a
regular object without the global object existing, and in fact that's
what we do now - the realm is allocated before the global object, and
the intrinsics between both :^)
2022-08-27 11:29:10 +01:00

114 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/TypeCasts.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Temporal/Calendar.h>
#include <LibJS/Runtime/Temporal/Instant.h>
#include <LibJS/Runtime/Temporal/TimeZone.h>
#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
#include <LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h>
namespace JS::Temporal {
// 6.1 The Temporal.ZonedDateTime Constructor, https://tc39.es/proposal-temporal/#sec-temporal-zoneddatetime-constructor
ZonedDateTimeConstructor::ZonedDateTimeConstructor(Realm& realm)
: NativeFunction(vm().names.ZonedDateTime.as_string(), *realm.intrinsics().function_prototype())
{
}
void ZonedDateTimeConstructor::initialize(Realm& realm)
{
NativeFunction::initialize(realm);
auto& vm = this->vm();
// 6.2.1 Temporal.ZonedDateTime.prototype, https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype
define_direct_property(vm.names.prototype, realm.intrinsics().temporal_zoned_date_time_prototype(), 0);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, vm.names.from, from, 1, attr);
define_native_function(realm, vm.names.compare, compare, 2, attr);
define_direct_property(vm.names.length, Value(2), Attribute::Configurable);
}
// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime
ThrowCompletionOr<Value> ZonedDateTimeConstructor::call()
{
auto& vm = this->vm();
// 1. If NewTarget is undefined, then
// a. Throw a TypeError exception.
return vm.throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime");
}
// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime
ThrowCompletionOr<Object*> ZonedDateTimeConstructor::construct(FunctionObject& new_target)
{
auto& vm = this->vm();
// 2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds).
auto* epoch_nanoseconds = TRY(vm.argument(0).to_bigint(vm));
// 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds))
return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidEpochNanoseconds);
// 4. Let timeZone be ? ToTemporalTimeZone(timeZoneLike).
auto* time_zone = TRY(to_temporal_time_zone(vm, vm.argument(1)));
// 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike).
auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, vm.argument(2)));
// 6. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar, NewTarget).
return TRY(create_temporal_zoned_date_time(vm, *epoch_nanoseconds, *time_zone, *calendar, &new_target));
}
// 6.2.2 Temporal.ZonedDateTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.from
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimeConstructor::from)
{
// 1. Set options to ? GetOptionsObject(options).
auto const* options = TRY(get_options_object(vm, vm.argument(1)));
auto item = vm.argument(0);
// 2. If Type(item) is Object and item has an [[InitializedTemporalZonedDateTime]] internal slot, then
if (item.is_object() && is<ZonedDateTime>(item.as_object())) {
auto& item_object = static_cast<ZonedDateTime&>(item.as_object());
// a. Perform ? ToTemporalOverflow(options).
(void)TRY(to_temporal_overflow(vm, options));
// b. Perform ? ToTemporalDisambiguation(options).
(void)TRY(to_temporal_disambiguation(vm, options));
// c. Perform ? ToTemporalOffset(options, "reject").
(void)TRY(to_temporal_offset(vm, options, "reject"));
// d. Return ! CreateTemporalZonedDateTime(item.[[Nanoseconds]], item.[[TimeZone]], item.[[Calendar]]).
return MUST(create_temporal_zoned_date_time(vm, item_object.nanoseconds(), item_object.time_zone(), item_object.calendar()));
}
// 3. Return ? ToTemporalZonedDateTime(item, options).
return TRY(to_temporal_zoned_date_time(vm, item, options));
}
// 6.2.3 Temporal.ZonedDateTime.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.compare
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimeConstructor::compare)
{
// 1. Set one to ? ToTemporalZonedDateTime(one).
auto* one = TRY(to_temporal_zoned_date_time(vm, vm.argument(0)));
// 2. Set two to ? ToTemporalZonedDateTime(two).
auto* two = TRY(to_temporal_zoned_date_time(vm, vm.argument(1)));
// 3. Return 𝔽(! CompareEpochNanoseconds(one.[[Nanoseconds]], two.[[Nanoseconds]])).
return Value(compare_epoch_nanoseconds(one->nanoseconds(), two->nanoseconds()));
}
}