NoFlags = 0x00000000,
// Can apply to all properties, except IsFunction
- IsConstant = 0x00000001,
- IsWritable = 0x00000002,
- IsResettable = 0x00000004,
- IsAlias = 0x00000008,
- IsFinal = 0x00000010,
+ IsConstant = 0x00000001, // Has CONST flag
+ IsWritable = 0x00000002, // Has WRITE function
+ IsResettable = 0x00000004, // Has RESET function
+ IsAlias = 0x00000008, // Is a QML alias to another property
+ IsFinal = 0x00000010, // Has FINAL flag
+ IsDirect = 0x00000020, // Exists on a C++ QMetaObject
// These are mutualy exclusive
- IsFunction = 0x00000020,
- IsQObjectDerived = 0x00000040,
- IsEnumType = 0x00000080,
- IsQList = 0x00000100,
- IsQmlBinding = 0x00000200,
- IsQScriptValue = 0x00000400,
- IsV8Handle = 0x00000800,
+ IsFunction = 0x00000040, // Is an invokable
+ IsQObjectDerived = 0x00000080, // Property type is a QObject* derived type
+ IsEnumType = 0x00000100, // Property type is an enum
+ IsQList = 0x00000200, // Property type is a QML list
+ IsQmlBinding = 0x00000400, // Property type is a QDeclarativeBinding*
+ IsQScriptValue = 0x00000800, // Property type is a QScriptValue
+ IsV8Handle = 0x00001000, // Property type is a QDeclarativeV8Handle
// Apply only to IsFunctions
- IsVMEFunction = 0x00001000,
- HasArguments = 0x00002000,
- IsSignal = 0x00004000,
- IsVMESignal = 0x00008000,
- IsV8Function = 0x00010000
+ IsVMEFunction = 0x00002000, // Function was added by QML
+ HasArguments = 0x00004000, // Function takes arguments
+ IsSignal = 0x00008000, // Function is a signal
+ IsVMESignal = 0x00010000, // Signal was added by QML
+ IsV8Function = 0x00020000 // Function takes QDeclarativeV8Function* args
};
Q_DECLARE_FLAGS(Flags, Flag)
bool isResettable() const { return flags & IsResettable; }
bool isAlias() const { return flags & IsAlias; }
bool isFinal() const { return flags & IsFinal; }
+ bool isDirect() const { return flags & IsDirect; }
bool isFunction() const { return flags & IsFunction; }
bool isQObject() const { return flags & IsQObjectDerived; }
bool isEnum() const { return flags & IsEnumType; }
static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &);
static Data *property(QDeclarativeEngine *, QObject *, const QHashedV8String &, Data &);
+ static bool isDynamicMetaObject(const QMetaObject *);
protected:
virtual void clear();
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; \
\
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 & 0x7FFF0000) >> 16; \
+ if (notify == 0x7FFF) 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_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);
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 QDeclarativePropertyCache::Data &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 reinterpret_cast<v8::Handle<v8::Value> &>(handle);
+ } else if (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);
+ }
+
+ 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,
}
};
- if (engine->qobjectWrapper()->m_toStringString == property) {
- return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
- } else if (engine->qobjectWrapper()->m_destroyString == 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;
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))
}
}
+ 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->isDirect()) {
+ return LoadPropertyDirect(engine, object, *result);
+ } else {
+ return LoadProperty(engine, object, *result);
+ }
}
// Setter for writable properties. Shared between the interceptor and fast property accessor
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::Undefined();
QObject *object = resource->object;
QHashedV8String propertystring(property);
QV8Engine *v8engine = resource->engine;
+ v8::Handle<v8::Value> This = info.This();
v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, propertystring,
QV8QObjectWrapper::IgnoreRevision);
if (!result.IsEmpty())
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;
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;
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;
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;
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;
{
Q_ASSERT(handle->IsObject());
- QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(handle->ToObject());
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(handle->ToObject());
Q_ASSERT(resource);
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;