mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
LibJS: Start implementing Temporal.Instant
Just like the initial Temporal.TimeZone commit, this patch adds the Instant object itself, its constructor and prototype (currently empty), and two required abstract operations.
This commit is contained in:
parent
d9cff591b6
commit
47fb4286c7
Notes:
sideshowbarker
2024-07-18 10:09:52 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/47fb4286c72 Pull-request: https://github.com/SerenityOS/serenity/pull/8534
11 changed files with 255 additions and 1 deletions
|
@ -121,6 +121,9 @@ set(SOURCES
|
|||
Runtime/SymbolConstructor.cpp
|
||||
Runtime/SymbolObject.cpp
|
||||
Runtime/SymbolPrototype.cpp
|
||||
Runtime/Temporal/Instant.cpp
|
||||
Runtime/Temporal/InstantConstructor.cpp
|
||||
Runtime/Temporal/InstantPrototype.cpp
|
||||
Runtime/Temporal/ISO8601.cpp
|
||||
Runtime/Temporal/Now.cpp
|
||||
Runtime/Temporal/Temporal.cpp
|
||||
|
|
|
@ -76,7 +76,8 @@
|
|||
__JS_ENUMERATE(Float32Array, float32_array, Float32ArrayPrototype, Float32ArrayConstructor, float) \
|
||||
__JS_ENUMERATE(Float64Array, float64_array, Float64ArrayPrototype, Float64ArrayConstructor, double)
|
||||
|
||||
#define JS_ENUMERATE_TEMPORAL_OBJECTS \
|
||||
#define JS_ENUMERATE_TEMPORAL_OBJECTS \
|
||||
__JS_ENUMERATE(Instant, instant, InstantPrototype, InstantConstructor) \
|
||||
__JS_ENUMERATE(TimeZone, time_zone, TimeZonePrototype, TimeZoneConstructor)
|
||||
|
||||
#define JS_ENUMERATE_ITERATOR_PROTOTYPES \
|
||||
|
|
|
@ -162,6 +162,7 @@
|
|||
M(StringNonGlobalRegExp, "RegExp argument is non-global") \
|
||||
M(StringRawCannotConvert, "Cannot convert property 'raw' to object from {}") \
|
||||
M(StringRepeatCountMustBe, "repeat count must be a {} number") \
|
||||
M(TemporalInvalidEpochNanoseconds, "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17") \
|
||||
M(TemporalInvalidTimeZoneName, "Invalid time zone name") \
|
||||
M(ThisHasNotBeenInitialized, "|this| has not been initialized") \
|
||||
M(ThisIsAlreadyInitialized, "|this| is already initialized") \
|
||||
|
|
|
@ -67,6 +67,8 @@
|
|||
#include <LibJS/Runtime/StringPrototype.h>
|
||||
#include <LibJS/Runtime/SymbolConstructor.h>
|
||||
#include <LibJS/Runtime/SymbolPrototype.h>
|
||||
#include <LibJS/Runtime/Temporal/InstantConstructor.h>
|
||||
#include <LibJS/Runtime/Temporal/InstantPrototype.h>
|
||||
#include <LibJS/Runtime/Temporal/Temporal.h>
|
||||
#include <LibJS/Runtime/Temporal/TimeZoneConstructor.h>
|
||||
#include <LibJS/Runtime/Temporal/TimeZonePrototype.h>
|
||||
|
|
68
Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp
Normal file
68
Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibCrypto/BigInt/SignedBigInteger.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Temporal/Instant.h>
|
||||
#include <LibJS/Runtime/Temporal/InstantConstructor.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
// 8 Temporal.Instant Objects, https://tc39.es/proposal-temporal/#sec-temporal-instant-objects
|
||||
Instant::Instant(BigInt& nanoseconds, Object& prototype)
|
||||
: Object(prototype)
|
||||
, m_nanoseconds(nanoseconds)
|
||||
{
|
||||
}
|
||||
|
||||
void Instant::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
|
||||
visitor.visit(&m_nanoseconds);
|
||||
}
|
||||
|
||||
// 8.5.1 IsValidEpochNanoseconds ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds
|
||||
bool is_valid_epoch_nanoseconds(BigInt const& epoch_nanoseconds)
|
||||
{
|
||||
// 1. Assert: Type(epochNanoseconds) is BigInt.
|
||||
|
||||
// 2. If epochNanoseconds < −86400ℤ × 10^17ℤ or epochNanoseconds > 86400ℤ × 10^17ℤ, then
|
||||
if (epoch_nanoseconds.big_integer() < INSTANT_NANOSECONDS_MIN || epoch_nanoseconds.big_integer() > INSTANT_NANOSECONDS_MAX) {
|
||||
// a. Return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 8.5.2 CreateTemporalInstant ( epochNanoseconds [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalinstant
|
||||
Object* create_temporal_instant(GlobalObject& global_object, BigInt& epoch_nanoseconds, FunctionObject* new_target)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// 1. Assert: Type(epochNanoseconds) is BigInt.
|
||||
|
||||
// 2. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true.
|
||||
VERIFY(is_valid_epoch_nanoseconds(epoch_nanoseconds));
|
||||
|
||||
// 3. If newTarget is not present, set it to %Temporal.Instant%.
|
||||
if (!new_target)
|
||||
new_target = global_object.temporal_instant_constructor();
|
||||
|
||||
// 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Instant.prototype%", « [[InitializedTemporalInstant]], [[Nanoseconds]] »).
|
||||
// 5. Set object.[[Nanoseconds]] to epochNanoseconds.
|
||||
auto* object = ordinary_create_from_constructor<Instant>(global_object, *new_target, &GlobalObject::temporal_instant_prototype, epoch_nanoseconds);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
// 6. Return object.
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
41
Userland/Libraries/LibJS/Runtime/Temporal/Instant.h
Normal file
41
Userland/Libraries/LibJS/Runtime/Temporal/Instant.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Optional.h>
|
||||
#include <LibJS/Runtime/BigInt.h>
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
class Instant final : public Object {
|
||||
JS_OBJECT(Instant, Object);
|
||||
|
||||
public:
|
||||
explicit Instant(BigInt& nanoseconds, Object& prototype);
|
||||
virtual ~Instant() override = default;
|
||||
|
||||
BigInt const& nanoseconds() const { return m_nanoseconds; }
|
||||
|
||||
private:
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
// 8.4 Properties of Temporal.Instant Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-instant-instances
|
||||
|
||||
// [[Nanoseconds]]
|
||||
BigInt& m_nanoseconds;
|
||||
};
|
||||
|
||||
// -86400 * 10^17
|
||||
const auto INSTANT_NANOSECONDS_MIN = Crypto::SignedBigInteger::from_base(10, "-8640000000000000000000");
|
||||
// +86400 * 10^17
|
||||
const auto INSTANT_NANOSECONDS_MAX = Crypto::SignedBigInteger::from_base(10, "8640000000000000000000");
|
||||
|
||||
bool is_valid_epoch_nanoseconds(BigInt const& epoch_nanoseconds);
|
||||
Object* create_temporal_instant(GlobalObject&, BigInt& nanoseconds, FunctionObject* new_target = nullptr);
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Temporal/Instant.h>
|
||||
#include <LibJS/Runtime/Temporal/InstantConstructor.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
// 8.1 The Temporal.Instant Constructor, https://tc39.es/proposal-temporal/#sec-temporal-instant-constructor
|
||||
InstantConstructor::InstantConstructor(GlobalObject& global_object)
|
||||
: NativeFunction(vm().names.Instant.as_string(), *global_object.function_prototype())
|
||||
{
|
||||
}
|
||||
|
||||
void InstantConstructor::initialize(GlobalObject& global_object)
|
||||
{
|
||||
NativeFunction::initialize(global_object);
|
||||
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 8.2.1 Temporal.Instant.prototype, https://tc39.es/proposal-temporal/#sec-temporal-instant-prototype
|
||||
define_direct_property(vm.names.prototype, global_object.temporal_instant_prototype(), 0);
|
||||
|
||||
define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
}
|
||||
|
||||
// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant
|
||||
Value InstantConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, then
|
||||
// a. Throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant");
|
||||
return {};
|
||||
}
|
||||
|
||||
// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant
|
||||
Value InstantConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds).
|
||||
auto* epoch_nanoseconds = vm.argument(0).to_bigint(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
// 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
|
||||
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
|
||||
return {};
|
||||
}
|
||||
|
||||
// 4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget).
|
||||
return create_temporal_instant(global_object, *epoch_nanoseconds, &new_target);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
class InstantConstructor final : public NativeFunction {
|
||||
JS_OBJECT(InstantConstructor, NativeFunction);
|
||||
|
||||
public:
|
||||
explicit InstantConstructor(GlobalObject&);
|
||||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~InstantConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Temporal/InstantPrototype.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
// 8.3 Properties of the Temporal.Instant Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-instant-prototype-object
|
||||
InstantPrototype::InstantPrototype(GlobalObject& global_object)
|
||||
: Object(*global_object.object_prototype())
|
||||
{
|
||||
}
|
||||
|
||||
void InstantPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
Object::initialize(global_object);
|
||||
}
|
||||
|
||||
}
|
22
Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
Normal file
22
Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
class InstantPrototype final : public Object {
|
||||
JS_OBJECT(InstantPrototype, Object);
|
||||
|
||||
public:
|
||||
explicit InstantPrototype(GlobalObject&);
|
||||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~InstantPrototype() override = default;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Temporal/InstantConstructor.h>
|
||||
#include <LibJS/Runtime/Temporal/Now.h>
|
||||
#include <LibJS/Runtime/Temporal/Temporal.h>
|
||||
#include <LibJS/Runtime/Temporal/TimeZoneConstructor.h>
|
||||
|
@ -25,6 +26,7 @@ void Temporal::initialize(GlobalObject& global_object)
|
|||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
|
||||
define_direct_property(vm.names.now, heap().allocate<Now>(global_object, global_object), attr);
|
||||
define_direct_property(vm.names.Instant, global_object.temporal_instant_constructor(), attr);
|
||||
define_direct_property(vm.names.TimeZone, global_object.temporal_time_zone_constructor(), attr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue