2012-11-17 21:10:52 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
2012-11-17 21:10:52 +00:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2012-11-17 21:10:52 +00:00
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
**
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3.0 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
**
|
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
#ifndef QMLJS_VALUE_H
|
|
|
|
#define QMLJS_VALUE_H
|
|
|
|
|
2013-04-19 19:24:46 +00:00
|
|
|
#include <cmath> // this HAS to come
|
|
|
|
|
2012-11-17 21:10:52 +00:00
|
|
|
#include <QtCore/QString>
|
|
|
|
#include <QtCore/qnumeric.h>
|
2013-04-15 09:50:16 +00:00
|
|
|
#include "qv4global_p.h"
|
|
|
|
#include "qv4string_p.h"
|
2012-11-17 21:10:52 +00:00
|
|
|
#include <QtCore/QDebug>
|
2013-04-15 09:50:16 +00:00
|
|
|
#include "qv4managed_p.h"
|
2013-08-09 11:28:02 +00:00
|
|
|
#include <private/qtqmlglobal_p.h>
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2013-04-17 16:17:30 +00:00
|
|
|
//#include <wtf/MathExtras.h>
|
2013-02-14 22:16:50 +00:00
|
|
|
|
2013-06-25 12:23:35 +00:00
|
|
|
#include "qv4value_def_p.h"
|
|
|
|
|
2013-01-31 09:00:06 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
namespace QV4 {
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2013-04-19 19:24:46 +00:00
|
|
|
double __qmljs_to_number(const QV4::Value &value);
|
|
|
|
Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const QV4::Value &value);
|
|
|
|
QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
|
|
|
|
|
2013-08-26 13:07:38 +00:00
|
|
|
inline Managed *Value::asManaged() const
|
|
|
|
{
|
|
|
|
if (isManaged())
|
|
|
|
return managed();
|
|
|
|
return 0;
|
|
|
|
}
|
2013-05-06 09:37:53 +00:00
|
|
|
|
2013-06-25 12:23:35 +00:00
|
|
|
inline ExecutionEngine *Value::engine() const {
|
|
|
|
Managed *m = asManaged();
|
|
|
|
return m ? m->engine() : 0;
|
|
|
|
}
|
2013-01-28 15:46:09 +00:00
|
|
|
|
2013-06-25 12:23:35 +00:00
|
|
|
inline void Value::mark() const {
|
|
|
|
Managed *m = asManaged();
|
|
|
|
if (m)
|
|
|
|
m->mark();
|
|
|
|
}
|
2012-11-17 21:10:52 +00:00
|
|
|
|
|
|
|
inline Value Value::undefinedValue()
|
|
|
|
{
|
|
|
|
Value v;
|
2013-02-21 11:07:17 +00:00
|
|
|
#if QT_POINTER_SIZE == 8
|
2012-11-17 21:10:52 +00:00
|
|
|
v.val = quint64(_Undefined_Type) << Tag_Shift;
|
|
|
|
#else
|
|
|
|
v.tag = _Undefined_Type;
|
|
|
|
v.int_32 = 0;
|
|
|
|
#endif
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Value Value::nullValue()
|
|
|
|
{
|
|
|
|
Value v;
|
2013-02-21 11:07:17 +00:00
|
|
|
#if QT_POINTER_SIZE == 8
|
2012-11-17 21:10:52 +00:00
|
|
|
v.val = quint64(_Null_Type) << Tag_Shift;
|
|
|
|
#else
|
|
|
|
v.tag = _Null_Type;
|
|
|
|
v.int_32 = 0;
|
|
|
|
#endif
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2013-05-07 10:56:58 +00:00
|
|
|
inline Value Value::emptyValue()
|
2013-04-10 08:46:23 +00:00
|
|
|
{
|
2013-04-19 11:03:42 +00:00
|
|
|
Value v;
|
2013-05-07 10:56:58 +00:00
|
|
|
v.tag = Value::_Empty_Type;
|
2013-04-10 08:46:23 +00:00
|
|
|
v.uint_32 = 0;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-17 21:10:52 +00:00
|
|
|
inline Value Value::fromBoolean(Bool b)
|
|
|
|
{
|
|
|
|
Value v;
|
|
|
|
v.tag = _Boolean_Type;
|
|
|
|
v.int_32 = (bool)b;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Value Value::fromDouble(double d)
|
|
|
|
{
|
|
|
|
Value v;
|
|
|
|
v.dbl = d;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Value Value::fromInt32(int i)
|
|
|
|
{
|
|
|
|
Value v;
|
|
|
|
v.tag = _Integer_Type;
|
|
|
|
v.int_32 = i;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2013-01-11 13:33:10 +00:00
|
|
|
inline Value Value::fromUInt32(uint i)
|
|
|
|
{
|
|
|
|
Value v;
|
|
|
|
if (i < INT_MAX) {
|
|
|
|
v.tag = _Integer_Type;
|
|
|
|
v.int_32 = (int)i;
|
|
|
|
} else {
|
|
|
|
v.dbl = i;
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2012-11-17 21:10:52 +00:00
|
|
|
inline Value Value::fromString(String *s)
|
|
|
|
{
|
|
|
|
Value v;
|
2013-02-21 11:07:17 +00:00
|
|
|
#if QT_POINTER_SIZE == 8
|
2012-11-17 21:10:52 +00:00
|
|
|
v.val = (quint64)s;
|
|
|
|
v.val |= quint64(_String_Type) << Tag_Shift;
|
|
|
|
#else
|
|
|
|
v.tag = _String_Type;
|
|
|
|
v.s = s;
|
|
|
|
#endif
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Value Value::fromObject(Object *o)
|
|
|
|
{
|
|
|
|
Value v;
|
2013-02-21 11:07:17 +00:00
|
|
|
#if QT_POINTER_SIZE == 8
|
2012-11-17 21:10:52 +00:00
|
|
|
v.val = (quint64)o;
|
|
|
|
v.val |= quint64(_Object_Type) << Tag_Shift;
|
|
|
|
#else
|
|
|
|
v.tag = _Object_Type;
|
|
|
|
v.o = o;
|
|
|
|
#endif
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2013-06-07 20:43:14 +00:00
|
|
|
inline bool Value::toBoolean() const
|
2013-02-14 22:16:50 +00:00
|
|
|
{
|
|
|
|
switch (type()) {
|
|
|
|
case Value::Undefined_Type:
|
|
|
|
case Value::Null_Type:
|
|
|
|
return false;
|
|
|
|
case Value::Boolean_Type:
|
|
|
|
case Value::Integer_Type:
|
|
|
|
return (bool)int_32;
|
|
|
|
case Value::String_Type:
|
|
|
|
return stringValue()->toQString().length() > 0;
|
|
|
|
case Value::Object_Type:
|
|
|
|
return true;
|
|
|
|
default: // double
|
2013-08-09 13:37:39 +00:00
|
|
|
return doubleValue() && !std::isnan(doubleValue());
|
2013-02-14 22:16:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 20:41:49 +00:00
|
|
|
inline Object *Value::toObject(ExecutionContext *ctx) const
|
|
|
|
{
|
|
|
|
if (isObject())
|
|
|
|
return objectValue();
|
|
|
|
return __qmljs_convert_to_object(ctx, *this);
|
|
|
|
}
|
|
|
|
|
2013-04-14 20:01:20 +00:00
|
|
|
inline int Value::toInt32() const
|
2012-12-13 13:48:20 +00:00
|
|
|
{
|
|
|
|
if (isConvertibleToInt())
|
|
|
|
return int_32;
|
|
|
|
double d;
|
|
|
|
if (isDouble())
|
|
|
|
d = dbl;
|
|
|
|
else
|
2013-04-14 20:01:20 +00:00
|
|
|
d = __qmljs_to_number(*this);
|
2012-12-13 13:48:20 +00:00
|
|
|
|
|
|
|
const double D32 = 4294967296.0;
|
|
|
|
const double D31 = D32 / 2.0;
|
|
|
|
|
|
|
|
if ((d >= -D31 && d < D31))
|
|
|
|
return static_cast<int>(d);
|
|
|
|
|
2013-08-09 13:37:39 +00:00
|
|
|
return Value::toInt32(d);
|
2012-12-13 13:48:20 +00:00
|
|
|
}
|
|
|
|
|
2013-04-14 20:01:20 +00:00
|
|
|
inline unsigned int Value::toUInt32() const
|
|
|
|
{
|
2012-12-13 13:48:20 +00:00
|
|
|
if (isConvertibleToInt())
|
|
|
|
return (unsigned) int_32;
|
|
|
|
double d;
|
|
|
|
if (isDouble())
|
|
|
|
d = dbl;
|
|
|
|
else
|
2013-04-14 20:01:20 +00:00
|
|
|
d = __qmljs_to_number(*this);
|
2012-12-13 13:48:20 +00:00
|
|
|
|
|
|
|
const double D32 = 4294967296.0;
|
2013-08-09 13:37:39 +00:00
|
|
|
if (d >= 0 && d < D32)
|
|
|
|
return static_cast<uint>(d);
|
2012-12-13 13:48:20 +00:00
|
|
|
return toUInt32(d);
|
|
|
|
}
|
|
|
|
|
2013-01-11 09:13:02 +00:00
|
|
|
inline uint Value::asArrayIndex() const
|
|
|
|
{
|
|
|
|
if (isInteger() && int_32 >= 0)
|
|
|
|
return (uint)int_32;
|
|
|
|
if (!isDouble())
|
|
|
|
return UINT_MAX;
|
|
|
|
uint idx = (uint)dbl;
|
|
|
|
if (idx != dbl)
|
|
|
|
return UINT_MAX;
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2013-04-14 20:01:20 +00:00
|
|
|
inline uint Value::asArrayLength(bool *ok) const
|
2013-01-11 09:13:02 +00:00
|
|
|
{
|
|
|
|
*ok = true;
|
2013-01-11 15:28:05 +00:00
|
|
|
if (isConvertibleToInt() && int_32 >= 0)
|
2013-01-11 09:13:02 +00:00
|
|
|
return (uint)int_32;
|
2013-01-11 15:28:05 +00:00
|
|
|
if (isDouble()) {
|
|
|
|
uint idx = (uint)dbl;
|
|
|
|
if ((double)idx != dbl) {
|
|
|
|
*ok = false;
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
return idx;
|
|
|
|
}
|
2013-01-11 13:33:10 +00:00
|
|
|
if (isString())
|
|
|
|
return stringValue()->toUInt(ok);
|
|
|
|
|
2013-04-14 20:01:20 +00:00
|
|
|
uint idx = toUInt32();
|
|
|
|
double d = toNumber();
|
2013-01-11 15:28:05 +00:00
|
|
|
if (d != idx) {
|
2013-01-11 09:13:02 +00:00
|
|
|
*ok = false;
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2013-02-16 22:27:07 +00:00
|
|
|
inline String *Value::asString() const
|
|
|
|
{
|
|
|
|
if (isString())
|
|
|
|
return stringValue();
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-11 09:13:02 +00:00
|
|
|
|
2013-01-25 12:23:58 +00:00
|
|
|
inline Object *Value::asObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? objectValue() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline FunctionObject *Value::asFunctionObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asFunctionObject() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BooleanObject *Value::asBooleanObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asBooleanObject() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline NumberObject *Value::asNumberObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asNumberObject() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline StringObject *Value::asStringObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asStringObject() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DateObject *Value::asDateObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asDateObject() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline ArrayObject *Value::asArrayObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asArrayObject() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline ErrorObject *Value::asErrorObject() const
|
|
|
|
{
|
|
|
|
return isObject() ? managed()->asErrorObject() : 0;
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:07:57 +00:00
|
|
|
// ###
|
2013-09-06 10:44:12 +00:00
|
|
|
inline Value Managed::construct(CallData *d) {
|
2013-08-21 15:31:22 +00:00
|
|
|
return vtbl->construct(this, d);
|
2013-02-14 13:07:57 +00:00
|
|
|
}
|
2013-09-06 10:44:12 +00:00
|
|
|
inline Value Managed::call(CallData *d) {
|
2013-08-21 15:31:22 +00:00
|
|
|
return vtbl->call(this, d);
|
2013-02-14 13:07:57 +00:00
|
|
|
}
|
2013-01-25 12:23:58 +00:00
|
|
|
|
2013-08-09 11:28:02 +00:00
|
|
|
struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate
|
2013-04-16 09:36:56 +00:00
|
|
|
{
|
2013-06-21 13:19:20 +00:00
|
|
|
PersistentValuePrivate(const Value &v, ExecutionEngine *engine = 0, bool weak = false);
|
2013-06-14 11:54:36 +00:00
|
|
|
virtual ~PersistentValuePrivate();
|
2013-04-16 09:36:56 +00:00
|
|
|
Value value;
|
2013-05-23 20:13:42 +00:00
|
|
|
uint refcount;
|
2013-06-21 13:19:20 +00:00
|
|
|
QV4::ExecutionEngine *engine;
|
2013-05-06 13:11:01 +00:00
|
|
|
PersistentValuePrivate **prev;
|
2013-04-16 09:36:56 +00:00
|
|
|
PersistentValuePrivate *next;
|
|
|
|
|
2013-05-23 20:13:42 +00:00
|
|
|
void removeFromList();
|
2013-04-16 09:36:56 +00:00
|
|
|
void ref() { ++refcount; }
|
|
|
|
void deref();
|
2013-05-29 12:58:52 +00:00
|
|
|
PersistentValuePrivate *detach(const QV4::Value &value, bool weak = false);
|
2013-06-21 13:19:20 +00:00
|
|
|
|
|
|
|
bool checkEngine(QV4::ExecutionEngine *otherEngine) {
|
|
|
|
if (!engine) {
|
|
|
|
Q_ASSERT(!value.isObject());
|
|
|
|
engine = otherEngine;
|
|
|
|
}
|
|
|
|
return (engine == otherEngine);
|
|
|
|
}
|
2013-04-16 09:36:56 +00:00
|
|
|
};
|
|
|
|
|
2013-05-07 10:29:30 +00:00
|
|
|
class Q_QML_EXPORT PersistentValue
|
2013-03-06 19:04:43 +00:00
|
|
|
{
|
|
|
|
public:
|
2013-05-07 11:17:57 +00:00
|
|
|
PersistentValue() : d(0) {}
|
2013-05-06 09:37:53 +00:00
|
|
|
PersistentValue(const Value &val);
|
2013-03-06 19:04:43 +00:00
|
|
|
PersistentValue(const PersistentValue &other);
|
|
|
|
PersistentValue &operator=(const PersistentValue &other);
|
2013-05-06 09:37:53 +00:00
|
|
|
PersistentValue &operator=(const Value &other);
|
2013-03-06 19:04:43 +00:00
|
|
|
~PersistentValue();
|
|
|
|
|
2013-05-07 11:17:57 +00:00
|
|
|
Value value() const {
|
|
|
|
return d ? d->value : Value::emptyValue();
|
|
|
|
}
|
2013-03-06 19:04:43 +00:00
|
|
|
|
2013-05-06 09:37:53 +00:00
|
|
|
ExecutionEngine *engine() {
|
2013-05-07 11:17:57 +00:00
|
|
|
if (!d)
|
|
|
|
return 0;
|
2013-05-06 09:37:53 +00:00
|
|
|
Managed *m = d->value.asManaged();
|
|
|
|
return m ? m->engine() : 0;
|
|
|
|
}
|
|
|
|
|
2013-05-07 11:17:57 +00:00
|
|
|
operator Value() const { return value(); }
|
|
|
|
|
2013-05-08 13:21:42 +00:00
|
|
|
bool isEmpty() const { return !d || d->value.isEmpty(); }
|
2013-05-08 11:14:40 +00:00
|
|
|
void clear() {
|
|
|
|
*this = PersistentValue();
|
|
|
|
}
|
2013-03-06 19:04:43 +00:00
|
|
|
|
|
|
|
private:
|
2013-04-16 09:36:56 +00:00
|
|
|
PersistentValuePrivate *d;
|
2013-03-06 19:04:43 +00:00
|
|
|
};
|
|
|
|
|
2013-05-23 20:13:42 +00:00
|
|
|
class Q_QML_EXPORT WeakValue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
WeakValue() : d(0) {}
|
|
|
|
WeakValue(const Value &val);
|
|
|
|
WeakValue(const WeakValue &other);
|
|
|
|
WeakValue &operator=(const WeakValue &other);
|
|
|
|
WeakValue &operator=(const Value &other);
|
|
|
|
~WeakValue();
|
|
|
|
|
|
|
|
Value value() const {
|
|
|
|
return d ? d->value : Value::emptyValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionEngine *engine() {
|
|
|
|
if (!d)
|
|
|
|
return 0;
|
|
|
|
Managed *m = d->value.asManaged();
|
|
|
|
return m ? m->engine() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator Value() const { return value(); }
|
|
|
|
|
|
|
|
bool isEmpty() const { return !d || d->value.isEmpty(); }
|
|
|
|
void clear() {
|
|
|
|
*this = WeakValue();
|
|
|
|
}
|
|
|
|
|
2013-05-24 15:12:57 +00:00
|
|
|
void markOnce();
|
|
|
|
|
2013-05-23 20:13:42 +00:00
|
|
|
private:
|
|
|
|
PersistentValuePrivate *d;
|
|
|
|
};
|
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
} // namespace QV4
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2013-01-31 09:00:06 +00:00
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
2012-11-17 21:10:52 +00:00
|
|
|
#endif
|