diff --git a/Userland/Libraries/LibJS/Runtime/Date.h b/Userland/Libraries/LibJS/Runtime/Date.h index 00ca3be055..e961aad8fe 100644 --- a/Userland/Libraries/LibJS/Runtime/Date.h +++ b/Userland/Libraries/LibJS/Runtime/Date.h @@ -15,6 +15,8 @@ class Date final : public Object { JS_OBJECT(Date, Object); public: + static constexpr double time_clip = 8.64e15; + static Date* create(GlobalObject&, Core::DateTime, i16 milliseconds, bool is_invalid = false); static Date* now(GlobalObject&); diff --git a/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp b/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp index 20349a0fa0..b4b0330368 100644 --- a/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp @@ -172,6 +172,8 @@ Value DateConstructor::construct(Function&) // A timestamp since the epoch, in UTC. double value_as_double = value.as_double(); + if (value_as_double > Date::time_clip) + return create_invalid_date(); auto datetime = Core::DateTime::from_timestamp(static_cast(value_as_double / 1000)); auto milliseconds = static_cast(fmod(value_as_double, 1000)); return Date::create(global_object(), datetime, milliseconds); @@ -247,7 +249,10 @@ Value DateConstructor::construct(Function&) year += 1900; int month = month_index + 1; auto datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds); - return Date::create(global_object(), datetime, milliseconds); + auto* date = Date::create(global_object(), datetime, milliseconds); + if (date->time() > Date::time_clip) + return create_invalid_date(); + return date; } JS_DEFINE_NATIVE_FUNCTION(DateConstructor::now) diff --git a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp index e75979609d..1fdeac5cdd 100644 --- a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2020-2021, Linus Groh * Copyright (c) 2021, Petróczi Zoltán + * Copyright (c) 2021, Idan Horowitz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -127,9 +128,13 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_date) } auto new_date = new_date_value.as_i32(); - this_object->set_is_invalid(false); - datetime.set_time(datetime.year(), datetime.month(), new_date, datetime.hour(), datetime.minute(), datetime.second()); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + + this_object->set_is_invalid(false); return Value(this_object->time()); } @@ -195,6 +200,11 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_full_year) auto new_day = new_day_value.as_i32(); datetime.set_time(new_year, new_month, new_day, datetime.hour(), datetime.minute(), datetime.second()); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + this_object->set_is_invalid(false); return Value(this_object->time()); @@ -232,6 +242,11 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_year) new_year += 1900; datetime.set_time(new_year, datetime.month(), datetime.day(), datetime.hour(), datetime.minute(), datetime.second()); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + this_object->set_is_invalid(false); return Value(this_object->time()); @@ -295,12 +310,16 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_hours) } auto new_milliseconds = new_milliseconds_value.as_i32(); - this_object->set_is_invalid(false); - new_seconds += new_milliseconds / 1000; this_object->set_milliseconds(new_milliseconds % 1000); datetime.set_time(datetime.year(), datetime.month(), datetime.day(), new_hours, new_minutes, new_seconds); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + + this_object->set_is_invalid(false); return Value(this_object->time()); } @@ -341,6 +360,11 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_milliseconds) datetime.set_time(datetime.year(), datetime.month(), datetime.day(), datetime.hour(), datetime.minute(), datetime.second() + added_seconds); } + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + this_object->set_is_invalid(false); return Value(this_object->time()); @@ -395,12 +419,16 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_minutes) } auto new_milliseconds = new_milliseconds_value.as_i32(); - this_object->set_is_invalid(false); - new_seconds += new_milliseconds / 1000; this_object->set_milliseconds(new_milliseconds % 1000); datetime.set_time(datetime.year(), datetime.month(), datetime.day(), datetime.hour(), new_minutes, new_seconds); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + + this_object->set_is_invalid(false); return Value(this_object->time()); } @@ -444,9 +472,13 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_month) } auto new_date = new_date_value.as_i32(); - this_object->set_is_invalid(false); - datetime.set_time(datetime.year(), new_month, new_date, datetime.hour(), datetime.minute(), datetime.second()); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + + this_object->set_is_invalid(false); return Value(this_object->time()); } @@ -490,12 +522,16 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_seconds) } auto new_milliseconds = new_milliseconds_value.as_i32(); - this_object->set_is_invalid(false); - new_seconds += new_milliseconds / 1000; this_object->set_milliseconds(new_milliseconds % 1000); datetime.set_time(datetime.year(), datetime.month(), datetime.day(), datetime.hour(), datetime.minute(), new_seconds); + if (this_object->time() > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } + + this_object->set_is_invalid(false); return Value(this_object->time()); } @@ -526,11 +562,16 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_time) } auto new_time = new_time_value.as_double(); - this_object->set_is_invalid(false); + if (new_time > Date::time_clip) { + this_object->set_is_invalid(true); + return js_nan(); + } auto new_date_time = Core::DateTime::from_timestamp(static_cast(new_time / 1000)); this_object->datetime().set_time(new_date_time.year(), new_date_time.month(), new_date_time.day(), new_date_time.hour(), new_date_time.minute(), new_date_time.second()); this_object->set_milliseconds(static_cast(fmod(new_time, 1000))); + + this_object->set_is_invalid(false); return Value(this_object->time()); }