ladybird/Libraries/LibJS/Runtime/Temporal/Now.cpp
Andreas Kling b6bef6b688 Libraries: Use UTF-16 for JS-visible runtime strings
Produce JS-visible string results as UTF-16 at their source, including
numeric formatting, BigInt and BigFraction formatting, URI encoding,
console formatting, parser errors, regular expression errors, Intl and
Temporal records, LibUnicode locale boundaries, and LibWeb bindings.

Handle fractional radix formatting through the UTF-16 builder view.
2026-06-22 19:51:25 +02:00

172 lines
6.7 KiB
C++
Raw Permalink 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-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/Temporal/Instant.h>
#include <LibJS/Runtime/Temporal/Now.h>
#include <LibJS/Runtime/Temporal/PlainDate.h>
#include <LibJS/Runtime/Temporal/PlainDateTime.h>
#include <LibJS/Runtime/Temporal/PlainTime.h>
#include <LibJS/Runtime/Temporal/TimeZone.h>
#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
namespace JS::Temporal {
GC_DEFINE_ALLOCATOR(Now);
// 2 The Temporal.Now Object, https://tc39.es/proposal-temporal/#sec-temporal-now-object
Now::Now(Realm& realm)
: Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype())
{
}
void Now::initialize(Realm& realm)
{
Base::initialize(realm);
auto& vm = this->vm();
// 2.1.1 Temporal.Now [ %Symbol.toStringTag% ], https://tc39.es/proposal-temporal/#sec-temporal-now-%symbol.tostringtag%
define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.Now"_utf16_fly_string), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, vm.names.timeZoneId, time_zone_id, 0, attr);
define_native_function(realm, vm.names.instant, instant, 0, attr);
define_native_function(realm, vm.names.plainDateTimeISO, plain_date_time_iso, 0, attr);
define_native_function(realm, vm.names.zonedDateTimeISO, zoned_date_time_iso, 0, attr);
define_native_function(realm, vm.names.plainDateISO, plain_date_iso, 0, attr);
define_native_function(realm, vm.names.plainTimeISO, plain_time_iso, 0, attr);
}
// 2.2.1 Temporal.Now.timeZoneId ( ), https://tc39.es/proposal-temporal/#sec-temporal.now.timezoneid
JS_DEFINE_NATIVE_FUNCTION(Now::time_zone_id)
{
// 1. Return SystemTimeZoneIdentifier().
auto time_zone = system_time_zone_identifier();
return PrimitiveString::create(vm, time_zone);
}
// 2.2.2 Temporal.Now.instant ( ), https://tc39.es/proposal-temporal/#sec-temporal.now.instant
JS_DEFINE_NATIVE_FUNCTION(Now::instant)
{
// 1. Let ns be SystemUTCEpochNanoseconds().
auto nanoseconds = system_utc_epoch_nanoseconds(vm);
// 2. Return ! CreateTemporalInstant(ns).
return MUST(create_temporal_instant(vm, BigInt::create(vm, move(nanoseconds))));
}
// 2.2.3 Temporal.Now.plainDateTimeISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaindatetimeiso
JS_DEFINE_NATIVE_FUNCTION(Now::plain_date_time_iso)
{
auto temporal_time_zone_like = vm.argument(0);
// 1. Let isoDateTime be ? SystemDateTime(temporalTimeZoneLike).
auto iso_date_time = TRY(system_date_time(vm, temporal_time_zone_like));
// 2. Return ! CreateTemporalDateTime(isoDateTime, "iso8601").
return MUST(create_temporal_date_time(vm, iso_date_time, "iso8601"_utf16));
}
// 2.2.4 Temporal.Now.zonedDateTimeISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.zoneddatetimeiso
JS_DEFINE_NATIVE_FUNCTION(Now::zoned_date_time_iso)
{
auto temporal_time_zone_like = vm.argument(0);
Utf16String time_zone;
// 1. If temporalTimeZoneLike is undefined, then
if (temporal_time_zone_like.is_undefined()) {
// a. Let timeZone be SystemTimeZoneIdentifier().
time_zone = system_time_zone_identifier();
}
// 2. Else,
else {
// a. Let timeZone be ? ToTemporalTimeZoneIdentifier(temporalTimeZoneLike).
time_zone = TRY(to_temporal_time_zone_identifier(vm, temporal_time_zone_like));
}
// 3. Let ns be SystemUTCEpochNanoseconds().
auto nanoseconds = system_utc_epoch_nanoseconds(vm);
// 4. Return ! CreateTemporalZonedDateTime(ns, timeZone, "iso8601").
return MUST(create_temporal_zoned_date_time(vm, BigInt::create(vm, move(nanoseconds)), move(time_zone), "iso8601"_utf16));
}
// 2.2.5 Temporal.Now.plainDateISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaindateiso
JS_DEFINE_NATIVE_FUNCTION(Now::plain_date_iso)
{
auto temporal_time_zone_like = vm.argument(0);
// 1. Let isoDateTime be ? SystemDateTime(temporalTimeZoneLike).
auto iso_date_time = TRY(system_date_time(vm, temporal_time_zone_like));
// 2. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], "iso8601").
return MUST(create_temporal_date(vm, iso_date_time.iso_date, "iso8601"_utf16));
}
// 2.2.6 Temporal.Now.plainTimeISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaintimeiso
JS_DEFINE_NATIVE_FUNCTION(Now::plain_time_iso)
{
auto temporal_time_zone_like = vm.argument(0);
// 1. Let isoDateTime be ? SystemDateTime(temporalTimeZoneLike).
auto iso_date_time = TRY(system_date_time(vm, temporal_time_zone_like));
// 2. Return ! CreateTemporalTime(isoDateTime.[[Time]]).
return MUST(create_temporal_time(vm, iso_date_time.time));
}
// 2.3.2 SystemUTCEpochMilliseconds ( ), https://tc39.es/proposal-temporal/#sec-temporal-systemutcepochmilliseconds
double system_utc_epoch_milliseconds(VM& vm)
{
// 1. Let global be GetGlobalObject().
auto const& global = vm.get_global_object();
// 2. Let nowNs be HostSystemUTCEpochNanoseconds(global).
auto now_ns = vm.host_system_utc_epoch_nanoseconds(global);
// 3. Return 𝔽(floor(nowNs / 10**6)).
return big_floor(now_ns, NANOSECONDS_PER_MILLISECOND).to_double();
}
// 2.3.3 SystemUTCEpochNanoseconds ( ), https://tc39.es/proposal-temporal/#sec-temporal-systemutcepochnanoseconds
Crypto::SignedBigInteger system_utc_epoch_nanoseconds(VM& vm)
{
// 1. Let global be GetGlobalObject().
auto const& global = vm.get_global_object();
// 2. Let nowNs be HostSystemUTCEpochNanoseconds(global).
auto now_ns = vm.host_system_utc_epoch_nanoseconds(global);
// 3. Return (nowNs).
return now_ns;
}
// 2.3.4 SystemDateTime ( temporalTimeZoneLike ), https://tc39.es/proposal-temporal/#sec-temporal-systemdatetime
ThrowCompletionOr<ISODateTime> system_date_time(VM& vm, Value temporal_time_zone_like)
{
Utf16String time_zone;
// 1. If temporalTimeZoneLike is undefined, then
if (temporal_time_zone_like.is_undefined()) {
// a. Let timeZone be SystemTimeZoneIdentifier().
time_zone = system_time_zone_identifier();
}
// 2. Else,
else {
// a. Let timeZone be ? ToTemporalTimeZoneIdentifier(temporalTimeZoneLike).
time_zone = TRY(to_temporal_time_zone_identifier(vm, temporal_time_zone_like));
}
// 3. Let epochNs be SystemUTCEpochNanoseconds().
auto epoch_nanoseconds = system_utc_epoch_nanoseconds(vm);
// 4. Return GetISODateTimeFor(timeZone, epochNs).
return get_iso_date_time_for(time_zone, epoch_nanoseconds);
}
}