LibJS: Start implementing Date :^)

This adds:

- A global Date object (with `length` property and `now` function)
- The Date constructor (no arguments yet)
- The Date prototype (with `get*` functions)
This commit is contained in:
Linus Groh 2020-03-30 00:21:56 +01:00 committed by Andreas Kling
parent 5c779c124b
commit d4e3688f4f
Notes: sideshowbarker 2024-07-19 08:03:11 +09:00
25 changed files with 567 additions and 5 deletions

29
Base/home/anon/js/date.js Normal file
View file

@ -0,0 +1,29 @@
var now = Date.now();
console.log("Unix timestamp: " + now / 1000);
// FIXME: We need String.prototype.padStart() :^)
var d = new Date();
var year = d.getFullYear();
var month = d.getMonth() + 1;
if (month < 10)
month = "0" + month;
var day = d.getDate();
if (day < 10)
day = "0" + day;
var hours = d.getHours();
if (hours < 10)
hours = "0" + hours;
var minutes = d.getMinutes();
if (minutes < 10)
minutes = "0" + minutes;
var seconds = d.getSeconds();
if (seconds < 10)
seconds = "0" + seconds;
var milliseconds = d.getMilliseconds();
if (milliseconds < 10) {
milliseconds = "00" + milliseconds;
} else if (milliseconds < 100) {
milliseconds = "0" + milliseconds;
}
console.log("Date: " + year + "-" + month + "-" + day);
console.log("Time: " + hours + ":" + minutes + ":" + seconds + "." + milliseconds);

View file

@ -28,6 +28,7 @@
#include <LibJS/AST.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/ArrayPrototype.h>
#include <LibJS/Runtime/DatePrototype.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/ErrorPrototype.h>
#include <LibJS/Runtime/GlobalObject.h>
@ -46,6 +47,7 @@ Interpreter::Interpreter()
m_string_prototype = heap().allocate<StringPrototype>();
m_array_prototype = heap().allocate<ArrayPrototype>();
m_error_prototype = heap().allocate<ErrorPrototype>();
m_date_prototype = heap().allocate<DatePrototype>();
m_global_object = heap().allocate<GlobalObject>();
}
@ -165,6 +167,7 @@ void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
roots.set(m_object_prototype);
roots.set(m_array_prototype);
roots.set(m_error_prototype);
roots.set(m_date_prototype);
roots.set(m_exception);

View file

@ -111,6 +111,7 @@ public:
Object* object_prototype() { return m_object_prototype; }
Object* array_prototype() { return m_array_prototype; }
Object* error_prototype() { return m_error_prototype; }
Object* date_prototype() { return m_date_prototype; }
Exception* exception() { return m_exception; }
void clear_exception() { m_exception = nullptr; }
@ -138,6 +139,7 @@ private:
Object* m_object_prototype { nullptr };
Object* m_array_prototype { nullptr };
Object* m_error_prototype { nullptr };
Object* m_date_prototype { nullptr };
Exception* m_exception { nullptr };

View file

@ -10,6 +10,9 @@ OBJS = \
Runtime/ArrayPrototype.o \
Runtime/Cell.o \
Runtime/ConsoleObject.o \
Runtime/Date.o \
Runtime/DateConstructor.o \
Runtime/DatePrototype.o \
Runtime/Error.o \
Runtime/ErrorPrototype.o \
Runtime/Exception.o \

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibCore/DateTime.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Date.h>
namespace JS {
Date::Date(Core::DateTime datetime, u16 milliseconds)
: m_datetime(datetime)
, m_milliseconds(milliseconds)
{
set_prototype(interpreter().date_prototype());
}
Date::~Date()
{
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibCore/DateTime.h>
#include <LibJS/Runtime/Object.h>
namespace JS {
class Date final : public Object {
public:
Date(Core::DateTime datetime, u16 milliseconds);
virtual ~Date() override;
Core::DateTime& datetime() { return m_datetime; }
u16 milliseconds() { return m_milliseconds; }
virtual Value value_of() const override
{
return Value(static_cast<double>(m_datetime.timestamp() * 1000 + m_milliseconds));
}
private:
virtual bool is_date() const final { return true; }
virtual const char* class_name() const override { return "Date"; }
Core::DateTime m_datetime;
u16 m_milliseconds;
};
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibCore/DateTime.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/DateConstructor.h>
#include <sys/time.h>
#include <time.h>
namespace JS {
DateConstructor::DateConstructor()
{
put("prototype", interpreter().date_prototype());
put("length", Value(7));
put_native_function("now", now);
}
DateConstructor::~DateConstructor()
{
}
Value DateConstructor::call(Interpreter& interpreter)
{
// TODO: Support args
struct timeval tv;
gettimeofday(&tv, nullptr);
auto datetime = Core::DateTime::now();
auto milliseconds = static_cast<u16>(tv.tv_usec / 1000);
return interpreter.heap().allocate<Date>(datetime, milliseconds);
}
Value DateConstructor::now(Interpreter&)
{
struct timeval tv;
gettimeofday(&tv, nullptr);
return Value(tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0);
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <LibJS/Runtime/NativeFunction.h>
namespace JS {
class DateConstructor final : public NativeFunction {
public:
DateConstructor();
virtual ~DateConstructor() override;
virtual Value call(Interpreter&) override;
private:
virtual const char* class_name() const override { return "DateConstructor"; }
static Value now(Interpreter&);
};
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <AK/Function.h>
#include <AK/String.h>
#include <LibCore/DateTime.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/DatePrototype.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
static Date* this_date_from_interpreter(Interpreter& interpreter)
{
auto* this_object = interpreter.this_value().to_object(interpreter.heap());
if (!this_object)
return nullptr;
if (!this_object->is_date()) {
interpreter.throw_exception<Error>("TypeError", "object must be of type Date");
return nullptr;
}
return static_cast<Date*>(this_object);
}
DatePrototype::DatePrototype()
{
put_native_function("getDate", get_date);
put_native_function("getDay", get_day);
put_native_function("getFullYear", get_full_year);
put_native_function("getHours", get_hours);
put_native_function("getMilliseconds", get_milliseconds);
put_native_function("getMinutes", get_minutes);
put_native_function("getMonth", get_month);
put_native_function("getSeconds", get_seconds);
put_native_function("getTime", get_time);
}
DatePrototype::~DatePrototype()
{
}
Value DatePrototype::get_date(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto date = this_object->datetime().day();
return Value(static_cast<double>(date));
}
Value DatePrototype::get_day(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto day = this_object->datetime().weekday();
return Value(static_cast<double>(day));
}
Value DatePrototype::get_full_year(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto full_year = this_object->datetime().year();
return Value(static_cast<double>(full_year));
}
Value DatePrototype::get_hours(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto hours = this_object->datetime().hour();
return Value(static_cast<double>(hours));
}
Value DatePrototype::get_milliseconds(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto milliseconds = this_object->milliseconds();
return Value(static_cast<double>(milliseconds));
}
Value DatePrototype::get_minutes(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto minutes = this_object->datetime().minute();
return Value(static_cast<double>(minutes));
}
Value DatePrototype::get_month(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto months = this_object->datetime().month() - 1;
return Value(static_cast<double>(months));
}
Value DatePrototype::get_seconds(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto seconds = this_object->datetime().second();
return Value(static_cast<double>(seconds));
}
Value DatePrototype::get_time(Interpreter& interpreter)
{
auto* this_object = this_date_from_interpreter(interpreter);
if (!this_object)
return {};
auto seconds = this_object->datetime().timestamp();
auto milliseconds = this_object->milliseconds();
return Value(static_cast<double>(seconds * 1000 + milliseconds));
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <LibJS/Runtime/Object.h>
namespace JS {
class DatePrototype final : public Object {
public:
DatePrototype();
virtual ~DatePrototype() override;
private:
virtual const char* class_name() const override { return "DatePrototype"; }
static Value get_date(Interpreter&);
static Value get_day(Interpreter&);
static Value get_full_year(Interpreter&);
static Value get_hours(Interpreter&);
static Value get_milliseconds(Interpreter&);
static Value get_minutes(Interpreter&);
static Value get_month(Interpreter&);
static Value get_seconds(Interpreter&);
static Value get_time(Interpreter&);
};
}

View file

@ -3,6 +3,7 @@
#include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/ConsoleObject.h>
#include <LibJS/Runtime/DateConstructor.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/MathObject.h>
#include <LibJS/Runtime/NativeFunction.h>
@ -17,6 +18,7 @@ GlobalObject::GlobalObject()
put_native_function("isNaN", is_nan);
put("console", heap().allocate<ConsoleObject>());
put("Date", heap().allocate<DateConstructor>());
put("Math", heap().allocate<MathObject>());
put("Object", heap().allocate<ObjectConstructor>());
}

View file

@ -49,12 +49,13 @@ public:
void put_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)>);
void put_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter);
virtual bool is_error() const { return false; }
virtual bool is_array() const { return false; }
virtual bool is_date() const { return false; }
virtual bool is_error() const { return false; }
virtual bool is_function() const { return false; }
virtual bool is_native_function() const { return false; }
virtual bool is_string_object() const { return false; }
virtual bool is_native_property() const { return false; }
virtual bool is_string_object() const { return false; }
virtual const char* class_name() const override { return "Object"; }
virtual void visit_children(Cell::Visitor&) override;

View file

@ -58,7 +58,7 @@ String Value::to_string() const
return "NaN";
// FIXME: This needs improvement.
return String::number((i32)as_double());
return String::format("%f", as_double());
}
if (is_object())

View file

@ -53,7 +53,7 @@ public:
bool is_cell() const { return is_string() || is_object(); }
bool is_array() const;
bool is_nan() const { return is_number() && __builtin_isnan( as_double()); }
bool is_nan() const { return is_number() && __builtin_isnan(as_double()); }
Value()
: m_type(Type::Undefined)

View file

@ -0,0 +1,15 @@
function assert(x) { if (!x) throw 1; }
try {
var last = 0;
for (var i = 0; i < 100; ++i) {
var now = Date.now();
assert(!isNaN(now))
assert(now > 1580000000000);
assert(now >= last);
last = now;
}
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getDate()));
assert(1 <= d.getDate() <= 31);
assert(d.getDate() === d.getDate());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getDay()));
assert(0 <= d.getDay() <= 6);
assert(d.getDay() === d.getDay());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getFullYear()));
assert(d.getFullYear() >= 2020);
assert(d.getFullYear() === d.getFullYear());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getHours()));
assert(0 <= d.getHours() <= 23);
assert(d.getHours() === d.getHours());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getMilliseconds()));
assert(0 <= d.getMilliseconds() <= 999);
assert(d.getMilliseconds() === d.getMilliseconds());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getMinutes()));
assert(0 <= d.getMinutes() <= 59);
assert(d.getMinutes() === d.getMinutes());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getMonth()));
assert(0 <= d.getMonth() <= 11);
assert(d.getMonth() === d.getMonth());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getSeconds()));
assert(0 <= d.getSeconds() <= 59);
assert(d.getSeconds() === d.getSeconds());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -0,0 +1,11 @@
function assert(x) { if (!x) throw 1; }
try {
var d = new Date();
assert(!isNaN(d.getTime()));
assert(d.getTime() > 1580000000000);
assert(d.getTime() === d.getTime());
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}

View file

@ -4,7 +4,7 @@ APPS = ${SRCS:.cpp=}
EXTRA_CLEAN = $(APPS)
LIB_DEPS = Web GUI Gfx Audio Protocol IPC Thread Pthread Core PCIDB Markdown JS
LIB_DEPS = Web GUI Gfx Audio Protocol IPC Thread Pthread PCIDB Markdown JS Core
include ../Makefile.common