// note that the actual SRD is owned by the JS engine,
// so we cannot delete the SRD; but we can free the
// memory used by the variant in the SRD.
- while (ScarceResourceData *sr = scarceResources.first()) {
+ QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine());
+ while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) {
sr->data = QVariant();
- scarceResources.remove(sr);
+ engine->scarceResources.remove(sr);
}
}
}
QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders;
- // Scarce resources are "exceptionally high cost" QVariant types where allowing the
- // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
- // out-of-resource situations. When such a resource is passed into JavaScript we
- // add it to the scarceResources list and it is destroyed when we return from the
- // JavaScript execution that created it. The user can prevent this behavior by
- // calling preserve() on the object which removes it from this scarceResource list.
- class ScarceResourceData {
- public:
- ScarceResourceData(const QVariant &data) : data(data) {}
- QVariant data;
- QIntrusiveListNode node;
- };
- QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
int scarceResourcesRefCount;
void referenceScarceResources();
void dereferenceScarceResources();
#include "qqmlbinding_p.h"
#include "qqmlpropertyvalueinterceptor_p.h"
-#include <private/qv8variantresource_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qv4object_p.h>
+#include <private/qv4variantobject_p.h>
QT_BEGIN_NAMESPACE
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
v8::Handle<v8::Value> oldv = varProperties.value().asObject()->getIndexed(id - firstVarPropertyIndex);
- if (oldv->IsObject()) {
- QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v8::Handle<v8::Object>::Cast(oldv));
- if (r) {
- r->removeVmePropertyReference();
- }
- }
+ if (QV4::VariantObject *v = oldv->v4Value().asVariantObject())
+ v->removeVmePropertyReference();
QObject *valueObject = 0;
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
if (value->IsObject()) {
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
- if (QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v8::Handle<v8::Object>::Cast(value))) {
- r->addVmePropertyReference();
+ if (QV4::VariantObject *v = value->v4Value().asVariantObject()) {
+ v->addVmePropertyReference();
} else if (QV8QObjectResource *r = v8_resource_cast<QV8QObjectResource>(v8::Handle<v8::Object>::Cast(value))) {
// We need to track this QObject to signal its deletion
valueObject = r->object;
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
v8::Handle<v8::Value> oldv = varProperties.value().asObject()->getIndexed(id - firstVarPropertyIndex);
- if (oldv->IsObject()) {
- QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v8::Handle<v8::Object>::Cast(oldv));
- if (r) {
- r->removeVmePropertyReference();
- }
- }
+ if (QV4::VariantObject *v = oldv->v4Value().asVariantObject())
+ v->removeVmePropertyReference();
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
v8::Handle<v8::Value> newv = QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value);
- if (newv->IsObject()) {
- QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v8::Handle<v8::Object>::Cast(newv));
- if (r) {
- r->addVmePropertyReference();
- }
- }
+ if (QV4::VariantObject *v = newv->v4Value().asVariantObject())
+ v->addVmePropertyReference();
// Write the value and emit change signal as appropriate.
QVariant currentValue = readPropertyAsVariant(id);
#include <qv4mathobject_p.h>
#include <qv4numberobject_p.h>
#include <qv4regexpobject_p.h>
+#include <qv4variantobject_p.h>
#include <qv4runtime_p.h>
#include "qv4mm_p.h"
#include <qv4argumentsobject_p.h>
typeErrorPrototype = new (memoryManager) TypeErrorPrototype(this);
uRIErrorPrototype = new (memoryManager) URIErrorPrototype(this);
+ variantPrototype = new (memoryManager) VariantPrototype(this);
+
stringPrototype->prototype = objectPrototype;
numberPrototype->prototype = objectPrototype;
booleanPrototype->prototype = objectPrototype;
typeErrorPrototype->init(this, typeErrorCtor);
uRIErrorPrototype->init(this, uRIErrorCtor);
+ variantPrototype->initClass(this);
+
//
// set up the global object
//
return new (memoryManager) URIErrorObject(this, message);
}
+Object *ExecutionEngine::newVariantObject(const QVariant &v)
+{
+ return new (memoryManager) VariantObject(this, v);
+}
+
Object *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
{
return new (memoryManager) ForEachIteratorObject(ctx, o);
#include "qv4util_p.h"
#include "qv4context_p.h"
#include "qv4property_p.h"
-#include <setjmp.h>
+#include <private/qintrusivelist_p.h>
namespace WTF {
class BumpPointerAllocator;
struct SyntaxErrorPrototype;
struct TypeErrorPrototype;
struct URIErrorPrototype;
+struct VariantPrototype;
struct EvalFunction;
struct Identifiers;
struct InternalClass;
TypeErrorPrototype *typeErrorPrototype;
URIErrorPrototype *uRIErrorPrototype;
+ VariantPrototype *variantPrototype;
+
QQmlJS::MemoryPool classPool;
InternalClass *emptyClass;
InternalClass *arrayClass;
RegExpCache *regExpCache;
+ // Scarce resources are "exceptionally high cost" QVariant types where allowing the
+ // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
+ // out-of-resource situations. When such a resource is passed into JavaScript we
+ // add it to the scarceResources list and it is destroyed when we return from the
+ // JavaScript execution that created it. The user can prevent this behavior by
+ // calling preserve() on the object which removes it from this scarceResource list.
+ class ScarceResourceData {
+ public:
+ ScarceResourceData(const QVariant &data) : data(data) {}
+ QVariant data;
+ QIntrusiveListNode node;
+ };
+ QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
+
ExecutionEngine(QQmlJS::EvalISelFactory *iselFactory = 0);
~ExecutionEngine();
Object *newRangeErrorObject(const QString &message);
Object *newURIErrorObject(Value message);
+ Object *newVariantObject(const QVariant &v);
+
Object *newForEachIteratorObject(ExecutionContext *ctx, Object *o);
Object *qmlContextObject() const;
class RegExp;
struct Lookup;
struct ExecutionEngine;
+struct VariantObject;
struct ManagedVTable
{
Type_QmlRealList,
Type_QmlBoolList,
Type_QmlStringList,
- Type_QmlUrlList
+ Type_QmlUrlList,
+
+ // Wrapped QVariant
+ Type_QVariant
};
ExecutionEngine *engine() const;
QQmlLocaleData *asQmlLocale() { return type == Type_QmlLocale ? reinterpret_cast<QQmlLocaleData *>(this) : 0; }
QQuickJSContext2D *asQQuickJSContext2D() { return type == Type_QQuickJSContext2D ? reinterpret_cast<QQuickJSContext2D *>(this) : 0; }
+ VariantObject *asVariantObject() { return type == Type_QVariant ? reinterpret_cast<VariantObject *>(this) : 0; }
QQmlIntList *asQmlIntList() { return type == Type_QmlIntList ? reinterpret_cast<QQmlIntList *>(this): 0; }
QQmlRealList *asQmlRealList() { return type == Type_QmlRealList ? reinterpret_cast<QQmlRealList *>(this): 0; }
RegExpObject *asRegExpObject() const;
ArrayObject *asArrayObject() const;
ErrorObject *asErrorObject() const;
+ VariantObject *asVariantObject() const;
uint asArrayIndex() const;
uint asArrayLength(bool *ok) const;
return isObject() ? managed()->asErrorObject() : 0;
}
+inline VariantObject *Value::asVariantObject() const
+{
+ return isObject() ? managed()->asVariantObject() : 0;
+}
+
// ###
inline Value Managed::construct(ExecutionContext *context, Value *args, int argc) {
return vtbl->construct(this, context, args, argc);
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $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$
+**
+****************************************************************************/
+
+#include "qv4variantobject_p.h"
+#include "qv4functionobject_p.h"
+#include "qv4objectproto_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QV4;
+
+DEFINE_MANAGED_VTABLE(VariantObject);
+
+VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
+ : Object(engine)
+ , ExecutionEngine::ScarceResourceData(value)
+ , m_vmePropertyReferenceCount(0)
+{
+ type = Type_QVariant;
+ prototype = engine->variantPrototype;
+ if (isScarce())
+ internalClass->engine->scarceResources.insert(this);
+}
+
+QVariant VariantObject::toVariant(const QV4::Value &v)
+{
+ VariantObject *o = v.asVariantObject();
+ return o ? o->data : QVariant();
+}
+
+bool VariantObject::isScarce() const
+{
+ QVariant::Type t = data.type();
+ return t == QVariant::Pixmap || t == QVariant::Image;
+}
+
+void VariantObject::destroy(Managed *that)
+{
+ VariantObject *v = static_cast<VariantObject *>(that);
+ if (v->isScarce())
+ v->node.remove();
+ Object::destroy(that);
+}
+
+void VariantObject::addVmePropertyReference()
+{
+ if (isScarce() && ++m_vmePropertyReferenceCount == 1) {
+ // remove from the ep->scarceResources list
+ // since it is now no longer eligible to be
+ // released automatically by the engine.
+ node.remove();
+ }
+}
+
+void VariantObject::removeVmePropertyReference()
+{
+ if (isScarce() && --m_vmePropertyReferenceCount == 0) {
+ // and add to the ep->scarceResources list
+ // since it is now eligible to be released
+ // automatically by the engine.
+ internalClass->engine->scarceResources.insert(this);
+ }
+}
+
+
+VariantPrototype::VariantPrototype(ExecutionEngine *engine)
+ : VariantObject(engine, QVariant())
+{
+ prototype = engine->objectPrototype;
+}
+
+QV4::Value VariantPrototype::method_preserve(SimpleCallContext *ctx)
+{
+ VariantObject *o = ctx->thisObject.asVariantObject();
+ if (o && o->isScarce())
+ o->node.remove();
+ return Value::undefinedValue();
+}
+
+QV4::Value VariantPrototype::method_destroy(SimpleCallContext *ctx)
+{
+ VariantObject *o = ctx->thisObject.asVariantObject();
+ if (o) {
+ if (o->isScarce())
+ o->node.remove();
+ o->data = QVariant();
+ }
+ return QV4::Value::undefinedValue();
+}
+
+QV4::Value VariantPrototype::method_toString(SimpleCallContext *ctx)
+{
+ VariantObject *o = ctx->thisObject.asVariantObject();
+ if (!o)
+ return Value::undefinedValue();
+ QString result = o->data.toString();
+ if (result.isEmpty())
+ result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->data.typeName()));
+ return Value::fromString(ctx->engine->newString(result));
+}
+
+QV4::Value VariantPrototype::method_valueOf(SimpleCallContext *ctx)
+{
+ VariantObject *o = ctx->thisObject.asVariantObject();
+ if (o) {
+ QVariant v = o->data;
+ switch (v.type()) {
+ case QVariant::Invalid:
+ return Value::undefinedValue();
+ case QVariant::String:
+ return Value::fromString(ctx->engine->newString(v.toString()));
+ case QVariant::Int:
+ return Value::fromInt32(v.toInt());
+ case QVariant::Double:
+ case QVariant::UInt:
+ return Value::fromDouble(v.toDouble());
+ case QVariant::Bool:
+ return Value::fromBoolean(v.toBool());
+ default:
+ break;
+ }
+ }
+ return ctx->thisObject;
+}
+
+#include "qv4variantobject_p_jsclass.cpp"
+
+QT_END_NAMESPACE
**
****************************************************************************/
-#ifndef QV8VARIANTRESOURCE_P_H
-#define QV8VARIANTRESOURCE_P_H
+#ifndef QV4VARIANTOBJECT_P_H
+#define QV4VARIANTOBJECT_P_H
//
// W A R N I N G
//
#include <QtCore/qglobal.h>
-#include <private/qv8_p.h>
-#include <private/qv8engine_p.h>
-#include <private/qqmlengine_p.h>
+#include <QtQml/qqmllist.h>
+#include <QtCore/qvariant.h>
+
+#include <private/qv4value_p.h>
+#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
-class QV8VariantResource : public QV8ObjectResource,
- public QQmlEnginePrivate::ScarceResourceData
-{
- V8_RESOURCE_TYPE(VariantType)
+namespace QV4 {
+struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
+{
public:
- QV8VariantResource(QV8Engine *engine, const QVariant &data);
+ VariantObject(ExecutionEngine *engine, const QVariant &value);
+ ~VariantObject();
+
+ static QVariant toVariant(const QV4::Value &v);
void addVmePropertyReference();
void removeVmePropertyReference();
-
- bool m_isScarceResource;
+ bool isScarce() const;
int m_vmePropertyReferenceCount;
+
+ static void destroy(Managed *that);
+
+private:
+ static const ManagedVTable static_vtbl;
};
+struct QV4_JS_CLASS(VariantPrototype) : VariantObject
+{
+public:
+ VariantPrototype(ExecutionEngine *engine);
+
+ void initClass(ExecutionEngine *engine);
+
+ static Value method_preserve(SimpleCallContext *ctx);
+ static Value method_destroy(SimpleCallContext *ctx);
+ static Value method_toString(SimpleCallContext *ctx);
+ static Value method_valueOf(SimpleCallContext *ctx);
+
+private:
+ static const QV4::ManagedVTable static_vtbl;
+};
+
+}
+
QT_END_NAMESPACE
-#endif // QV8VARIANTRESOURCE_P_H
+#endif
$$PWD/qv4objectproto.cpp \
$$PWD/qv4regexpobject.cpp \
$$PWD/qv4stringobject.cpp \
+ $$PWD/qv4variantobject.cpp \
$$PWD/qv4string.cpp \
$$PWD/qv4objectiterator.cpp \
$$PWD/qv4regexp.cpp \
$$PWD/qv4objectproto_p.h \
$$PWD/qv4regexpobject_p.h \
$$PWD/qv4stringobject_p.h \
+ $$PWD/qv4variantobject_p.h \
$$PWD/qv4string_p.h \
$$PWD/qv4property_p.h \
$$PWD/qv4objectiterator_p.h \
JS_CLASS_SOURCES += $$PWD/qv4dateobject_p.h \
$$PWD/qv4stringobject_p.h \
$$PWD/qv4booleanobject_p.h \
- $$PWD/qv4regexpobject_p.h
+ $$PWD/qv4regexpobject_p.h \
+ $$PWD/qv4variantobject_p.h
js_class_bindings.output = ${QMAKE_FILE_BASE}_jsclass.cpp
js_class_bindings.input = JS_CLASS_SOURCES
#include "qv4dateobject_p.h"
#include "qv4runtime_p.h"
#include "qv4v8_p.h"
-#include "qv8variantwrapper_p.h"
+#include "qv4variantobject_p.h"
/*!
\since 5.0
*/
bool QJSValue::isVariant() const
{
- QV4::ExecutionEngine *e = d->engine();
- if (!e)
- return false;
-
- return QV8VariantWrapper::isVariant(d->value);
+ Managed *m = d->value.asManaged();
+ return m ? m->asVariantObject() : 0;
}
/*!
*/
QVariant QJSValue::toVariant() const
{
- return QV8VariantWrapper::toVariant(d->value);
+ return QV4::VariantObject::toVariant(d->value);
}
/*!
#include <private/qv4objectproto_p.h>
#include <private/qv4globalobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4variantobject_p.h>
Q_DECLARE_METATYPE(QList<int>)
if (lhs.IsEmpty() || rhs.IsEmpty())
return false;
+ QV4::VariantObject *lv = lhs->v4Value().asVariantObject();
+ if (lv) {
+ QV4::VariantObject *rv = rhs->v4Value().asVariantObject();
+ if (rv)
+ return lv->data == rv->data;
+
+ QV8ObjectResource *rhsr = static_cast<QV8ObjectResource*>(rhs->GetExternalResource());
+ if (rhsr->resourceType() == QV8ObjectResource::ValueTypeType)
+ return rhsr->engine->valueTypeWrapper()->isEqual(rhsr, lv->data);
+
+ return false;
+ }
+
QV8ObjectResource *lhsr = static_cast<QV8ObjectResource*>(lhs->GetExternalResource());
QV8ObjectResource *rhsr = static_cast<QV8ObjectResource*>(rhs->GetExternalResource());
// a value type might be equal to a variant or another value type
if (rhst == QV8ObjectResource::ValueTypeType) {
return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->valueTypeWrapper()->toVariant(rhsr));
- } else if (rhst == QV8ObjectResource::VariantType) {
- return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->variantWrapper()->toVariant(rhsr));
- }
- break;
- case QV8ObjectResource::VariantType:
- // a variant might be equal to a value type or other variant.
- if (rhst == QV8ObjectResource::VariantType) {
- return lhsr->engine->variantWrapper()->toVariant(lhsr) ==
- lhsr->engine->variantWrapper()->toVariant(rhsr);
- } else if (rhst == QV8ObjectResource::ValueTypeType) {
- return rhsr->engine->valueTypeWrapper()->isEqual(rhsr, rhsr->engine->variantWrapper()->toVariant(lhsr));
+ } else if (QV4::VariantObject *rv = rhs->v4Value().asVariantObject()) {
+ return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, rv->data);
}
break;
case QV8ObjectResource::SequenceType:
m_qobjectWrapper.init(this);
m_typeWrapper.init(this);
m_listWrapper.init(this);
- m_variantWrapper.init(this);
m_valueTypeWrapper.init(this);
m_sequenceWrapper.init(this);
m_jsonWrapper.init(m_v4Engine);
m_jsonWrapper.destroy();
m_sequenceWrapper.destroy();
m_valueTypeWrapper.destroy();
- m_variantWrapper.destroy();
m_listWrapper.destroy();
m_typeWrapper.destroy();
m_qobjectWrapper.destroy();
if (value.isEmpty())
return QVariant();
+ if (QV4::VariantObject *v = value.asVariantObject())
+ return v->data;
+
if (typeHint == QVariant::Bool)
return QVariant(value.toBoolean());
return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r));
case QV8ObjectResource::ListType:
return m_listWrapper.toVariant(r);
- case QV8ObjectResource::VariantType:
- return m_variantWrapper.toVariant(r);
case QV8ObjectResource::ValueTypeType:
return m_valueTypeWrapper.toVariant(r);
case QV8ObjectResource::SequenceType:
// + QObjectList
// + QList<int>
- return m_variantWrapper.newVariant(variant);
+ return QV4::Value::fromObject(m_v4Engine->newVariantObject(variant));
}
// A handle scope and context must be entered
return QV4::Value::nullValue();
} else {
// Fall back to wrapping in a QVariant.
- result = variantWrapper()->newVariant(QVariant(type, data));
+ result = QV4::Value::fromObject(m_v4Engine->newVariantObject(QVariant(type, data)));
}
}
}
return true;
if (isVariant(value) && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = variantWrapper()->variantValue(v8::Value::fromV4Value(value));
+ QVariant &var = value.asVariantObject()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
while (proto->IsObject()) {
bool canCast = false;
if (isVariant(proto->v4Value())) {
- canCast = (type == variantWrapper()->variantValue(proto).userType())
- || (valueType && (valueType == variantWrapper()->variantValue(proto).userType()));
+ const QVariant &v = proto->v4Value().asVariantObject()->data;
+ canCast = (type == v.userType()) || (valueType && (valueType == v.userType()));
}
else if (isQObject(proto->v4Value())) {
QByteArray className = name.left(name.size()-1);
if (QV4::RegExpObject *re = value.asRegExpObject())
return re->toQRegExp();
if (isVariant(value))
- return variantWrapper()->variantValue(v8::Value::fromV4Value(value));
+ return value.asVariantObject()->data;
if (isQObject(value))
return qVariantFromValue(qtObjectFromJS(value));
if (isValueType(value))
if (!value.isObject())
return 0;
+ QV4::VariantObject *v = value.asVariantObject();
+ if (v) {
+ QVariant variant = v->data;
+ int type = variant.userType();
+ if (type == QMetaType::QObjectStar)
+ return *reinterpret_cast<QObject* const *>(variant.constData());
+ }
QV8ObjectResource *r = (QV8ObjectResource *)v8::Value::fromV4Value(value)->ToObject()->GetExternalResource();
if (!r)
return 0;
QV8ObjectResource::ResourceType type = r->resourceType();
if (type == QV8ObjectResource::QObjectType)
return qobjectWrapper()->toQObject(r);
- else if (type == QV8ObjectResource::VariantType) {
- QVariant variant = variantWrapper()->toVariant(r);
- int type = variant.userType();
- if (type == QMetaType::QObjectStar)
- return *reinterpret_cast<QObject* const *>(variant.constData());
- }
return 0;
}
#include "qv8qobjectwrapper_p.h"
#include "qv8typewrapper_p.h"
#include "qv8listwrapper_p.h"
-#include "qv8variantwrapper_p.h"
#include "qv8valuetypewrapper_p.h"
#include "qv8sequencewrapper_p.h"
#include "qv4jsonwrapper_p.h"
QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
QV8ListWrapper *listWrapper() { return &m_listWrapper; }
- QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; }
QV8QObjectWrapper m_qobjectWrapper;
QV8TypeWrapper m_typeWrapper;
QV8ListWrapper m_listWrapper;
- QV8VariantWrapper m_variantWrapper;
QV8ValueTypeWrapper m_valueTypeWrapper;
QV8SequenceWrapper m_sequenceWrapper;
QV4JsonWrapper m_jsonWrapper;
bool QV8Engine::isVariant(const QV4::Value &value)
{
- return m_variantWrapper.isVariant(value);
+ QV4::Managed *m = value.asManaged();
+ return m ? m->asVariantObject() : 0;
}
v8::Handle<v8::Object> QV8Engine::qmlScope(QQmlContextData *ctxt, QObject *scope)
{
public:
QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
- enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType,
+ enum ResourceType { ContextType, QObjectType, TypeType, ListType,
ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
ListModelType, Context2DStyleType, Context2DPixelArrayType,
ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType,
#include <private/qv4functionobject_p.h>
#include <private/qv4runtime_p.h>
+#include <private/qv4variantobject_p.h>
#include <QtQml/qjsvalue.h>
#include <QtCore/qjsonarray.h>
} else if (actual->IsObject()) {
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual);
+ if (QV4::VariantObject *v = obj->v4Value().asVariantObject()) {
+ if (conversionType == qMetaTypeId<QVariant>())
+ return 0;
+ QV8Engine *engine = v->engine()->publicEngine->handle();
+ if (engine->toVariant(actual->v4Value(), -1).userType() == conversionType)
+ return 0;
+ else
+ return 10;
+ }
+
QV8ObjectResource *r = static_cast<QV8ObjectResource *>(obj->GetExternalResource());
if (r && r->resourceType() == QV8ObjectResource::QObjectType) {
switch (conversionType) {
default:
return 10;
}
- } else if (r && r->resourceType() == QV8ObjectResource::VariantType) {
- if (conversionType == qMetaTypeId<QVariant>())
- return 0;
- else if (r->engine->toVariant(actual->v4Value(), -1).userType() == conversionType)
- return 0;
- else
- return 10;
} else if (r && r->resourceType() == QV8ObjectResource::ValueTypeType) {
if (r->engine->toVariant(actual->v4Value(), -1).userType() == conversionType)
return 0;
+++ /dev/null
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $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$
-**
-****************************************************************************/
-
-#include "qv8variantwrapper_p.h"
-#include "qv8variantresource_p.h"
-#include "qv8engine_p.h"
-#include <private/qqmlengine_p.h>
-
-#include <private/qv4functionobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data)
-: QV8ObjectResource(engine), QQmlEnginePrivate::ScarceResourceData(data), m_isScarceResource(false), m_vmePropertyReferenceCount(0)
-{
-}
-
-void QV8VariantResource::addVmePropertyReference()
-{
- if (m_isScarceResource && ++m_vmePropertyReferenceCount == 1) {
- // remove from the ep->scarceResources list
- // since it is now no longer eligible to be
- // released automatically by the engine.
- node.remove();
- }
-}
-
-void QV8VariantResource::removeVmePropertyReference()
-{
- if (m_isScarceResource && --m_vmePropertyReferenceCount == 0) {
- // and add to the ep->scarceResources list
- // since it is now eligible to be released
- // automatically by the engine.
- QQmlEnginePrivate::get(engine->engine())->scarceResources.insert(this);
- }
-}
-
-QV8VariantWrapper::QV8VariantWrapper()
-: m_engine(0)
-{
-}
-
-QV8VariantWrapper::~QV8VariantWrapper()
-{
-}
-
-void QV8VariantWrapper::init(QV8Engine *engine)
-{
- m_engine = engine;
- m_toString = v8::FunctionTemplate::New(ToString)->GetFunction()->v4Value();
- m_valueOf = v8::FunctionTemplate::New(ValueOf)->GetFunction()->v4Value();
-
- {
- v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
- ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
- ft->InstanceTemplate()->SetHasExternalResource(true);
- ft->InstanceTemplate()->MarkAsUseUserObjectComparison();
- ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
- m_toString.value(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
- m_valueOf.value(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
- m_constructor = ft->GetFunction()->v4Value();
- }
- {
- m_preserve = v8::FunctionTemplate::New(Preserve)->GetFunction()->v4Value();
- m_destroy = v8::FunctionTemplate::New(Destroy)->GetFunction()->v4Value();
- v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
- ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
- ft->InstanceTemplate()->SetHasExternalResource(true);
- ft->InstanceTemplate()->MarkAsUseUserObjectComparison();
- ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0,
- m_preserve.value(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0,
- m_destroy.value(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
- m_toString.value(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
- m_valueOf.value(), v8::DEFAULT,
- v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
- m_scarceConstructor = ft->GetFunction()->v4Value();
- }
-
-}
-
-void QV8VariantWrapper::destroy()
-{
-}
-
-QV4::Value QV8VariantWrapper::newVariant(const QVariant &value)
-{
- bool scarceResource = value.type() == QVariant::Pixmap ||
- value.type() == QVariant::Image;
-
- // XXX NewInstance() should be optimized
- v8::Handle<v8::Object> rv;
- QV8VariantResource *r = new QV8VariantResource(m_engine, value);
-
- if (scarceResource) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_engine->engine());
- Q_ASSERT(ep->scarceResourcesRefCount);
- rv = m_scarceConstructor.value().asFunctionObject()->newInstance();
- r->m_isScarceResource = true;
- ep->scarceResources.insert(r);
- } else {
- rv = m_constructor.value().asFunctionObject()->newInstance();
- }
-
- rv->SetExternalResource(r);
- return rv->v4Value();
-}
-
-bool QV8VariantWrapper::isVariant(const QV4::Value &v)
-{
- if (!v.isObject())
- return false;
- v8::Handle<v8::Object> vv(v);
- return v8_resource_cast<QV8VariantResource>(vv);
-}
-
-QVariant QV8VariantWrapper::toVariant(const QV4::Value &v)
-{
- QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(v);
- return r ? r->data : QVariant();
-}
-
-QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r)
-{
- Q_ASSERT(r->resourceType() == QV8ObjectResource::VariantType);
- return static_cast<QV8VariantResource *>(r)->data;
-}
-
-QVariant &QV8VariantWrapper::variantValue(v8::Handle<v8::Value> value)
-{
- Q_ASSERT(isVariant(value->v4Value()));
- QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(value->ToObject());
- return static_cast<QV8VariantResource *>(r)->data;
-}
-
-v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Handle<v8::String> /* property */,
- const v8::AccessorInfo & /* info */)
-{
- return v8::Handle<v8::Value>();
-}
-
-v8::Handle<v8::Value> QV8VariantWrapper::Setter(v8::Handle<v8::String> /* property */,
- v8::Handle<v8::Value> value,
- const v8::AccessorInfo & /* info */)
-{
- return value;
-}
-
-v8::Handle<v8::Value> QV8VariantWrapper::PreserveGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info)
-{
- Q_UNUSED(property);
- return info.Data();
-}
-
-v8::Handle<v8::Value> QV8VariantWrapper::DestroyGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info)
-{
- Q_UNUSED(property);
- return info.Data();
-}
-
-v8::Handle<v8::Value> QV8VariantWrapper::ToStringGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info)
-{
- Q_UNUSED(property);
- return info.Data();
-}
-
-v8::Handle<v8::Value> QV8VariantWrapper::ValueOfGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info)
-{
- Q_UNUSED(property);
- return info.Data();
-}
-
-QV4::Value QV8VariantWrapper::Preserve(const v8::Arguments &args)
-{
- QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
- if (resource) {
- resource->node.remove();
- }
- return QV4::Value::undefinedValue();
-}
-
-QV4::Value QV8VariantWrapper::Destroy(const v8::Arguments &args)
-{
- QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
- if (resource) {
- resource->data = QVariant();
- resource->node.remove();
- }
- return QV4::Value::undefinedValue();
-}
-
-QV4::Value QV8VariantWrapper::ToString(const v8::Arguments &args)
-{
- QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
- if (resource) {
- QString result = resource->data.toString();
- if (result.isEmpty() && !resource->data.canConvert(QVariant::String))
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(resource->data.typeName()));
- return resource->engine->toString(result);
- } else {
- return QV4::Value::undefinedValue();
- }
-}
-
-QV4::Value QV8VariantWrapper::ValueOf(const v8::Arguments &args)
-{
- QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
- if (resource) {
- QVariant v = resource->data;
- switch (v.type()) {
- case QVariant::Invalid:
- return QV4::Value::undefinedValue();
- case QVariant::String:
- return resource->engine->toString(v.toString());
- case QVariant::Int:
- case QVariant::Double:
- case QVariant::UInt:
- return QV4::Value::fromDouble(v.toDouble());
- case QVariant::Bool:
- return QV4::Value::fromBoolean(v.toBool());
- default:
- break;
- }
- }
- return args.This()->v4Value();
-}
-
-QT_END_NAMESPACE
+++ /dev/null
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $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 QV8VARIANTWRAPPER_P_H
-#define QV8VARIANTWRAPPER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtQml/qqmllist.h>
-#include <private/qv8_p.h>
-
-#include <private/qv4value_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QV8Engine;
-class QV8ObjectResource;
-class QV8VariantWrapper
-{
-public:
- QV8VariantWrapper();
- ~QV8VariantWrapper();
-
- void init(QV8Engine *);
- void destroy();
-
- QV4::Value newVariant(const QVariant &);
- static bool isVariant(const QV4::Value &v);
- static QVariant toVariant(const QV4::Value &v);
- static QVariant toVariant(QV8ObjectResource *);
- QVariant &variantValue(v8::Handle<v8::Value>);
-
-private:
- static v8::Handle<v8::Value> Getter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> Setter(v8::Handle<v8::String> property,
- v8::Handle<v8::Value> value,
- const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> PreserveGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> DestroyGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> ToStringGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info);
- static v8::Handle<v8::Value> ValueOfGetter(v8::Handle<v8::String> property,
- const v8::AccessorInfo &info);
- static QV4::Value Preserve(const v8::Arguments &args);
- static QV4::Value Destroy(const v8::Arguments &args);
- static QV4::Value ToString(const v8::Arguments &args);
- static QV4::Value ValueOf(const v8::Arguments &args);
-
- QV8Engine *m_engine;
- QV4::PersistentValue m_constructor;
- QV4::PersistentValue m_scarceConstructor;
- QV4::PersistentValue m_preserve;
- QV4::PersistentValue m_destroy;
- QV4::PersistentValue m_toString;
- QV4::PersistentValue m_valueOf;
-};
-
-QT_END_NAMESPACE
-
-#endif // QV8VARIANTWRAPPER_P_H
-
$$PWD/qv8qobjectwrapper_p.h \
$$PWD/qv8typewrapper_p.h \
$$PWD/qv8listwrapper_p.h \
- $$PWD/qv8variantwrapper_p.h \
- $$PWD/qv8variantresource_p.h \
$$PWD/qv8valuetypewrapper_p.h \
$$PWD/qv4jsonwrapper_p.h \
$$PWD/qv8include_p.h \
$$PWD/qv8qobjectwrapper.cpp \
$$PWD/qv8typewrapper.cpp \
$$PWD/qv8listwrapper.cpp \
- $$PWD/qv8variantwrapper.cpp \
$$PWD/qv8valuetypewrapper.cpp \
$$PWD/qv4jsonwrapper.cpp \
$$PWD/qv8include.cpp \
QVERIFY(!opaque.isCallable());
QCOMPARE(opaque.isObject(), true);
QVERIFY(!opaque.prototype().isUndefined());
- QEXPECT_FAIL("", "FIXME: newly created QObject's prototype is an JS Object", Continue);
QCOMPARE(opaque.prototype().isVariant(), true);
QVERIFY(opaque.property("valueOf").callWithInstance(opaque).equals(opaque));
}
origPixmap.fill(Qt::blue);
QString srp_name, expectedWarning;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&engine);
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
ScarceResourceObject *eo = 0;
QObject *srsc = 0;
QObject *object = 0;
QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
- QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
+ QVERIFY(v4->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that scarce resources are handled properly from js functions in qml files
QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
+ QVERIFY(v4->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that if an exception occurs while invoking js function from cpp, that the resources are released.
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
+ QVERIFY(v4->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that if an Item which has JS ownership but has a scarce resource property is garbage collected,
QVERIFY(object != 0);
QVERIFY(!object->property("varProperty").isValid()); // not assigned yet
QMetaObject::invokeMethod(object, "assignVarProperty");
- QVERIFY(ep->scarceResources.isEmpty()); // the scarce resource is a VME property.
+ QVERIFY(v4->scarceResources.isEmpty()); // the scarce resource is a VME property.
QMetaObject::invokeMethod(object, "deassignVarProperty");
- QVERIFY(ep->scarceResources.isEmpty()); // should still be empty; the resource should have been released on gc.
+ QVERIFY(v4->scarceResources.isEmpty()); // should still be empty; the resource should have been released on gc.
delete object;
/* property variant semantics */
QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
- QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
+ QVERIFY(v4->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that scarce resources are handled properly from js functions in qml files
QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
+ QVERIFY(v4->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that if an exception occurs while invoking js function from cpp, that the resources are released.
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
+ QVERIFY(v4->scarceResources.isEmpty()); // should have been released by this point.
delete object;
}
QFETCH(QStringList, expectedErrors);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&engine);
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
ScarceResourceObject *eo = 0;
QObject *object = 0;
QCOMPARE(eo->scarceResourceIsDetached(), expectedDetachStatus);
}
- QVERIFY(ep->scarceResources.isEmpty());
+ QVERIFY(v4->scarceResources.isEmpty());
delete object;
}