diff options
Diffstat (limited to 'src/declarative/qml/v8/qv8typewrapper.cpp')
-rw-r--r-- | src/declarative/qml/v8/qv8typewrapper.cpp | 85 |
1 files changed, 59 insertions, 26 deletions
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp index c51a2eeb7f..f46aaab320 100644 --- a/src/declarative/qml/v8/qv8typewrapper.cpp +++ b/src/declarative/qml/v8/qv8typewrapper.cpp @@ -45,6 +45,9 @@ #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativecontext_p.h> +#include <private/qjsvalue_p.h> +#include <private/qscript_impl_p.h> + QT_BEGIN_NAMESPACE class QV8TypeResource : public QV8ObjectResource @@ -58,12 +61,14 @@ public: QV8TypeWrapper::TypeNameMode mode; QDeclarativeGuard<QObject> object; + QDeclarativeType *type; QDeclarativeTypeNameCache *typeNamespace; + const void *importNamespace; }; QV8TypeResource::QV8TypeResource(QV8Engine *engine) -: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0) +: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0), importNamespace(0) { } @@ -95,6 +100,7 @@ void QV8TypeWrapper::init(QV8Engine *engine) m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } +// Returns a type wrapper for type t on o. This allows access of enums, and attached properties. v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode) { Q_ASSERT(t); @@ -106,14 +112,18 @@ v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, return rv; } -v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode) +// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a +// namespace. +v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, + const void *importNamespace, TypeNameMode mode) { Q_ASSERT(t); + Q_ASSERT(importNamespace); // XXX NewInstance() should be optimized v8::Local<v8::Object> rv = m_constructor->NewInstance(); QV8TypeResource *r = new QV8TypeResource(m_engine); t->addref(); - r->mode = mode; r->object = o; r->typeNamespace = t; + r->mode = mode; r->object = o; r->typeNamespace = t; r->importNamespace = importNamespace; rv->SetExternalResource(r); return rv; } @@ -136,19 +146,9 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, QDeclarativeType *type = resource->type; if (QV8Engine::startsWithUpper(property)) { - if (resource->mode == IncludeEnums) { - QString name = v8engine->toString(property); - - // ### Optimize - QByteArray enumName = name.toUtf8(); - const QMetaObject *metaObject = type->baseMetaObject(); - for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - int value = e.keyToValue(enumName.constData()); - if (value != -1) - return v8::Integer::New(value); - } - } + int value = type->enumValue(propertystring); + if (-1 != value) + return v8::Integer::New(value); // Fall through to return empty handle @@ -164,14 +164,15 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, // Fall through to return empty handle } else if (resource->typeNamespace) { + Q_ASSERT(resource->importNamespace); + QDeclarativeTypeNameCache::Result r = resource->typeNamespace->query(propertystring, + resource->importNamespace); - QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace; - QDeclarativeTypeNameCache::Data *d = typeNamespace->data(propertystring); - Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported + if (r.isValid()) { + Q_ASSERT(r.type); - if (d && d->type) { - return v8engine->typeWrapper()->newObject(object, d->type, resource->mode); - } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) { + return v8engine->typeWrapper()->newObject(object, r.type, resource->mode); + } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { if (moduleApi->scriptCallback) { moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); @@ -184,8 +185,31 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, } if (moduleApi->qobjectApi) { + // check for enum value + if (QV8Engine::startsWithUpper(property)) { + if (resource->mode == IncludeEnums) { + QString name = v8engine->toString(property); + + // ### Optimize + QByteArray enumName = name.toUtf8(); + const QMetaObject *metaObject = moduleApi->qobjectApi->metaObject(); + for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + int value = e.keyToValue(enumName.constData()); + if (value != -1) + return v8::Integer::New(value); + } + } + } + + // check for property. v8::Handle<v8::Value> rv = v8engine->qobjectWrapper()->getProperty(moduleApi->qobjectApi, propertystring, QV8QObjectWrapper::IgnoreRevision); return rv; + } else if (moduleApi->scriptApi.isValid()) { + // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. + QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi); + QScopedPointer<QJSValuePrivate> propertyValue(apiprivate->property(property).give()); + return propertyValue->asV8Value(v8engine); } else { return v8::Handle<v8::Value>(); } @@ -212,8 +236,6 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, QV8Engine *v8engine = resource->engine; - // XXX TODO: Implement writes to module API objects - QHashedV8String propertystring(property); if (resource->type && resource->object) { @@ -224,7 +246,7 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, v8engine->qobjectWrapper()->setProperty(ao, propertystring, value, QV8QObjectWrapper::IgnoreRevision); } else if (resource->typeNamespace) { - if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi()) { + if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { if (moduleApi->scriptCallback) { moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); moduleApi->scriptCallback = 0; @@ -235,9 +257,20 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, moduleApi->qobjectCallback = 0; } - if (moduleApi->qobjectApi) + if (moduleApi->qobjectApi) { v8engine->qobjectWrapper()->setProperty(moduleApi->qobjectApi, propertystring, value, QV8QObjectWrapper::IgnoreRevision); + } else if (moduleApi->scriptApi.isValid()) { + QScopedPointer<QJSValuePrivate> setvalp(new QJSValuePrivate(v8engine, value)); + QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi); + if (apiprivate->propertyFlags(property) & QJSValue::ReadOnly) { + QString error = QLatin1String("Cannot assign to read-only property \"") + + v8engine->toString(property) + QLatin1Char('\"'); + v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); + } else { + apiprivate->setProperty(property, setvalp.data()); + } + } } } |