[GTK] Gardening, update TestExpectations and add baseline
[WebKit.git] / Source / JavaScriptCore / runtime / DateConstructor.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004-2019 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
18  *  USA
19  *
20  */
21
22 #include "config.h"
23 #include "DateConstructor.h"
24
25 #include "DateConversion.h"
26 #include "DateInstance.h"
27 #include "DatePrototype.h"
28 #include "JSDateMath.h"
29 #include "JSFunction.h"
30 #include "JSGlobalObject.h"
31 #include "JSString.h"
32 #include "ObjectPrototype.h"
33 #include "JSCInlines.h"
34 #include <math.h>
35 #include <time.h>
36 #include <wtf/MathExtras.h>
37
38 #if HAVE(SYS_TIME_H)
39 #include <sys/time.h>
40 #endif
41
42 #if HAVE(SYS_TIMEB_H)
43 #include <sys/timeb.h>
44 #endif
45
46 namespace JSC {
47
48 EncodedJSValue JSC_HOST_CALL dateParse(JSGlobalObject*, CallFrame*);
49 EncodedJSValue JSC_HOST_CALL dateUTC(JSGlobalObject*, CallFrame*);
50 EncodedJSValue JSC_HOST_CALL dateNow(JSGlobalObject*, CallFrame*);
51
52 }
53
54 #include "DateConstructor.lut.h"
55
56 namespace JSC {
57
58 const ClassInfo DateConstructor::s_info = { "Function", &InternalFunction::s_info, &dateConstructorTable, nullptr, CREATE_METHOD_TABLE(DateConstructor) };
59
60 /* Source for DateConstructor.lut.h
61 @begin dateConstructorTable
62   parse     dateParse   DontEnum|Function 1
63   UTC       dateUTC     DontEnum|Function 7
64   now       dateNow     DontEnum|Function 0
65 @end
66 */
67
68 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DateConstructor);
69
70 static EncodedJSValue JSC_HOST_CALL callDate(JSGlobalObject*, CallFrame*);
71 static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(JSGlobalObject*, CallFrame*);
72
73 DateConstructor::DateConstructor(VM& vm, Structure* structure)
74     : InternalFunction(vm, structure, callDate, constructWithDateConstructor)
75 {
76 }
77
78 void DateConstructor::finishCreation(VM& vm, DatePrototype* datePrototype)
79 {
80     Base::finishCreation(vm, vm.propertyNames->Date.string(), NameAdditionMode::WithoutStructureTransition);
81     putDirectWithoutTransition(vm, vm.propertyNames->prototype, datePrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
82     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(7), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
83 }
84
85 static double millisecondsFromComponents(JSGlobalObject* globalObject, const ArgList& args, WTF::TimeType timeType)
86 {
87     VM& vm = globalObject->vm();
88     auto scope = DECLARE_THROW_SCOPE(vm);
89
90     // Initialize doubleArguments with default values.
91     double doubleArguments[7] {
92         0, 0, 1, 0, 0, 0, 0
93     };
94     unsigned numberOfUsedArguments = std::max(std::min<unsigned>(7U, args.size()), 1U);
95     for (unsigned i = 0; i < numberOfUsedArguments; ++i) {
96         doubleArguments[i] = args.at(i).toNumber(globalObject);
97         RETURN_IF_EXCEPTION(scope, 0);
98     }
99     for (unsigned i = 0; i < numberOfUsedArguments; ++i) {
100         if (!std::isfinite(doubleArguments[i]) || (doubleArguments[i] > INT_MAX) || (doubleArguments[i] < INT_MIN))
101             return PNaN;
102     }
103
104     GregorianDateTime t;
105     int year = JSC::toInt32(doubleArguments[0]);
106     t.setYear((year >= 0 && year <= 99) ? (year + 1900) : year);
107     t.setMonth(JSC::toInt32(doubleArguments[1]));
108     t.setMonthDay(JSC::toInt32(doubleArguments[2]));
109     t.setHour(JSC::toInt32(doubleArguments[3]));
110     t.setMinute(JSC::toInt32(doubleArguments[4]));
111     t.setSecond(JSC::toInt32(doubleArguments[5]));
112     t.setIsDST(-1);
113     return gregorianDateTimeToMS(vm, t, doubleArguments[6], timeType);
114 }
115
116 // ECMA 15.9.3
117 JSObject* constructDate(JSGlobalObject* globalObject, JSValue newTarget, const ArgList& args)
118 {
119     VM& vm = globalObject->vm();
120     auto scope = DECLARE_THROW_SCOPE(vm);
121     int numArgs = args.size();
122
123     double value;
124
125     if (numArgs == 0) // new Date() ECMA 15.9.3.3
126         value = jsCurrentTime();
127     else if (numArgs == 1) {
128         JSValue arg0 = args.at(0);
129         if (auto* dateInstance = jsDynamicCast<DateInstance*>(vm, arg0))
130             value = dateInstance->internalNumber();
131         else {
132             JSValue primitive = arg0.toPrimitive(globalObject);
133             RETURN_IF_EXCEPTION(scope, nullptr);
134             if (primitive.isString()) {
135                 String primitiveString = asString(primitive)->value(globalObject);
136                 RETURN_IF_EXCEPTION(scope, nullptr);
137                 value = parseDate(globalObject, vm, primitiveString);
138                 RETURN_IF_EXCEPTION(scope, nullptr);
139             } else
140                 value = primitive.toNumber(globalObject);
141         }
142     } else
143         value = millisecondsFromComponents(globalObject, args, WTF::LocalTime);
144     RETURN_IF_EXCEPTION(scope, nullptr);
145
146     Structure* dateStructure = InternalFunction::createSubclassStructure(globalObject, globalObject->dateConstructor(), newTarget, globalObject->dateStructure());
147     RETURN_IF_EXCEPTION(scope, nullptr);
148
149     return DateInstance::create(vm, dateStructure, value);
150 }
151     
152 static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(JSGlobalObject* globalObject, CallFrame* callFrame)
153 {
154     ArgList args(callFrame);
155     return JSValue::encode(constructDate(globalObject, callFrame->newTarget(), args));
156 }
157
158 // ECMA 15.9.2
159 static EncodedJSValue JSC_HOST_CALL callDate(JSGlobalObject* globalObject, CallFrame*)
160 {
161     VM& vm = globalObject->vm();
162     GregorianDateTime ts;
163     msToGregorianDateTime(vm, WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
164     return JSValue::encode(jsNontrivialString(vm, formatDateTime(ts, DateTimeFormatDateAndTime, false)));
165 }
166
167 EncodedJSValue JSC_HOST_CALL dateParse(JSGlobalObject* globalObject, CallFrame* callFrame)
168 {
169     VM& vm = globalObject->vm();
170     auto scope = DECLARE_THROW_SCOPE(vm);
171     String dateStr = callFrame->argument(0).toWTFString(globalObject);
172     RETURN_IF_EXCEPTION(scope, encodedJSValue());
173     RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(parseDate(globalObject, vm, dateStr))));
174 }
175
176 JSValue dateNowImpl()
177 {
178     return jsNumber(jsCurrentTime());
179 }
180
181 EncodedJSValue JSC_HOST_CALL dateNow(JSGlobalObject*, CallFrame*)
182 {
183     return JSValue::encode(jsNumber(jsCurrentTime()));
184 }
185
186 EncodedJSValue JSC_HOST_CALL dateUTC(JSGlobalObject* globalObject, CallFrame* callFrame)
187 {
188     double ms = millisecondsFromComponents(globalObject, ArgList(callFrame), WTF::UTCTime);
189     return JSValue::encode(jsNumber(timeClip(ms)));
190 }
191
192 } // namespace JSC