** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** 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.
+** 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, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
#include <private/qdeclarativeengine_p.h>
#include <private/qdeclarativevmemetaobject_p.h>
#include <private/qdeclarativebinding_p.h>
+#include <private/qjsvalue_p.h>
+#include <private/qscript_impl_p.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QJSValue);
Q_DECLARE_METATYPE(QDeclarativeV8Handle);
+QT_BEGIN_NAMESPACE
+
#if defined(__GNUC__)
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
// The code in this file does not violate strict aliasing, but GCC thinks it does
QV8QObjectWrapper *wrapper;
};
+class QV8SignalHandlerResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(SignalHandlerType)
+public:
+ QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index);
+
+ QDeclarativeGuard<QObject> object;
+ int index;
+};
+
namespace {
+
+template<typename A, typename B, typename C, typename D, typename E>
+class MaxSizeOf5 {
+ template<typename Z, typename X>
+ struct SMax {
+ static const size_t Size = sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X);
+ };
+public:
+ static const size_t Size = SMax<A, SMax<B, SMax<C, SMax<D, E> > > >::Size;
+};
+
struct MetaCallArgument {
inline MetaCallArgument();
inline ~MetaCallArgument();
inline void cleanup();
- char data[4 * sizeof(void *)];
+ union {
+ float floatValue;
+ double doubleValue;
+ quint32 intValue;
+ bool boolValue;
+ QObject *qobjectPtr;
+
+ char allocData[MaxSizeOf5<QVariant,
+ QString,
+ QList<QObject *>,
+ QJSValue,
+ QDeclarativeV8Handle>::Size];
+ qint64 q_for_alignment;
+ };
+
+ // Pointers to allocData
+ union {
+ QString *qstringPtr;
+ QVariant *qvariantPtr;
+ QList<QObject *> *qlistPtr;
+ QJSValue *qjsValuePtr;
+ QDeclarativeV8Handle *handlePtr;
+ };
+
int type;
- bool isObjectType;
};
}
{
}
+QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index)
+: QV8ObjectResource(engine), object(object), index(index)
+{
+}
+
static QAtomicInt objectIdCounter(1);
QV8QObjectWrapper::QV8QObjectWrapper()
qPersistentDispose(m_hiddenObject);
qPersistentDispose(m_destroySymbol);
qPersistentDispose(m_toStringSymbol);
+ qPersistentDispose(m_signalHandlerConstructor);
qPersistentDispose(m_methodConstructor);
qPersistentDispose(m_constructor);
}
static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info) \
{ \
v8::Handle<v8::Object> This = info.This(); \
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(This); \
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); \
\
- if (!resource || resource->object.isNull()) return v8::Undefined(); \
+ if (resource->object.isNull()) return v8::Undefined(); \
\
QObject *object = resource->object; \
\
uint32_t data = info.Data()->Uint32Value(); \
int index = data & 0x7FFF; \
- int notify = (data & 0x7FFF0000) >> 16; \
- if (notify == 0x7FFF) notify = -1; \
+ int notify = (data & 0x0FFF0000) >> 16; \
+ if (notify == 0x0FFF) notify = -1; \
\
QDeclarativeEnginePrivate *ep = resource->engine->engine()?QDeclarativeEnginePrivate::get(resource->engine->engine()):0; \
if (ep && notify /* 0 means constant */ && ep->captureProperties) { \
QMetaObject::metacall(object, QMetaObject::ReadProperty, index, args); \
\
return constructor(value); \
+} \
+static v8::Handle<v8::Value> name ## ValueGetterDirect(v8::Local<v8::String>, const v8::AccessorInfo &info) \
+{ \
+ v8::Handle<v8::Object> This = info.This(); \
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); \
+ \
+ if (resource->object.isNull()) return v8::Undefined(); \
+ \
+ QObject *object = resource->object; \
+ \
+ uint32_t data = info.Data()->Uint32Value(); \
+ int index = data & 0x7FFF; \
+ int notify = (data & 0x0FFF0000) >> 16; \
+ if (notify == 0x0FFF) notify = -1; \
+ \
+ QDeclarativeEnginePrivate *ep = resource->engine->engine()?QDeclarativeEnginePrivate::get(resource->engine->engine()):0; \
+ if (ep && notify /* 0 means constant */ && ep->captureProperties) { \
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty; \
+ ep->capturedProperties << CapturedProperty(object, index, notify); \
+ } \
+ \
+ cpptype value = defaultvalue; \
+ void *args[] = { &value, 0 }; \
+ object->qt_metacall(QMetaObject::ReadProperty, index, args); \
+ \
+ return constructor(value); \
}
#define CREATE_FUNCTION \
"});"\
"})"
+
+static quint32 toStringHash = -1;
+static quint32 destroyHash = -1;
+
void QV8QObjectWrapper::init(QV8Engine *engine)
{
m_engine = engine;
m_destroySymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("destroy"));
m_hiddenObject = qPersistentNew<v8::Object>(v8::Object::New());
+ m_toStringString = QHashedV8String(m_toStringSymbol);
+ m_destroyString = QHashedV8String(m_destroySymbol);
+
+ toStringHash = m_toStringString.hash();
+ destroyHash = m_destroyString.hash();
+
{
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator);
m_methodConstructor = qPersistentNew<v8::Function>(createFn);
}
+ v8::Local<v8::Function> connect = V8FUNCTION(Connect, engine);
+ v8::Local<v8::Function> disconnect = V8FUNCTION(Disconnect, engine);
+
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum);
+ ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
+ m_signalHandlerConstructor = qPersistentNew<v8::Function>(ft->GetFunction());
+ }
+
{
v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject();
- prototype->Set(v8::String::New("connect"), V8FUNCTION(Connect, engine));
- prototype->Set(v8::String::New("disconnect"), V8FUNCTION(Disconnect, engine));
+ prototype->Set(v8::String::New("connect"), connect, v8::DontEnum);
+ prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
}
}
}
// r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType)
-QObject *QV8QObjectWrapper::QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
+QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
{
Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType);
return static_cast<QV8QObjectResource *>(r)->object;
// Load value properties
static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
- const QDeclarativePropertyCache::Data &property)
+ const QDeclarativePropertyData &property)
{
Q_ASSERT(!property.isFunction());
} else if (property.isQList()) {
return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
} else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
- else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Number::New)
+ else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Integer::New)
else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
else PROPERTY_LOAD(QString, QString, engine->toString)
else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
QDeclarativeV8Handle handle;
void *args[] = { &handle, 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
- return reinterpret_cast<v8::Handle<v8::Value> &>(handle);
- } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+ return handle.toHandle();
+ } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)
+ && engine->engine()) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
if (valueType)
return engine->newValueType(object, property.coreIndex, valueType);
- }
+ } else {
+ // see if it's a sequence type
+ bool succeeded = false;
+ v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, &succeeded);
+ if (succeeded)
+ return retn;
+ }
QVariant var = object->metaObject()->property(property.coreIndex).read(object);
return engine->fromVariant(var);
+
+#undef PROPERTY_LOAD
+}
+
+static v8::Handle<v8::Value> LoadPropertyDirect(QV8Engine *engine, QObject *object,
+ const QDeclarativePropertyData &property)
+{
+ Q_ASSERT(!property.isFunction());
+
+#define PROPERTY_LOAD(metatype, cpptype, constructor) \
+ if (property.propType == QMetaType:: metatype) { \
+ cpptype type = cpptype(); \
+ void *args[] = { &type, 0 }; \
+ object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); \
+ return constructor(type); \
+ }
+
+ if (property.isQObject()) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+ return engine->newQObject(rv);
+ } else if (property.isQList()) {
+ return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
+ } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
+ else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Integer::New)
+ else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
+ else PROPERTY_LOAD(QString, QString, engine->toString)
+ else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
+ else PROPERTY_LOAD(Float, float, v8::Number::New)
+ else PROPERTY_LOAD(Double, double, v8::Number::New)
+ else if(property.isV8Handle()) {
+ QDeclarativeV8Handle handle;
+ void *args[] = { &handle, 0 };
+ object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args);
+ return handle.toHandle();
+ } else if (engine->engine() && QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
+ if (valueType)
+ return engine->newValueType(object, property.coreIndex, valueType);
+ } else {
+ // see if it's a sequence type
+ bool success = false;
+ v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, &success);
+ if (success)
+ return retn;
+ }
+
+ QVariant var = object->metaObject()->property(property.coreIndex).read(object);
+ return engine->fromVariant(var);
+
+#undef PROPERTY_LOAD
}
v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object,
v8::Handle<v8::Value> *objectHandle,
- v8::Handle<v8::String> property,
+ const QHashedV8String &property,
QV8QObjectWrapper::RevisionMode revisionMode)
{
// XXX More recent versions of V8 introduced "Callable" objects. It is possible that these
}
};
- if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property)) {
- return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
- } else if (engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property)) {
- return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
+ {
+ // Comparing the hash first actually makes a measurable difference here, at least on x86
+ quint32 hash = property.hash();
+ if (hash == toStringHash && engine->qobjectWrapper()->m_toStringString == property) {
+ return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
+ } else if (hash == destroyHash && engine->qobjectWrapper()->m_destroyString == property) {
+ return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
+ }
}
- QDeclarativePropertyCache::Data local;
- QDeclarativePropertyCache::Data *result = 0;
- result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+ QDeclarativePropertyData local;
+ QDeclarativePropertyData *result = 0;
+ {
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ if (ddata && ddata->propertyCache)
+ result = ddata->propertyCache->property(property);
+ else
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+ }
if (!result)
return v8::Handle<v8::Value>();
- QDeclarativeEnginePrivate *ep = engine->engine()?QDeclarativeEnginePrivate::get(engine->engine()):0;
-
if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
QDeclarativeData *ddata = QDeclarativeData::get(object);
if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
if (result->isFunction()) {
- if (result->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
+ if (result->isVMEFunction()) {
return ((QDeclarativeVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
- } else if (result->flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ } else if (result->isV8Function()) {
return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
+ } else if (result->isSignalHandler()) {
+ v8::Local<v8::Object> handler = engine->qobjectWrapper()->m_signalHandlerConstructor->NewInstance();
+ QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex);
+ handler->SetExternalResource(r);
+ return handler;
} else {
return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
}
}
+ QDeclarativeEnginePrivate *ep = engine->engine()?QDeclarativeEnginePrivate::get(engine->engine()):0;
if (ep && ep->captureProperties && !result->isConstant()) {
if (result->coreIndex == 0)
ep->capturedProperties << CapturedProperty(QDeclarativeData::get(object, true)->objectNameNotifier());
ep->capturedProperties << CapturedProperty(object, result->coreIndex, result->notifyIndex);
}
- return LoadProperty(engine, object, *result);
+ if (result->isVMEProperty())
+ return static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject*>(object->metaObject()))->vmeProperty(result->coreIndex);
+
+ if (result->isDirect()) {
+ return LoadPropertyDirect(engine, object, *result);
+ } else {
+ return LoadProperty(engine, object, *result);
+ }
}
// Setter for writable properties. Shared between the interceptor and fast property accessor
-static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativePropertyCache::Data *property,
+static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativePropertyData *property,
v8::Handle<v8::Value> value)
{
QDeclarativeBinding *newBinding = 0;
int lineNumber = frame->GetLineNumber();
QString url = engine->toString(frame->GetScriptName());
- QDeclarativePropertyCache::ValueTypeData valueTypeData;
newBinding = new QDeclarativeBinding(&function, object, context);
newBinding->setSourceLocation(url, lineNumber);
- newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, valueTypeData, object, context));
+ newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, object, context));
newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
}
PROPERTY_STORE(double, double(value->ToNumber()->Value()));
} else if (property->propType == QMetaType::QString && value->IsString()) {
PROPERTY_STORE(QString, engine->toString(value->ToString()));
+ } else if (property->isVMEProperty()) {
+ static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(object->metaObject()))->setVMEProperty(property->coreIndex, value);
} else {
QVariant v;
if (property->isQList())
v = engine->toVariant(value, property->propType);
QDeclarativeContextData *context = engine->callingContext();
-
if (!QDeclarativePropertyPrivate::write(object, *property, v, context)) {
const char *valueType = 0;
if (v.userType() == QVariant::Invalid) valueType = "null";
}
}
-bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, v8::Handle<v8::String> property,
+bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QHashedV8String &property,
v8::Handle<v8::Value> value, QV8QObjectWrapper::RevisionMode revisionMode)
{
- if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property) ||
- engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property))
+ if (engine->qobjectWrapper()->m_toStringString == property ||
+ engine->qobjectWrapper()->m_destroyString == property)
return true;
- QDeclarativePropertyCache::Data local;
- QDeclarativePropertyCache::Data *result = 0;
+ QDeclarativePropertyData local;
+ QDeclarativePropertyData *result = 0;
result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
if (!result)
if (!result->isWritable() && !result->isQList()) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
- engine->toString(property) + QLatin1Char('\"');
+ engine->toString(property.string()) + QLatin1Char('\"');
v8::ThrowException(v8::Exception::Error(engine->toString(error)));
return true;
}
v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
const v8::AccessorInfo &info)
{
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
- v8::Handle<v8::Value> This = info.This();
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (!resource || resource->object.isNull()) return v8::Undefined();
+ if (resource->object.isNull())
+ return v8::Handle<v8::Value>();
QObject *object = resource->object;
+ QHashedV8String propertystring(property);
+
QV8Engine *v8engine = resource->engine;
- v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, property, QV8QObjectWrapper::IgnoreRevision);
+ v8::Handle<v8::Value> This = info.This();
+ v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, propertystring,
+ QV8QObjectWrapper::IgnoreRevision);
if (!result.IsEmpty())
return result;
if (QV8Engine::startsWithUpper(property)) {
// Check for attached properties
QDeclarativeContextData *context = v8engine->callingContext();
- QDeclarativeTypeNameCache::Data *data = context && (context->imports)?context->imports->data(property):0;
- if (data) {
- if (data->type) {
- return v8engine->typeWrapper()->newObject(object, data->type, QV8TypeWrapper::ExcludeEnums);
- } else if (data->typeNamespace) {
- return v8engine->typeWrapper()->newObject(object, data->typeNamespace, QV8TypeWrapper::ExcludeEnums);
+ if (context && context->imports) {
+ QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring);
+
+ if (r.isValid()) {
+ if (r.scriptIndex != -1) {
+ return v8::Undefined();
+ } else if (r.type) {
+ return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums);
+ } else if (r.importNamespace) {
+ return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace,
+ QV8TypeWrapper::ExcludeEnums);
+ }
+ Q_ASSERT(!"Unreachable");
}
}
}
- return v8::Undefined();
+ return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
v8::Local<v8::Value> value,
const v8::AccessorInfo &info)
{
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (!resource || resource->object.isNull())
+ if (resource->object.isNull())
return value;
QObject *object = resource->object;
+ QHashedV8String propertystring(property);
+
QV8Engine *v8engine = resource->engine;
- bool result = SetProperty(v8engine, object, property, value, QV8QObjectWrapper::IgnoreRevision);
+ bool result = SetProperty(v8engine, object, propertystring, value, QV8QObjectWrapper::IgnoreRevision);
if (!result) {
QString error = QLatin1String("Cannot assign to non-existent property \"") +
v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property,
const v8::AccessorInfo &info)
{
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (!resource || resource->object.isNull())
+ if (resource->object.isNull())
return v8::Handle<v8::Integer>();
QV8Engine *engine = resource->engine;
QObject *object = resource->object;
- QDeclarativePropertyCache::Data local;
- QDeclarativePropertyCache::Data *result = 0;
- result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+ QHashedV8String propertystring(property);
+
+ QDeclarativePropertyData local;
+ QDeclarativePropertyData *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, propertystring, local);
if (!result)
return v8::Handle<v8::Integer>();
v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info)
{
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (!resource || resource->object.isNull())
+ if (resource->object.isNull())
return v8::Array::New();
QObject *object = resource->object;
QStringList result;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine());
+ QDeclarativeEnginePrivate *ep = resource->engine->engine()
+ ? QDeclarativeEnginePrivate::get(resource->engine->engine())
+ : 0;
QDeclarativePropertyCache *cache = 0;
QDeclarativeData *ddata = QDeclarativeData::get(object);
cache = ddata->propertyCache;
if (!cache) {
- cache = ep->cache(object);
+ cache = ep ? ep->cache(object) : 0;
if (cache) {
if (ddata) { cache->addref(); ddata->propertyCache = cache; }
} else {
static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
const v8::AccessorInfo& info)
{
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (!resource || resource->object.isNull())
+ if (resource->object.isNull())
return;
QObject *object = resource->object;
Q_ASSERT(ddata);
Q_ASSERT(ddata->propertyCache);
- QDeclarativePropertyCache::Data *pdata = ddata->propertyCache->property(index);
+ QDeclarativePropertyData *pdata = ddata->propertyCache->property(index);
Q_ASSERT(pdata);
Q_ASSERT(pdata->isWritable() || pdata->isQList());
static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8::Value>,
const v8::AccessorInfo& info)
{
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (!resource || resource->object.isNull())
+ if (resource->object.isNull())
return;
QV8Engine *v8engine = resource->engine;
- QString error = QLatin1String("Cannot assign to non-existent property \"") +
+ QString error = QLatin1String("Cannot assign to read-only property \"") +
v8engine->toString(property) + QLatin1Char('\"');
v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
}
{
Q_ASSERT(handle->IsObject());
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(handle->ToObject());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(handle->ToObject());
Q_ASSERT(resource);
v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8Engine *engine)
{
Q_ASSERT(object);
+ Q_ASSERT(this->engine);
Q_ASSERT(QDeclarativeData::get(object, false));
Q_ASSERT(QDeclarativeData::get(object, false)->propertyCache == this);
// performance, but the cost of setting up this structure hasn't been measured so
// its not guarenteed that this is a win overall. We need to try and measure the cost.
for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) {
- Data *property = *iter;
+ QDeclarativePropertyData *property = *iter;
if (property->isFunction() ||
- property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x7FFF ||
+ property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x0FFF ||
property->coreIndex == 0)
continue;
fastsetter = FastValueSetterReadOnly;
if (property->isQObject())
- fastgetter = QObjectValueGetter;
+ fastgetter = property->isDirect()?QObjectValueGetterDirect:QObjectValueGetter;
else if (property->propType == QMetaType::Int || property->isEnum())
- fastgetter = IntValueGetter;
+ fastgetter = property->isDirect()?IntValueGetterDirect:IntValueGetter;
else if (property->propType == QMetaType::Bool)
- fastgetter = BoolValueGetter;
+ fastgetter = property->isDirect()?BoolValueGetterDirect:BoolValueGetter;
else if (property->propType == QMetaType::QString)
- fastgetter = QStringValueGetter;
+ fastgetter = property->isDirect()?QStringValueGetterDirect:QStringValueGetter;
else if (property->propType == QMetaType::UInt)
- fastgetter = UIntValueGetter;
+ fastgetter = property->isDirect()?UIntValueGetterDirect:UIntValueGetter;
else if (property->propType == QMetaType::Float)
- fastgetter = FloatValueGetter;
+ fastgetter = property->isDirect()?FloatValueGetterDirect:FloatValueGetter;
else if (property->propType == QMetaType::Double)
- fastgetter = DoubleValueGetter;
+ fastgetter = property->isDirect()?DoubleValueGetterDirect:DoubleValueGetter;
if (fastgetter) {
int notifyIndex = property->notifyIndex;
if (property->isConstant()) notifyIndex = 0;
- else if (notifyIndex == -1) notifyIndex = 0x7FFF;
- uint32_t data = (property->notifyIndex & 0x7FFF) << 16 | property->coreIndex;
+ else if (notifyIndex == -1) notifyIndex = 0x0FFF;
+ uint32_t data = (notifyIndex & 0x0FFF) << 16 | property->coreIndex;
QString name = iter.key();
if (name == toString || name == destroy)
ft->InstanceTemplate()->SetHasExternalResource(true);
constructor = qPersistentNew<v8::Function>(ft->GetFunction());
}
+
+ QDeclarativeCleanup::addToEngine(this->engine);
}
v8::Local<v8::Object> result = constructor->NewInstance();
if (ddata->propertyCache) ddata->propertyCache->addref();
}
- if (ddata->propertyCache) {
+ if (ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine->engine()) {
rv = ddata->propertyCache->newQObject(object, engine);
} else {
// XXX NewInstance() should be optimized
}
}
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object)
+{
+ if (object->IsFunction())
+ return ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(object));
+
+ if (QV8SignalHandlerResource *resource = v8_resource_cast<QV8SignalHandlerResource>(object))
+ return qMakePair(resource->object.data(), resource->index);
+
+ return qMakePair((QObject *)0, -1);
+}
+
QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
{
v8::ScriptOrigin origin = function->GetScriptOrigin();
return qMakePair((QObject *)0, -1);
}
-struct QV8QObjectConnectionList : public QObject, public QDeclarativeGuard<QObject>
+class QV8QObjectConnectionList : public QObject, public QDeclarativeGuard<QObject>
{
+public:
QV8QObjectConnectionList(QObject *object, QV8Engine *engine);
~QV8QObjectConnectionList();
QList<Connection> connections = connectionList;
- QMetaMethod method = data()->metaObject()->method(index);
- Q_ASSERT(method.methodType() == QMetaMethod::Signal);
- // XXX TODO: We should figure out a way to cache the parameter types to avoid resolving
- // them each time.
- QList<QByteArray> params = method.parameterTypes();
+ QVarLengthArray<int, 9> dummy;
+ int *argsTypes = QDeclarativePropertyCache::methodParameterTypes(data(), index, dummy, 0);
v8::HandleScope handle_scope;
v8::Context::Scope scope(engine->context());
- QVarLengthArray<v8::Handle<v8::Value> > args(params.count());
- int argCount = params.count();
+ int argCount = argsTypes?argsTypes[0]:0;
+ QVarLengthArray<v8::Handle<v8::Value>, 9> args(argCount);
for (int ii = 0; ii < argCount; ++ii) {
- int type = QMetaType::type(params.at(ii).constData());
+ int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
} else {
QV8Engine *engine = V8ENGINE();
- if (!args.This()->IsFunction())
- V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
-
- QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
QV8Engine *engine = V8ENGINE();
- if (!args.This()->IsFunction())
- V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
-
- QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
}
/*!
+ \fn v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &property, QV8QObjectWrapper::RevisionMode revisionMode)
+
Get the \a property of \a object. Returns an empty handle if the property doesn't exist.
Only searches for real properties of \a object (including methods), not attached properties etc.
*/
-v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, v8::Handle<v8::String> property,
- QV8QObjectWrapper::RevisionMode revisionMode)
-{
- return GetProperty(m_engine, object, 0, property, revisionMode);
-}
/*
+ \fn bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &property, v8::Handle<v8::Value> value, RevisionMode revisionMode)
+
Set the \a property of \a object to \a value.
Returns true if the property was "set" - even if this results in an exception being thrown -
Only searches for real properties of \a object (including methods), not attached properties etc.
*/
-bool QV8QObjectWrapper::setProperty(QObject *object, v8::Handle<v8::String> property,
- v8::Handle<v8::Value> value, RevisionMode revisionMode)
-{
- return SetProperty(m_engine, object, property, value, revisionMode);
-}
namespace {
struct CallArgs
}
}
-static int EnumType(const QMetaObject *meta, const QString &strname)
-{
- QByteArray str = strname.toUtf8();
- QByteArray scope;
- QByteArray name;
- int scopeIdx = str.lastIndexOf("::");
- if (scopeIdx != -1) {
- scope = str.left(scopeIdx);
- name = str.mid(scopeIdx + 2);
- } else {
- name = str;
- }
- for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
- QMetaEnum m = meta->enumerator(i);
- if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
- return QVariant::Int;
- }
- return QVariant::Invalid;
-}
-
/*!
Returns the match score for converting \a actual to be of type \a conversionType. A
zero score means "perfect match" whereas a higher score is worse.
The conversion table is copied out of the QtScript callQtMethod() function.
*/
-static int MatchScore(v8::Handle<v8::Value> actual, int conversionType,
- const QByteArray &conversionTypeName)
+static int MatchScore(v8::Handle<v8::Value> actual, int conversionType)
{
if (actual->IsNumber()) {
switch (conversionType) {
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
return 0;
- default:
- if (!conversionTypeName.endsWith('*'))
- return 10;
- else
+ default: {
+ const char *typeName = QMetaType::typeName(conversionType);
+ if (typeName && typeName[strlen(typeName) - 1] == '*')
return 0;
+ else
+ return 10;
+ }
}
} else if (actual->IsObject()) {
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual);
/*!
Returns the next related method, if one, or 0.
*/
-static const QDeclarativePropertyCache::Data * RelatedMethod(QObject *object,
- const QDeclarativePropertyCache::Data *current,
- QDeclarativePropertyCache::Data &dummy)
+static const QDeclarativePropertyData * RelatedMethod(QObject *object,
+ const QDeclarativePropertyData *current,
+ QDeclarativePropertyData &dummy)
{
QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
- if (current->relatedIndex == -1)
+ if (!current->isOverload())
return 0;
+ Q_ASSERT(!current->overrideIndexIsProperty);
+
if (cache) {
- return cache->method(current->relatedIndex);
+ return cache->method(current->overrideIndex);
} else {
const QMetaObject *mo = object->metaObject();
int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
- while (methodOffset > current->relatedIndex) {
+ while (methodOffset > current->overrideIndex) {
mo = mo->superClass();
methodOffset -= QMetaObject_methods(mo);
}
- QMetaMethod method = mo->method(current->relatedIndex);
+ QMetaMethod method = mo->method(current->overrideIndex);
dummy.load(method);
// Look for overloaded methods
QByteArray methodName = QMetaMethod_name(method);
- for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
+ for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
if (methodName == QMetaMethod_name(mo->method(ii))) {
- dummy.relatedIndex = ii;
+ dummy.setFlags(dummy.getFlags() | QDeclarativePropertyData::IsOverload);
+ dummy.overrideIndexIsProperty = 0;
+ dummy.overrideIndex = ii;
return &dummy;
}
}
}
}
-static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
+static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyData &data,
QV8Engine *engine, CallArgs &callArgs)
{
- if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
-
- QMetaMethod m = object->metaObject()->method(data.coreIndex);
- QList<QByteArray> argTypeNames = m.parameterTypes();
- QVarLengthArray<int, 9> argTypes(argTypeNames.count());
-
- // ### Cache
- for (int ii = 0; ii < argTypeNames.count(); ++ii) {
- argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
- if (argTypes[ii] == QVariant::Invalid)
- argTypes[ii] = EnumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
- if (argTypes[ii] == QVariant::Invalid) {
- QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)));
- v8::ThrowException(v8::Exception::Error(engine->toString(error)));
- return v8::Handle<v8::Value>();
- }
+ if (data.hasArguments()) {
+
+ int *args = 0;
+ QVarLengthArray<int, 9> dummy;
+ QByteArray unknownTypeError;
+
+ args = QDeclarativePropertyCache::methodParameterTypes(object, data.coreIndex, dummy,
+ &unknownTypeError);
+
+ if (!args) {
+ QString typeName = QString::fromLatin1(unknownTypeError);
+ QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
}
- if (argTypes.count() > callArgs.Length()) {
+ if (args[0] > callArgs.Length()) {
QString error = QLatin1String("Insufficient arguments");
v8::ThrowException(v8::Exception::Error(engine->toString(error)));
return v8::Handle<v8::Value>();
}
- return CallMethod(object, data.coreIndex, data.propType, argTypes.count(),
- argTypes.data(), engine, callArgs);
+ return CallMethod(object, data.coreIndex, data.propType, args[0], args + 1, engine, callArgs);
} else {
If two or more overloads have the same match score, call the last one. The match
score is constructed by adding the matchScore() result for each of the parameters.
*/
-static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativePropertyCache::Data &data,
+static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativePropertyData &data,
QV8Engine *engine, CallArgs &callArgs)
{
int argumentCount = callArgs.Length();
- const QDeclarativePropertyCache::Data *best = 0;
+ const QDeclarativePropertyData *best = 0;
int bestParameterScore = INT_MAX;
int bestMatchScore = INT_MAX;
- QDeclarativePropertyCache::Data dummy;
- const QDeclarativePropertyCache::Data *attempt = &data;
+ QDeclarativePropertyData dummy;
+ const QDeclarativePropertyData *attempt = &data;
do {
- QList<QByteArray> methodArgTypeNames;
-
- if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
- methodArgTypeNames = object->metaObject()->method(attempt->coreIndex).parameterTypes();
+ QVarLengthArray<int, 9> dummy;
+ int methodArgumentCount = 0;
+ int *methodArgTypes = 0;
+ if (attempt->hasArguments()) {
+ typedef QDeclarativePropertyCache PC;
+ int *args = PC::methodParameterTypes(object, attempt->coreIndex, dummy, 0);
+ if (!args) // Must be an unknown argument
+ continue;
- int methodArgumentCount = methodArgTypeNames.count();
+ methodArgumentCount = args[0];
+ methodArgTypes = args + 1;
+ }
if (methodArgumentCount > argumentCount)
continue; // We don't have sufficient arguments to call this method
continue; // We already have a better option
int methodMatchScore = 0;
- QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
-
- bool unknownArgument = false;
- for (int ii = 0; ii < methodArgumentCount; ++ii) {
- methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
- if (methodArgTypes[ii] == QVariant::Invalid)
- methodArgTypes[ii] = EnumType(object->metaObject(),
- QString::fromLatin1(methodArgTypeNames.at(ii)));
- if (methodArgTypes[ii] == QVariant::Invalid) {
- unknownArgument = true;
- break;
- }
- methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii], methodArgTypeNames.at(ii));
- }
- if (unknownArgument)
- continue; // We don't understand all the parameters
+ for (int ii = 0; ii < methodArgumentCount; ++ii)
+ methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii]);
if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
best = attempt;
return CallPrecise(object, *best, engine, callArgs);
} else {
QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
- const QDeclarativePropertyCache::Data *candidate = &data;
+ const QDeclarativePropertyData *candidate = &data;
while (candidate) {
error += QLatin1String("\n ") +
QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature());
}
}
- QDeclarativePropertyCache::Data method;
+ QDeclarativePropertyData method;
if (QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(object)->declarativeData)) {
if (ddata->propertyCache) {
- QDeclarativePropertyCache::Data *d = ddata->propertyCache->method(index);
+ QDeclarativePropertyData *d = ddata->propertyCache->method(index);
if (!d)
return v8::Undefined();
method = *d;
}
if (method.coreIndex == -1) {
- QMetaMethod mm = object->metaObject()->method(index);
method.load(object->metaObject()->method(index));
if (method.coreIndex == -1)
return v8::Undefined();
}
- if (method.flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ if (method.isV8Function()) {
v8::Handle<v8::Value> rv;
v8::Handle<v8::Object> qmlglobal = args[2]->ToObject();
}
CallArgs callArgs(argCount, &arguments);
- if (method.relatedIndex == -1) {
+ if (!method.isOverload()) {
return CallPrecise(object, method, resource->engine, callArgs);
} else {
return CallOverloaded(object, method, resource->engine, callArgs);
}
MetaCallArgument::MetaCallArgument()
-: type(QVariant::Invalid), isObjectType(false)
+: type(QVariant::Invalid)
{
}
void MetaCallArgument::cleanup()
{
if (type == QMetaType::QString) {
- ((QString *)&data)->~QString();
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- ((QVariant *)&data)->~QVariant();
- } else if (type == qMetaTypeId<QScriptValue>()) {
- ((QScriptValue *)&data)->~QScriptValue();
+ qstringPtr->~QString();
+ } else if (type == -1 || type == QMetaType::QVariant) {
+ qvariantPtr->~QVariant();
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ qjsValuePtr->~QJSValue();
} else if (type == qMetaTypeId<QList<QObject *> >()) {
- ((QList<QObject *> *)&data)->~QList<QObject *>();
- }
+ qlistPtr->~QList<QObject *>();
+ }
}
void *MetaCallArgument::dataPtr()
{
if (type == -1)
- return ((QVariant *)data)->data();
+ return qvariantPtr->data();
else
- return (void *)&data;
+ return (void *)&allocData;
}
void MetaCallArgument::initAsType(int callType)
if (type != 0) { cleanup(); type = 0; }
if (callType == 0) return;
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue();
+ if (callType == qMetaTypeId<QJSValue>()) {
+ qjsValuePtr = new (&allocData) QJSValue();
type = callType;
} else if (callType == QMetaType::Int ||
callType == QMetaType::UInt ||
callType == QMetaType::Float) {
type = callType;
} else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = 0;
+ qobjectPtr = 0;
type = callType;
} else if (callType == QMetaType::QString) {
- new (&data) QString();
+ qstringPtr = new (&allocData) QString();
type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
+ } else if (callType == QMetaType::QVariant) {
type = callType;
- new (&data) QVariant();
+ qvariantPtr = new (&allocData) QVariant();
} else if (callType == qMetaTypeId<QList<QObject *> >()) {
type = callType;
- new (&data) QList<QObject *>();
+ qlistPtr = new (&allocData) QList<QObject *>();
} else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
type = callType;
- new (&data) v8::Handle<v8::Value>();
+ handlePtr = new (&allocData) QDeclarativeV8Handle;
} else {
type = -1;
- new (&data) QVariant(callType, (void *)0);
+ qvariantPtr = new (&allocData) QVariant(callType, (void *)0);
}
}
{
if (type != 0) { cleanup(); type = 0; }
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue();
- type = qMetaTypeId<QScriptValue>();
+ if (callType == qMetaTypeId<QJSValue>()) {
+ qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value)));
+ type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
- *((int *)&data) = int(value->Int32Value());
+ intValue = quint32(value->Int32Value());
type = callType;
} else if (callType == QMetaType::UInt) {
- *((uint *)&data) = uint(value->Uint32Value());
+ intValue = quint32(value->Uint32Value());
type = callType;
} else if (callType == QMetaType::Bool) {
- *((bool *)&data) = value->BooleanValue();
+ boolValue = value->BooleanValue();
type = callType;
} else if (callType == QMetaType::Double) {
- *((double *)&data) = double(value->NumberValue());
+ doubleValue = double(value->NumberValue());
type = callType;
} else if (callType == QMetaType::Float) {
- *((float *)&data) = float(value->NumberValue());
+ floatValue = float(value->NumberValue());
type = callType;
} else if (callType == QMetaType::QString) {
if (value->IsNull() || value->IsUndefined())
- new (&data) QString();
+ qstringPtr = new (&allocData) QString();
else
- new (&data) QString(engine->toString(value->ToString()));
+ qstringPtr = new (&allocData) QString(engine->toString(value->ToString()));
type = callType;
} else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = engine->toQObject(value);
+ qobjectPtr = engine->toQObject(value);
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
- new (&data) QVariant(engine->toVariant(value, -1));
+ qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1));
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
- QList<QObject *> *list = new (&data) QList<QObject *>();
+ qlistPtr = new (&allocData) QList<QObject *>();
if (value->IsArray()) {
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
uint32_t length = array->Length();
for (uint32_t ii = 0; ii < length; ++ii)
- list->append(engine->toQObject(array->Get(ii)));
+ qlistPtr->append(engine->toQObject(array->Get(ii)));
} else {
- list->append(engine->toQObject(value));
+ qlistPtr->append(engine->toQObject(value));
}
type = callType;
} else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
- new (&data) v8::Handle<v8::Value>(value);
+ handlePtr = new (&allocData) QDeclarativeV8Handle(QDeclarativeV8Handle::fromHandle(value));
type = callType;
} else {
- new (&data) QVariant();
+ qvariantPtr = new (&allocData) QVariant();
type = -1;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QDeclarativeEnginePrivate *ep = engine->engine() ? QDeclarativeEnginePrivate::get(engine->engine()) : 0;
QVariant v = engine->toVariant(value, -1);
if (v.userType() == callType) {
- *((QVariant *)&data) = v;
+ *qvariantPtr = v;
} else if (v.canConvert((QVariant::Type)callType)) {
- *((QVariant *)&data) = v;
- ((QVariant *)&data)->convert((QVariant::Type)callType);
- } else if (const QMetaObject *mo = ep->rawMetaObjectForType(callType)) {
+ *qvariantPtr = v;
+ qvariantPtr->convert((QVariant::Type)callType);
+ } else if (const QMetaObject *mo = ep ? ep->rawMetaObjectForType(callType) : 0) {
QObject *obj = ep->toQObject(v);
if (obj) {
if (!objMo) obj = 0;
}
- *((QVariant *)&data) = QVariant(callType, &obj);
+ *qvariantPtr = QVariant(callType, &obj);
} else {
- *((QVariant *)&data) = QVariant(callType, (void *)0);
+ *qvariantPtr = QVariant(callType, (void *)0);
}
}
}
v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
{
- if (type == qMetaTypeId<QScriptValue>()) {
- return v8::Undefined();
+ if (type == qMetaTypeId<QJSValue>()) {
+ return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine);
} else if (type == QMetaType::Int) {
- return v8::Integer::New(*((int *)&data));
+ return v8::Integer::New(int(intValue));
} else if (type == QMetaType::UInt) {
- return v8::Integer::NewFromUnsigned(*((uint *)&data));
+ return v8::Integer::NewFromUnsigned(intValue);
} else if (type == QMetaType::Bool) {
- return v8::Boolean::New(*((bool *)&data));
+ return v8::Boolean::New(boolValue);
} else if (type == QMetaType::Double) {
- return v8::Number::New(*((double *)&data));
+ return v8::Number::New(doubleValue);
} else if (type == QMetaType::Float) {
- return v8::Number::New(*((float *)&data));
+ return v8::Number::New(floatValue);
} else if (type == QMetaType::QString) {
- return engine->toString(*((QString *)&data));
+ return engine->toString(*qstringPtr);
} else if (type == QMetaType::QObjectStar) {
- QObject *object = *((QObject **)&data);
+ QObject *object = qobjectPtr;
if (object)
QDeclarativeData::get(object, true)->setImplicitDestructible();
return engine->newQObject(object);
} else if (type == qMetaTypeId<QList<QObject *> >()) {
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
- QList<QObject *> &list = *(QList<QObject *>*)&data;
+ QList<QObject *> &list = *qlistPtr;
v8::Local<v8::Array> array = v8::Array::New(list.count());
for (int ii = 0; ii < list.count(); ++ii)
array->Set(ii, engine->newQObject(list.at(ii)));
return array;
} else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
- return *(v8::Handle<v8::Value>*)&data;
+ return handlePtr->toHandle();
} else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- QVariant value = *((QVariant *)&data);
+ QVariant value = *qvariantPtr;
v8::Handle<v8::Value> rv = engine->fromVariant(value);
if (QObject *object = engine->toQObject(rv))
QDeclarativeData::get(object, true)->setImplicitDestructible();
return v8::Undefined();
}
}
+
+QT_END_NAMESPACE
+