1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_BUILTINS_BUILTINS_DATE_H
17 #define ECMASCRIPT_BUILTINS_BUILTINS_DATE_H
18 
19 #include "ecmascript/base/builtins_base.h"
20 #include "ecmascript/js_date.h"
21 
22 // List of functions in Date, excluding the '@@' properties.
23 // V(name, func, length, stubIndex)
24 // where BuiltinsDate::func refers to the native implementation of Date[name].
25 //       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
26 #define BUILTIN_DATE_FUNCTIONS(V)                                                                   \
27     /* Date.now ( ) */                                                                              \
28     V("now",   Now,   0, DateNow)                                                                   \
29     /* Date.parse ( string ) */                                                                     \
30     V("parse", Parse, 1, INVALID)                                                                   \
31     /* Date.UTC ( year [ , month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] ) */ \
32     V("UTC",   UTC,   ::panda::ecmascript::builtins::BuiltinsDate::UTC_LENGTH, INVALID)
33 
34 // List of functions in Date.prototype, excluding the constructor and '@@' properties.
35 // V(name, func, length, stubIndex)
36 // where BuiltinsDate::func refers to the native implementation of Date.prototype[name].
37 #define BUILTIN_DATE_PROTOTYPE_FUNCTIONS(V)                                     \
38     /* Date.prototype.getDate ( ) */                                            \
39     V("getDate",            GetDate,            0, INVALID)                     \
40     /* Date.prototype.getDay ( ) */                                             \
41     V("getDay",             GetDay,             0, INVALID)                     \
42     /* Date.prototype.getFullYear ( ) */                                        \
43     V("getFullYear",        GetFullYear,        0, INVALID)                     \
44     /* Date.prototype.getHours ( ) */                                           \
45     V("getHours",           GetHours,           0, INVALID)                     \
46     /* Date.prototype.getMilliseconds ( ) */                                    \
47     V("getMilliseconds",    GetMilliseconds,    0, INVALID)                     \
48     /* Date.prototype.getMinutes ( ) */                                         \
49     V("getMinutes",         GetMinutes,         0, INVALID)                     \
50     /* Date.prototype.getMonth ( ) */                                           \
51     V("getMonth",           GetMonth,           0, INVALID)                     \
52     /* Date.prototype.getSeconds ( ) */                                         \
53     V("getSeconds",         GetSeconds,         0, INVALID)                     \
54     /* Date.prototype.getTime ( ) */                                            \
55     V("getTime",            GetTime,            0, DateGetTime)                 \
56     /* Date.prototype.getTimezoneOffset ( ) */                                  \
57     V("getTimezoneOffset",  GetTimezoneOffset,  0, INVALID)                     \
58     /* Date.prototype.getUTCDate ( ) */                                         \
59     V("getUTCDate",         GetUTCDate,         0, INVALID)                     \
60     /* Date.prototype.getUTCDay ( ) */                                          \
61     V("getUTCDay",          GetUTCDay,          0, INVALID)                     \
62     /* Date.prototype.getUTCFullYear ( ) */                                     \
63     V("getUTCFullYear",     GetUTCFullYear,     0, INVALID)                     \
64     /* Date.prototype.getUTCHours ( ) */                                        \
65     V("getUTCHours",        GetUTCHours,        0, INVALID)                     \
66     /* Date.prototype.getUTCMilliseconds ( ) */                                 \
67     V("getUTCMilliseconds", GetUTCMilliseconds, 0, INVALID)                     \
68     /* Date.prototype.getUTCMinutes ( ) */                                      \
69     V("getUTCMinutes",      GetUTCMinutes,      0, INVALID)                     \
70     /* Date.prototype.getUTCMonth ( ) */                                        \
71     V("getUTCMonth",        GetUTCMonth,        0, INVALID)                     \
72     /* Date.prototype.getUTCSeconds ( ) */                                      \
73     V("getUTCSeconds",      GetUTCSeconds,      0, INVALID)                     \
74     /* Date.prototype.setDate ( date ) */                                       \
75     V("setDate",            SetDate,            1, INVALID)                     \
76     /* Date.prototype.setFullYear ( year [ , month [ , date ] ] ) */            \
77     V("setFullYear",        SetFullYear,        3, INVALID)                     \
78     /* Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] ) */         \
79     V("setHours",           SetHours,           4, INVALID)                     \
80     /* Date.prototype.setMilliseconds ( ms ) */                                 \
81     V("setMilliseconds",    SetMilliseconds,    1, INVALID)                     \
82     /* Date.prototype.setMinutes ( min [ , sec [ , ms ] ] ) */                  \
83     V("setMinutes",         SetMinutes,         3, INVALID)                     \
84     /* Date.prototype.setMonth ( month [ , date ] ) */                          \
85     V("setMonth",           SetMonth,           2, INVALID)                     \
86     /* Date.prototype.setSeconds ( sec [ , ms ] ) */                            \
87     V("setSeconds",         SetSeconds,         2, INVALID)                     \
88     /* Date.prototype.setTime ( time ) */                                       \
89     V("setTime",            SetTime,            1, INVALID)                     \
90     /* Date.prototype.setUTCDate ( date ) */                                    \
91     V("setUTCDate",         SetUTCDate,         1, INVALID)                     \
92     /* Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] ) */         \
93     V("setUTCFullYear",     SetUTCFullYear,     3, INVALID)                     \
94     /* Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] ) */      \
95     V("setUTCHours",        SetUTCHours,        4, INVALID)                     \
96     /* Date.prototype.setUTCMilliseconds ( ms ) */                              \
97     V("setUTCMilliseconds", SetUTCMilliseconds, 1, INVALID)                     \
98     /* Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] ) */               \
99     V("setUTCMinutes",      SetUTCMinutes,      3, INVALID)                     \
100     /* Date.prototype.setUTCMonth ( month [ , date ] ) */                       \
101     V("setUTCMonth",        SetUTCMonth,        2, INVALID)                     \
102     /* Date.prototype.setUTCSeconds ( sec [ , ms ] ) */                         \
103     V("setUTCSeconds",      SetUTCSeconds,      2, INVALID)                     \
104     /* Date.prototype.toDateString ( ) */                                       \
105     V("toDateString",       ToDateString,       0, INVALID)                     \
106     /* Date.prototype.toISOString ( ) */                                        \
107     V("toISOString",        ToISOString,        0, INVALID)                     \
108     /* Date.prototype.toJSON ( key ) */                                         \
109     V("toJSON",             ToJSON,             1, INVALID)                     \
110     /* Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] ) */   \
111     V("toLocaleDateString", ToLocaleDateString, 0, INVALID)                     \
112     /* Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */       \
113     V("toLocaleString",     ToLocaleString,     0, INVALID)                     \
114     /* Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] ) */   \
115     V("toLocaleTimeString", ToLocaleTimeString, 0, INVALID)                     \
116     /* Date.prototype.toString ( ) */                                           \
117     V("toString",           ToString,           0, INVALID)                     \
118     /* Date.prototype.toTimeString ( ) */                                       \
119     V("toTimeString",       ToTimeString,       0, INVALID)                     \
120     /* Date.prototype.toUTCString ( ) */                                        \
121     V("toUTCString",        ToUTCString,        0, INVALID)                     \
122     /* Date.prototype.valueOf ( ) */                                            \
123     V("valueOf",            ValueOf,            0, INVALID)
124 
125 namespace panda::ecmascript::builtins {
126 class BuiltinsDate : public base::BuiltinsBase {
127 public:
128     static constexpr int UTC_LENGTH = 7;
129 
130     // 20.4.2 The Date Constructor
131     static JSTaggedValue DateConstructor(EcmaRuntimeCallInfo *argv);
132 
133     // 20.4.3.1 Date.now ( )
134     static JSTaggedValue Now(EcmaRuntimeCallInfo *argv);
135 
136     // 20.4.3.4 Date.UTC ( year [ , month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] )
137     static JSTaggedValue UTC(EcmaRuntimeCallInfo *argv);
138 
139     static JSTaggedValue Parse(EcmaRuntimeCallInfo *argv);
140 
141     // 20.4.4.2 Date.prototype.getDate ( )
142     GET_DATE_VALUE(GetDate, DAYS, true);
143 
144     // 20.4.4.3 Date.prototype.getDay ( )
145     GET_DATE_VALUE(GetDay, WEEKDAY, true);
146 
147     // 20.4.4.4 Date.prototype.getFullYear ( )
148     GET_DATE_VALUE(GetFullYear, YEAR, true);
149 
150     // 20.4.4.5 Date.prototype.getHours ( )
151     GET_DATE_VALUE(GetHours, HOUR, true);
152 
153     // 20.4.4.6 Date.prototype.getMilliseconds ( )
154     GET_DATE_VALUE(GetMilliseconds, MS, true);
155 
156     // 20.4.4.7 Date.prototype.getMinutes ( )
157     GET_DATE_VALUE(GetMinutes, MIN, true);
158 
159     // 20.4.4.8 Date.prototype.getMonth ( )
160     GET_DATE_VALUE(GetMonth, MONTH, true);
161 
162     // 20.4.4.9 Date.prototype.getSeconds ( )
163     GET_DATE_VALUE(GetSeconds, SEC, true);
164 
165     // 20.4.4.10 Date.prototype.getTime ( )
166     static JSTaggedValue GetTime(EcmaRuntimeCallInfo *argv);
167 
168     // 20.4.4.11 Date.prototype.getTimezoneOffset ( )
169     GET_DATE_VALUE(GetTimezoneOffset, TIMEZONE, true);
170 
171     // 20.4.4.12 Date.prototype.getUTCDate ( )
172     GET_DATE_VALUE(GetUTCDate, DAYS, false);
173 
174     // 20.4.4.13 Date.prototype.getUTCDay ( )
175     GET_DATE_VALUE(GetUTCDay, WEEKDAY, false);
176 
177     // 20.4.4.14 Date.prototype.getUTCFullYear ( )
178     GET_DATE_VALUE(GetUTCFullYear, YEAR, false);
179 
180     // 20.4.4.15 Date.prototype.getUTCHours ( )
181     GET_DATE_VALUE(GetUTCHours, HOUR, false);
182 
183     // 20.4.4.16 Date.prototype.getUTCMilliseconds ( )
184     GET_DATE_VALUE(GetUTCMilliseconds, MS, false);
185 
186     // 20.4.4.17 Date.prototype.getUTCMinutes ( )
187     GET_DATE_VALUE(GetUTCMinutes, MIN, false);
188 
189     // 20.4.4.18 Date.prototype.getUTCMonth ( )
190     GET_DATE_VALUE(GetUTCMonth, MONTH, false);
191 
192     // 20.4.4.19 Date.prototype.getUTCSeconds ( )
193     GET_DATE_VALUE(GetUTCSeconds, SEC, false);
194 
195     // 20.3.4.20 Date.prototype.setDate ( date )
196     SET_DATE_VALUE(SetDate, CODE_SET_DATE, true);
197 
198     // 20.3.4.21 Date.prototype.setFullYear ( year [ , month [ , date ] ] )
199     SET_DATE_VALUE(SetFullYear, CODE_SET_FULL_YEAR, true);
200 
201     // 20.3.4.22 Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] )
202     SET_DATE_VALUE(SetHours, CODE_SET_HOURS, true);
203 
204     // 20.3.4.23 Date.prototype.setMilliseconds ( ms )
205     SET_DATE_VALUE(SetMilliseconds, CODE_SET_MILLISECONDS, true);
206 
207     // 20.3.4.24 Date.prototype.setMinutes ( min [ , sec [ , ms ] ] )
208     SET_DATE_VALUE(SetMinutes, CODE_SET_MINUTES, true);
209 
210     // 20.3.4.25 Date.prototype.setMonth ( month [ , date ] )
211     SET_DATE_VALUE(SetMonth, CODE_SET_MONTH, true);
212 
213     // 20.3.4.26 Date.prototype.setSeconds ( sec [ , ms ] )
214     SET_DATE_VALUE(SetSeconds, CODE_SET_SECONDS, true);
215 
216     // 20.3.4.27 Date.prototype.setTime ( time )
217     static JSTaggedValue SetTime(EcmaRuntimeCallInfo *argv);
218 
219     // 20.3.4.28 Date.prototype.setUTCDate ( date )
220     SET_DATE_VALUE(SetUTCDate, CODE_SET_DATE, false);
221 
222     // 20.3.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] )
223     SET_DATE_VALUE(SetUTCFullYear, CODE_SET_FULL_YEAR, false);
224 
225     // 20.3.4.30 Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] )
226     SET_DATE_VALUE(SetUTCHours, CODE_SET_HOURS, false);
227 
228     // 20.3.4.31 Date.prototype.setUTCMilliseconds ( ms )
229     SET_DATE_VALUE(SetUTCMilliseconds, CODE_SET_MILLISECONDS, false);
230 
231     // 20.3.4.32 Date.prototype.setUTCMinutes ( min [ , sec [, ms ] ] )
232     SET_DATE_VALUE(SetUTCMinutes, CODE_SET_MINUTES, false);
233 
234     // 20.3.4.33 Date.prototype.setUTCMonth ( month [ , date ] )
235     SET_DATE_VALUE(SetUTCMonth, CODE_SET_MONTH, false);
236 
237     // 20.3.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] )
238     SET_DATE_VALUE(SetUTCSeconds, CODE_SET_SECONDS, false);
239 
240     // 20.4.4.35 Date.prototype.toDateString ( )
241     DATE_STRING(ToDateString);
242 
243     // 20.4.4.36 Date.prototype.toISOString ( )
244     DATE_TO_STRING(ToISOString);
245 
246     // 20.4.4.37 Date.prototype.toJSON ( key )
247     static JSTaggedValue ToJSON(EcmaRuntimeCallInfo *argv);
248 
249     // 20.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )
250     static JSTaggedValue ToLocaleDateString(EcmaRuntimeCallInfo *argv);
251 
252     // 20.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )
253     static JSTaggedValue ToLocaleString(EcmaRuntimeCallInfo *argv);
254 
255     // 20.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )
256     static JSTaggedValue ToLocaleTimeString(EcmaRuntimeCallInfo *argv);
257 
258     // 20.4.4.41 Date.prototype.toString ( )
259     DATE_STRING(ToString);
260 
261     // 20.4.4.42 Date.prototype.toTimeString ( )
262     DATE_STRING(ToTimeString);
263 
264     // 20.4.4.43 Date.prototype.toUTCString ( )
265     DATE_STRING(ToUTCString);
266 
267     // 20.4.4.44 Date.prototype.valueOf ( )
268     static JSTaggedValue ValueOf(EcmaRuntimeCallInfo *argv);
269 
270     // 20.4.4.45 Date.prototype [ @@toPrimitive ]
271     static JSTaggedValue ToPrimitive(EcmaRuntimeCallInfo *argv);
272 
273     // Excluding the '@@' internal properties
GetDateFunctions()274     static Span<const base::BuiltinFunctionEntry> GetDateFunctions()
275     {
276         return Span<const base::BuiltinFunctionEntry>(DATE_FUNCTIONS);
277     }
278 
279     // Excluding the constructor and '@@' internal properties.
GetDatePrototypeFunctions()280     static Span<const base::BuiltinFunctionEntry> GetDatePrototypeFunctions()
281     {
282         return Span<const base::BuiltinFunctionEntry>(DATE_PROTOTYPE_FUNCTIONS);
283     }
284 
GetNumPrototypeInlinedProperties()285     static size_t GetNumPrototypeInlinedProperties()
286     {
287         // 2 : 2 more inline properties in Date.prototype:
288         //   (1) Date.prototype.constructor
289         //   (2) Date.prototype [ @@toPrimitive ]
290         return GetDatePrototypeFunctions().Size() + 2;
291     }
292 
293 private:
294 #define BUILTIN_DATE_FUNCTION_ENTRY(name, func, length, builtinId) \
295     base::BuiltinFunctionEntry::Create(name, BuiltinsDate::func, length, kungfu::BuiltinsStubCSigns::builtinId),
296 
297     static constexpr std::array DATE_FUNCTIONS = {
298         BUILTIN_DATE_FUNCTIONS(BUILTIN_DATE_FUNCTION_ENTRY)
299     };
300     static constexpr std::array DATE_PROTOTYPE_FUNCTIONS = {
301         BUILTIN_DATE_PROTOTYPE_FUNCTIONS(BUILTIN_DATE_FUNCTION_ENTRY)
302     };
303 #undef BUILTIN_DATE_FUNCTION_ENTRY
304     static JSTaggedValue ExtractDateFields(JSThread *thread, uint32_t &length, EcmaRuntimeCallInfo *argv,
305         JSTaggedValue &timeValue);
306 
307     // definition for set data code.
308     static constexpr uint32_t CODE_SET_DATE = 0x32;
309     static constexpr uint32_t CODE_SET_MILLISECONDS = 0x76;
310     static constexpr uint32_t CODE_SET_SECONDS = 0x75;
311     static constexpr uint32_t CODE_SET_MINUTES = 0x74;
312     static constexpr uint32_t CODE_SET_HOURS = 0x73;
313     static constexpr uint32_t CODE_SET_MONTH = 0x31;
314     static constexpr uint32_t CODE_SET_FULL_YEAR = 0x30;
315     static constexpr uint8_t CONSTRUCTOR_MAX_LENGTH = 7;
316 };
317 }  // namespace panda::ecmascript::builtins
318 #endif  // ECMASCRIPT_BUILTINS_BUILTINS_DATE_H
319