aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/v8/qv8typewrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/v8/qv8typewrapper.cpp')
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp85
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());
+ }
+ }
}
}