1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QV4DATEOBJECT_P_H
4#define QV4DATEOBJECT_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include "qv4object_p.h"
18#include "qv4functionobject_p.h"
19#include "qv4referenceobject_p.h"
20#include <QtCore/private/qnumeric_p.h>
21#include <QtCore/qdatetime.h>
22
23QT_BEGIN_NAMESPACE
24
25class QDateTime;
26
27namespace QV4 {
28
29struct Date
30{
31 static constexpr quint64 MaxDateVal = 8.64e15;
32
33 void init() { storage = InvalidDateVal; }
34 void init(Date date) { storage = date.storage; }
35 void init(double value);
36 void init(const QDateTime &dateTime);
37 void init(QDate date);
38 void init(QTime time, ExecutionEngine *engine);
39
40 Date &operator=(double value)
41 {
42 storage = (storage & (HasQDate | HasQTime)) | encode(value);
43 return *this;
44 }
45
46 operator double() const
47 {
48 const quint64 raw = (storage & ~(HasQDate | HasQTime));
49 if (raw == 0)
50 return qt_qnan();
51
52 if (raw > MaxDateVal)
53 return double(raw - MaxDateVal - Extra);
54
55 return double(raw) - double(MaxDateVal) - double(Extra);
56 }
57
58 QDate toQDate() const;
59 QTime toQTime() const;
60 QDateTime toQDateTime() const;
61 QVariant toVariant() const;
62
63 template<typename Function>
64 bool withReadonlyStoragePointer(Function function)
65 {
66 switch (storage & (HasQDate | HasQTime)) {
67 case HasQDate: {
68 QDate date = toQDate();
69 return function(&date);
70 }
71 case HasQTime: {
72 QTime time = toQTime();
73 return function(&time);
74 }
75 case (HasQTime | HasQDate): {
76 QDateTime dateTime = toQDateTime();
77 return function(&dateTime);
78 }
79 default: {
80 double d = operator double();
81 return function(&d);
82 }
83 }
84 }
85
86 template<typename Function>
87 bool withWriteonlyStoragePointer(Function function, ExecutionEngine *engine)
88 {
89 switch (storage & (HasQDate | HasQTime)) {
90 case HasQDate: {
91 QDate date;
92 if (function(&date)) {
93 init(date);
94 return true;
95 }
96 return false;
97 }
98 case HasQTime: {
99 QTime time;
100 if (function(&time)) {
101 init(time, engine);
102 return true;
103 }
104 return false;
105 }
106 case (HasQTime | HasQDate): {
107 QDateTime dateTime;
108 if (function(&dateTime)) {
109 init(dateTime);
110 return true;
111 }
112 return false;
113 }
114 default: {
115 double d;
116 if (function(&d)) {
117 init(value: d);
118 return true;
119 }
120 return false;
121 }
122 }
123 }
124
125private:
126 static constexpr quint64 InvalidDateVal = 0;
127 static constexpr quint64 Extra = 1;
128 static constexpr quint64 HasQDate = 1ull << 63;
129 static constexpr quint64 HasQTime = 1ull << 62;
130
131 // Make all our dates fit into quint64, leaving space for the flags
132 static_assert(((MaxDateVal * 2 + Extra) & (HasQDate | HasQTime)) == 0ull);
133
134 static quint64 encode(double value);
135 static quint64 encode(const QDateTime &dateTime);
136
137 quint64 storage;
138};
139
140namespace Heap {
141
142#define DateObjectMembers(class, Member)
143DECLARE_HEAP_OBJECT(DateObject, ReferenceObject) {
144 DECLARE_MARKOBJECTS(DateObject);
145
146 void doSetLocation()
147 {
148 if (CppStackFrame *frame = internalClass->engine->currentStackFrame)
149 setLocation(function: frame->v4Function, statement: frame->statementNumber());
150 }
151
152 void init()
153 {
154 ReferenceObject::init(object: nullptr, property: -1, flags: {});
155 m_date.init();
156 }
157
158 void init(Date date)
159 {
160 ReferenceObject::init(object: nullptr, property: -1, flags: {});
161 m_date.init(date);
162 }
163
164 void init(double dateTime)
165 {
166 ReferenceObject::init(object: nullptr, property: -1, flags: {});
167 m_date.init(value: dateTime);
168 }
169
170 void init(const QDateTime &dateTime)
171 {
172 ReferenceObject::init(object: nullptr, property: -1, flags: {});
173 m_date.init(dateTime);
174 }
175
176 void init(const QDateTime &dateTime, Heap::Object *parent, int property, Flags flags)
177 {
178 ReferenceObject::init(object: parent, property, flags: flags | EnforcesLocation);
179 doSetLocation();
180 m_date.init(dateTime);
181 };
182
183 void init(QDate date, Heap::Object *parent, int property, Flags flags)
184 {
185 ReferenceObject::init(object: parent, property, flags: flags | EnforcesLocation);
186 doSetLocation();
187 m_date.init(date);
188 };
189
190 void init(QTime time, Heap::Object *parent, int property, Flags flags)
191 {
192 ReferenceObject::init(object: parent, property, flags: flags | EnforcesLocation);
193 doSetLocation();
194 m_date.init(time, engine: internalClass->engine);
195 };
196
197 DateObject *detached() const;
198 bool setVariant(const QVariant &variant);
199
200 void setDate(double newDate)
201 {
202 m_date = newDate;
203 if (isAttachedToProperty())
204 writeBack();
205 }
206
207 double date() const
208 {
209 return m_date;
210 }
211
212 QVariant toVariant() const { return m_date.toVariant(); }
213 QDateTime toQDateTime() const { return m_date.toQDateTime(); }
214
215 bool readReference()
216 {
217 if (!object())
218 return false;
219
220 if (!isDirty())
221 return true;
222
223 QV4::Scope scope(internalClass->engine);
224 QV4::ScopedObject o(scope, object());
225
226 bool wasRead = false;
227 if (isVariant()) {
228 QVariant variant;
229 void *a[] = { &variant };
230 wasRead = o->metacall(call: QMetaObject::ReadProperty, index: property(), a)
231 && setVariant(variant);
232 } else {
233 wasRead = m_date.withWriteonlyStoragePointer(function: [&](void *storagePointer) {
234 void *a[] = { storagePointer };
235 return o->metacall(call: QMetaObject::ReadProperty, index: property(), a);
236 }, engine: scope.engine);
237 }
238
239 setDirty(!isConnected() || !wasRead);
240 return wasRead;
241 }
242
243 bool writeBack(int internalIndex = QV4::ReferenceObject::AllProperties)
244 {
245 if (!object() || !canWriteBack())
246 return false;
247
248 QV4::Scope scope(internalClass->engine);
249 QV4::ScopedObject o(scope, object());
250
251 int flags = 0;
252 int status = -1;
253 if (isVariant()) {
254 QVariant variant = toVariant();
255 void *a[] = { &variant, nullptr, &status, &flags, &internalIndex };
256 return o->metacall(call: QMetaObject::WriteProperty, index: property(), a);
257 }
258
259 return m_date.withReadonlyStoragePointer(function: [&](void *storagePointer) {
260 void *a[] = { storagePointer, nullptr, &status, &flags, &internalIndex };
261 return o->metacall(call: QMetaObject::WriteProperty, index: property(), a);
262 });
263 }
264
265private:
266 Date m_date;
267};
268
269
270struct DateCtor : FunctionObject {
271 void init(QV4::ExecutionEngine *engine);
272};
273
274}
275
276struct DateObject: ReferenceObject {
277 V4_OBJECT2(DateObject, ReferenceObject)
278 Q_MANAGED_TYPE(DateObject)
279 V4_PROTOTYPE(datePrototype)
280
281 void setDate(double date) { d()->setDate(date); }
282 double date() const { return d()->date(); }
283
284 Q_QML_EXPORT QDateTime toQDateTime() const;
285 QString toString() const;
286
287 static QString dateTimeToString(const QDateTime &dateTime, ExecutionEngine *engine);
288 static double dateTimeToNumber(const QDateTime &dateTime);
289 static QDate dateTimeToDate(const QDateTime &dateTime);
290 static QDateTime stringToDateTime(const QString &string, ExecutionEngine *engine);
291 static QDateTime timestampToDateTime(double timestamp, QTimeZone zone = QTimeZone::LocalTime);
292 static double componentsToTimestamp(
293 double year, double month, double day,
294 double hours, double mins, double secs, double ms,
295 ExecutionEngine *v4);
296};
297
298template<>
299inline const DateObject *Value::as() const {
300 return isManaged() && m()->internalClass->vtable->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr;
301}
302
303struct DateCtor: FunctionObject
304{
305 V4_OBJECT2(DateCtor, FunctionObject)
306
307 static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
308 static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int);
309};
310
311struct DatePrototype: Object
312{
313 V4_PROTOTYPE(objectPrototype)
314
315 void init(ExecutionEngine *engine, Object *ctor);
316
317 static double getThisDate(ExecutionEngine *v4, const Value *thisObject);
318
319 static ReturnedValue method_parse(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
320 static ReturnedValue method_UTC(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
321 static ReturnedValue method_now(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
322
323 static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
324 static ReturnedValue method_toDateString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
325 static ReturnedValue method_toTimeString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
326 static ReturnedValue method_toLocaleString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
327 static ReturnedValue method_toLocaleDateString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
328 static ReturnedValue method_toLocaleTimeString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
329 static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
330 static ReturnedValue method_getTime(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
331 static ReturnedValue method_getYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
332 static ReturnedValue method_getFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
333 static ReturnedValue method_getUTCFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
334 static ReturnedValue method_getMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
335 static ReturnedValue method_getUTCMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
336 static ReturnedValue method_getDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
337 static ReturnedValue method_getUTCDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
338 static ReturnedValue method_getDay(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
339 static ReturnedValue method_getUTCDay(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
340 static ReturnedValue method_getHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
341 static ReturnedValue method_getUTCHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
342 static ReturnedValue method_getMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
343 static ReturnedValue method_getUTCMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
344 static ReturnedValue method_getSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
345 static ReturnedValue method_getUTCSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
346 static ReturnedValue method_getMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
347 static ReturnedValue method_getUTCMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
348 static ReturnedValue method_getTimezoneOffset(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
349 static ReturnedValue method_setTime(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
350 static ReturnedValue method_setMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
351 static ReturnedValue method_setUTCMilliseconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
352 static ReturnedValue method_setSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
353 static ReturnedValue method_setUTCSeconds(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
354 static ReturnedValue method_setMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
355 static ReturnedValue method_setUTCMinutes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
356 static ReturnedValue method_setHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
357 static ReturnedValue method_setUTCHours(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
358 static ReturnedValue method_setDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
359 static ReturnedValue method_setUTCDate(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
360 static ReturnedValue method_setMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
361 static ReturnedValue method_setUTCMonth(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
362 static ReturnedValue method_setYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
363 static ReturnedValue method_setFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
364 static ReturnedValue method_setUTCFullYear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
365 static ReturnedValue method_toUTCString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
366 static ReturnedValue method_toISOString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
367 static ReturnedValue method_toJSON(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
368 static ReturnedValue method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int);
369
370 static void timezoneUpdated(ExecutionEngine *e);
371};
372
373template<>
374inline bool ReferenceObject::readReference<Heap::DateObject>(Heap::DateObject *ref)
375{
376 return ref->readReference();
377}
378
379template<>
380inline bool ReferenceObject::writeBack<Heap::DateObject>(Heap::DateObject *ref, int internalIndex)
381{
382 return ref->writeBack(internalIndex);
383}
384
385}
386
387QT_END_NAMESPACE
388
389#endif // QV4ECMAOBJECTS_P_H
390

source code of qtdeclarative/src/qml/jsruntime/qv4dateobject_p.h