diff options
Diffstat (limited to 'src/declarative/qml')
24 files changed, 231 insertions, 114 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 71cf3cb..9a7a242 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -148,14 +148,46 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) idx, a); } else { + QDeclarativeEnginePrivate *ep = (data->context() && data->context()->engine)? + QDeclarativeEnginePrivate::get(data->context()->engine):0; + bool isUndefined = false; - QVariant value = this->value(&isUndefined); + QVariant value; + + QScriptValue scriptValue = d->scriptValue(0, &isUndefined); + if (data->property.propertyTypeCategory() == QDeclarativeProperty::List) { + value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >()); + } else { + value = ep->scriptValueToVariant(scriptValue, data->property.propertyType()); + if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) { + // If the object is null, we extract the predicted type. While this isn't + // 100% reliable, in many cases it gives us better error messages if we + // assign this null-object to an incompatible property + int type = ep->objectClass->objectType(scriptValue); + value = QVariant(type, (void *)0); + } + } + + if (data->error.isValid()) { + + } else if (!scriptValue.isVariant() && value.userType() == QMetaType::QVariantList && + data->property.propertyType() == qMetaTypeId<QVariant>()) { + + // This case catches QtScript's automatic conversion to QVariantList for arrays + QUrl url = QUrl(data->url); + int line = data->line; + if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>")); + + data->error.setUrl(url); + data->error.setLine(line); + data->error.setColumn(-1); + data->error.setDescription(QLatin1String("Unable to assign JavaScript array to QML variant property")); - if (isUndefined && !data->error.isValid() && data->property.isResettable()) { + } else if (isUndefined && data->property.isResettable()) { data->property.reset(); - } else if (isUndefined && !data->error.isValid()) { + } else if (isUndefined) { QUrl url = QUrl(data->url); int line = data->line; @@ -166,7 +198,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) data->error.setColumn(-1); data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(data->property.propertyType()))); - } else if (!isUndefined && data->property.object() && + } else if (data->property.object() && !QDeclarativePropertyPrivate::write(data->property, value, flags)) { QUrl url = QUrl(data->url); @@ -187,9 +219,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } if (data->error.isValid()) { - QDeclarativeEnginePrivate *p = (data->context() && data->context()->engine)? - QDeclarativeEnginePrivate::get(data->context()->engine):0; - if (!data->addError(p)) + if (!data->addError(ep)) qWarning().nospace() << qPrintable(this->error().toString()); } else { data->removeError(); diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index b12d6f4..d2b2024 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -342,9 +342,22 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, switch(type) { case -1: { - instr.type = QDeclarativeInstruction::StoreVariant; - instr.storeString.propertyIndex = prop.propertyIndex(); - instr.storeString.value = output->indexForString(string); + if (v->value.isNumber()) { + double n = v->value.asNumber(); + if (double(int(n)) == n) { + instr.type = QDeclarativeInstruction::StoreVariantInteger; + instr.storeInteger.propertyIndex = prop.propertyIndex(); + instr.storeInteger.value = int(n); + } else { + instr.type = QDeclarativeInstruction::StoreVariantDouble; + instr.storeDouble.propertyIndex = prop.propertyIndex(); + instr.storeDouble.value = n; + } + } else { + instr.type = QDeclarativeInstruction::StoreVariant; + instr.storeString.propertyIndex = prop.propertyIndex(); + instr.storeString.value = output->indexForString(string); + } } break; case QVariant::String: @@ -882,7 +895,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) // Create the object if (obj->custom.isEmpty() && output->types.at(obj->type).type && - obj != compileState.root) { + !output->types.at(obj->type).type->isExtendedType() && obj != compileState.root) { QDeclarativeInstruction create; create.type = QDeclarativeInstruction::CreateSimpleObject; @@ -2520,7 +2533,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn ((QDeclarativeVMEMetaData *)dynamicData.data())->methodCount++; QDeclarativeVMEMetaData::MethodData methodData = - { s.parameterNames.count(), 0, funcScript.length(), 0 }; + { s.parameterNames.count(), 0, funcScript.length(), s.location.start.line }; dynamicData.append((char *)&methodData, sizeof(methodData)); } diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 6c5a1f7..eee72b6 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -174,7 +174,7 @@ public: inline ContextGuard &operator=(QObject *obj) { QDeclarativeGuard<QObject>::operator=(obj); return *this; } virtual void objectDestroyed(QObject *) { - if (!QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify(); + if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify(); } QDeclarativeContextData *context; QDeclarativeNotifier bindings; diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp index 6d31c22..461fab5 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp +++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp @@ -295,7 +295,7 @@ void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifie QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - ep->objectClass->setProperty(lastScopeObject, name, value, bindContext); + ep->objectClass->setProperty(lastScopeObject, name, value, context(), bindContext); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativedeclarativedata_p.h b/src/declarative/qml/qdeclarativedeclarativedata_p.h index 87c5c9c..5b12629 100644 --- a/src/declarative/qml/qdeclarativedeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedeclarativedata_p.h @@ -75,7 +75,17 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - attachedProperties(0), scriptValue(0), propertyCache(0), guards(0) {} + attachedProperties(0), scriptValue(0), propertyCache(0), guards(0) { + init(); + } + + static inline void init() { + QDeclarativeData::destroyed = destroyed; + QDeclarativeData::parentChanged = parentChanged; + } + + static void destroyed(QDeclarativeData *, QObject *); + static void parentChanged(QDeclarativeData *, QObject *, QObject *); void destroyed(QObject *); void parentChanged(QObject *, QObject *); diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index f5fe140..1bcadf2 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -346,12 +346,12 @@ typedef QMap<QString, QString> StringStringMap; Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri -static void QDeclarativeDeclarativeData_destroyed(QDeclarativeData *d, QObject *o) +void QDeclarativeDeclarativeData::destroyed(QDeclarativeData *d, QObject *o) { static_cast<QDeclarativeDeclarativeData *>(d)->destroyed(o); } -static void QDeclarativeDeclarativeData_parentChanged(QDeclarativeData *d, QObject *o, QObject *p) +void QDeclarativeDeclarativeData::parentChanged(QDeclarativeData *d, QObject *o, QObject *p) { static_cast<QDeclarativeDeclarativeData *>(d)->parentChanged(o, p); } @@ -363,8 +363,7 @@ void QDeclarativeEnginePrivate::init() qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString"); qRegisterMetaType<QScriptValue>("QScriptValue"); - QDeclarativeData::destroyed = QDeclarativeDeclarativeData_destroyed; - QDeclarativeData::parentChanged = QDeclarativeDeclarativeData_parentChanged; + QDeclarativeDeclarativeData::init(); contextClass = new QDeclarativeContextScriptClass(q); objectClass = new QDeclarativeObjectScriptClass(q); @@ -409,7 +408,7 @@ QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine \code QDeclarativeEngine engine; QDeclarativeComponent component(&engine); - component.setData("import Qt 4.6\nText { text: \"Hello world!\" }", QUrl()); + component.setData("import Qt 4.7\nText { text: \"Hello world!\" }", QUrl()); QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create()); //add item to view, etc @@ -1324,7 +1323,6 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); } - QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) { if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { @@ -1335,6 +1333,14 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } else { return scriptEngine.nullValue(); } + } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) { + const QList<QObject *> &list = *(QList<QObject *>*)val.constData(); + QScriptValue rv = scriptEngine.newArray(list.count()); + for (int ii = 0; ii < list.count(); ++ii) { + QObject *object = list.at(ii); + rv.setProperty(ii, objectClass->newQObject(object)); + } + return rv; } bool objOk; @@ -1346,22 +1352,29 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } } -QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val) +QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint) { QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); if (dc == objectClass) return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == valueTypeClass) + return valueTypeClass->toVariant(val); else if (dc == contextClass) return QVariant(); - QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val); - if (!sc) { - return val.toVariant(); - } else if (sc == valueTypeClass) { - return valueTypeClass->toVariant(val); - } else { - return QVariant(); + // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted + if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) { + QList<QObject *> list; + int length = val.property(QLatin1String("length")).toInt32(); + for (int ii = 0; ii < length; ++ii) { + QScriptValue arrayItem = val.property(ii); + QObject *d = arrayItem.toQObject(); + list << d; + } + return QVariant::fromValue(list); } + + return val.toVariant(); } // XXX this beyonds in QUrl::toLocalFile() diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 45089d0..3f22d61 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -308,7 +308,7 @@ public: QHash<QString, QScriptValue> m_sharedScriptImports; QScriptValue scriptValueFromVariant(const QVariant &); - QVariant scriptValueToVariant(const QScriptValue &); + QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid); void sendQuit (); diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index a250f21..2a3e557 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -175,7 +175,8 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex } QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object, - const QString &program, QScriptValue *contextObject) + const QString &program, const QString &fileName, + int lineNumber, QScriptValue *contextObject) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); @@ -186,7 +187,7 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex scriptContext->pushScope(ep->contextClass->newContext(context, object)); } scriptContext->pushScope(ep->globalClass->globalObject()); - QScriptValue rv = ep->scriptEngine.evaluate(program); + QScriptValue rv = ep->scriptEngine.evaluate(program, fileName, lineNumber); ep->scriptEngine.popContext(); return rv; } @@ -351,7 +352,7 @@ void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine } } -QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined) +QScriptValue QDeclarativeExpressionPrivate::eval(QObject *secondaryScope, bool *isUndefined) { QDeclarativeExpressionData *data = this->data; QDeclarativeEngine *engine = data->context()->engine; @@ -376,7 +377,7 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo const QString code = rewriteBinding(data->expression, &ok); if (!ok) { scriptEngine->popContext(); - return QVariant(); + return QScriptValue(); } data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line); } @@ -413,54 +414,20 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo if (scriptEngine->hasUncaughtException()) { exceptionToError(scriptEngine, data->error); scriptEngine->clearExceptions(); - return QVariant(); + return QScriptValue(); } else { data->error = QDeclarativeError(); + return svalue; } - - QVariant rv; - - if (svalue.isArray()) { - int length = svalue.property(QLatin1String("length")).toInt32(); - if (length && svalue.property(0).isObject()) { - QList<QObject *> list; - for (int ii = 0; ii < length; ++ii) { - QScriptValue arrayItem = svalue.property(ii); - QObject *d = arrayItem.toQObject(); - list << d; - } - rv = QVariant::fromValue(list); - } - } else if (svalue.isObject() && - ep->objectClass->scriptClass(svalue) == ep->objectClass) { - QObject *o = svalue.toQObject(); - int type = QMetaType::QObjectStar; - // If the object is null, we extract the predicted type. While this isn't - // 100% reliable, in many cases it gives us better error messages if we - // assign this null-object to an incompatible property - if (!o) type = ep->objectClass->objectType(svalue); - - return QVariant(type, &o); - } - - if (rv.isNull()) - rv = svalue.toVariant(); - - return rv; } -QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) +QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined) { Q_Q(QDeclarativeExpression); - - QVariant rv; - if (!q->engine()) { - qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context"); - return rv; - } + Q_ASSERT(q->engine()); if (data->expression.isEmpty()) - return rv; + return QScriptValue(); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine()); @@ -476,7 +443,7 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU QDeclarativeExpressionData *localData = data; localData->addref(); - rv = evalQtScript(secondaryScope, isUndefined); + QScriptValue value = eval(secondaryScope, isUndefined); ep->currentExpression = lastCurrentExpression; ep->captureProperties = lastCaptureProperties; @@ -494,7 +461,21 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU lastCapturedProperties.copyAndClear(ep->capturedProperties); - return rv; + return value; +} + +QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) +{ + Q_Q(QDeclarativeExpression); + + if (!q->engine()) { + qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context"); + return QVariant(); + } + + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine()); + + return ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId<QList<QObject*> >()); } /*! diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h index 9a90fb6..d39aa2c 100644 --- a/src/declarative/qml/qdeclarativeexpression_p.h +++ b/src/declarative/qml/qdeclarativeexpression_p.h @@ -150,7 +150,9 @@ public: QDeclarativeExpressionData *data; QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0); - QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0); + QScriptValue scriptValue(QObject *secondaryScope = 0, bool *isUndefined = 0); + + QScriptValue eval(QObject *secondaryScope, bool *isUndefined = 0); void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties); void clearGuards(); @@ -165,8 +167,10 @@ public: virtual void emitValueChanged(); static void exceptionToError(QScriptEngine *, QDeclarativeError &); - static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, QScriptValue * = 0); - static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &, QScriptValue * = 0); + static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, const QString &, + int, QScriptValue *); + static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &, + QScriptValue *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 1f8b8af..d88d06a 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -130,6 +130,12 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreVariant: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); break; + case QDeclarativeInstruction::StoreVariantInteger: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + break; + case QDeclarativeInstruction::StoreVariantDouble: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + break; case QDeclarativeInstruction::StoreObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex; break; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index 1f3c964..e8287c0 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -114,6 +114,8 @@ public: StoreRectF, /* storeRect */ StoreVector3D, /* storeVector3D */ StoreVariant, /* storeString */ + StoreVariantInteger, /* storeInteger */ + StoreVariantDouble, /* storeDouble */ StoreObject, /* storeObject */ StoreVariantObject, /* storeObject */ StoreInterface, /* storeObject */ diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 56cc219..7b71608 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -328,6 +328,13 @@ bool QDeclarativeType::isCreatable() const return d->m_newFunc != 0; } +bool QDeclarativeType::isExtendedType() const +{ + d->init(); + + return !d->m_metaObjects.isEmpty(); +} + bool QDeclarativeType::isInterface() const { return d->m_isInterface; diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 96e3c74..70b7c90 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -122,6 +122,7 @@ public: QDeclarativeCustomParser *customParser() const; bool isCreatable() const; + bool isExtendedType() const; bool isInterface() const; int typeId() const; diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 10b9fab..ec84da9 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -52,6 +52,7 @@ #include <QtCore/qtimer.h> #include <QtCore/qvarlengtharray.h> +#include <QtScript/qscriptcontextinfo.h> Q_DECLARE_METATYPE(QScriptValue); @@ -100,6 +101,9 @@ QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type if (!object) return newObject(scriptEngine, this, new ObjectData(object, type)); + if (QObjectPrivate::get(object)->wasDeleted) + return scriptEngine->undefinedValue(); + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, true); if (!ddata) { @@ -222,15 +226,10 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) { return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex)); } else { -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) // Uncomment to use QtScript method call logic // QScriptValue sobj = scriptEngine->newQObject(obj); // return Value(scriptEngine, sobj.property(toString(name))); return Value(scriptEngine, methods.newMethod(obj, lastData)); -#else - QScriptValue sobj = scriptEngine->newQObject(obj); - return Value(scriptEngine, sobj.property(toString(name))); -#endif } } else { if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) { @@ -295,7 +294,6 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); return Value(scriptEngine, enginePriv->scriptValueFromVariant(var)); } - } } @@ -303,40 +301,40 @@ void QDeclarativeObjectScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - return setProperty(toQObject(object), name, value); + return setProperty(toQObject(object), name, value, context()); } void QDeclarativeObjectScriptClass::setProperty(QObject *obj, - const Identifier &name, - const QScriptValue &value, - QDeclarativeContextData *evalContext) + const Identifier &name, + const QScriptValue &value, + QScriptContext *context, + QDeclarativeContextData *evalContext) { Q_UNUSED(name); Q_ASSERT(obj); Q_ASSERT(lastData); + Q_ASSERT(context); if (!lastData->isValid()) { QString error = QLatin1String("Cannot assign to non-existent property \"") + toString(name) + QLatin1Char('\"'); - if (context()) - context()->throwError(error); + context->throwError(error); return; } if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable)) { QString error = QLatin1String("Cannot assign to read-only property \"") + toString(name) + QLatin1Char('\"'); - if (context()) - context()->throwError(error); + context->throwError(error); return; } QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - if (!evalContext && context()) { + if (!evalContext) { // Global object, QScriptContext activation object, QDeclarativeContext object - QScriptValue scopeNode = scopeChainValue(context(), -3); + QScriptValue scopeNode = scopeChainValue(context, -3); if (scopeNode.isValid()) { Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass); @@ -352,10 +350,33 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) { void *a[] = { 0 }; QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a); + } else if (value.isUndefined()) { + QString error = QLatin1String("Cannot assign [undefined] to ") + + QLatin1String(QMetaType::typeName(lastData->propType)); + context->throwError(error); } else { - // ### Can well known types be optimized? - QVariant v = enginePriv->scriptValueToVariant(value); - QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext); + QVariant v; + if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) + v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >()); + else + v = enginePriv->scriptValueToVariant(value, lastData->propType); + + if (!value.isVariant() && v.userType() == QMetaType::QVariantList && + lastData->propType == qMetaTypeId<QVariant>()) { + + QString error = QLatin1String("Cannot assign JavaScript array to QML variant property"); + context->throwError(error); + } else if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) { + const char *valueType = 0; + if (v.userType() == QVariant::Invalid) valueType = "null"; + else valueType = QMetaType::typeName(v.userType()); + + QString error = QLatin1String("Cannot assign ") + + QLatin1String(valueType) + + QLatin1String(" to ") + + QLatin1String(QMetaType::typeName(lastData->propType)); + context->throwError(error); + } } } @@ -456,8 +477,6 @@ bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2) return d1 == d2 || d1->object == d2->object; } -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) - struct MethodData : public QScriptDeclarativeClass::Object { MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {} @@ -687,7 +706,17 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value)); type = callType; } else if (callType == qMetaTypeId<QList<QObject*> >()) { - new (&data) QList<QObject *>(); // We don't support passing in QList<QObject*> + QList<QObject *> *list = new (&data) QList<QObject *>(); + if (value.isArray()) { + int length = value.property(QLatin1String("length")).toInt32(); + for (int ii = 0; ii < length; ++ii) { + QScriptValue arrayItem = value.property(ii); + QObject *d = arrayItem.toQObject(); + list->append(d); + } + } else if (QObject *d = value.toQObject()) { + list->append(d); + } type = callType; } else { new (&data) QVariant(); @@ -800,7 +829,5 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass:: return Value(); } -#endif - QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h index 8a2f7c7..5a59ef8 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h @@ -118,7 +118,7 @@ public: Value property(QObject *, const Identifier &); void setProperty(QObject *, const Identifier &name, const QScriptValue &, - QDeclarativeContextData *evalContext = 0); + QScriptContext *context, QDeclarativeContextData *evalContext = 0); virtual QStringList propertyNames(Object *); virtual bool compare(Object *, Object *); diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index 69186b6..d1f209a 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -200,7 +200,7 @@ QDeclarativeParser::Object::DynamicSlot::DynamicSlot() } QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) -: name(o.name), body(o.body), parameterNames(o.parameterNames) +: name(o.name), body(o.body), parameterNames(o.parameterNames), location(o.location) { } diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 57df04c..00fc65b 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -227,6 +227,7 @@ namespace QDeclarativeParser QByteArray name; QString body; QList<QByteArray> parameterNames; + LocationSpan location; }; // The list of dynamic properties diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index cba5bb9..507ff5b 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -488,8 +488,8 @@ bool ProcessAST::visit(AST::UiImport *node) } else if (import.type == QDeclarativeScriptParser::Import::Script) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Script import requires a qualifier")); - error.setLine(node->importIdToken.startLine); - error.setColumn(node->importIdToken.startColumn); + error.setLine(node->fileNameToken.startLine); + error.setColumn(node->fileNameToken.startColumn); _parser->_errors << error; return false; } @@ -828,6 +828,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node) if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { Object::DynamicSlot slot; + slot.location = location(funDecl->firstSourceLocation(), funDecl->lastSourceLocation()); AST::FormalParameterList *f = funDecl->formals; while (f) { diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 5c88b9a..bbcc00b 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -82,10 +82,6 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) { if (s.isEmpty()) return QVariant(s); - if (s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) { - QString data = s.mid(1, s.length() - 2); - return QVariant(data); - } bool ok = false; QRectF r = rectFFromString(s, &ok); if (ok) return QVariant(r); @@ -104,6 +100,10 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int preferredType, bool *ok) { switch (preferredType) { + case QMetaType::Int: + return QVariant(int(qRound(s.toDouble(ok)))); + case QMetaType::UInt: + return QVariant(uint(qRound(s.toDouble(ok)))); case QMetaType::QColor: return QVariant::fromValue(colorFromString(s, ok)); case QMetaType::QDate: diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index 324b3de..2a3417a 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -159,7 +159,7 @@ void QDeclarativeTypeNameScriptClass::setProperty(Object *o, const Identifier &n Q_ASSERT(!type); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v); + ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v, context()); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 2d1a549..0addfabd 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -345,6 +345,26 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, } break; + case QDeclarativeInstruction::StoreVariantInteger: + { + QObject *target = stack.top(); + QVariant v(instr.storeInteger.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeString.propertyIndex, a); + } + break; + + case QDeclarativeInstruction::StoreVariantDouble: + { + QObject *target = stack.top(); + QVariant v(instr.storeDouble.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeString.propertyIndex, a); + } + break; + case QDeclarativeInstruction::StoreString: { QObject *target = stack.top(); diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 2644ecf..2e2a8e8 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -671,7 +671,8 @@ QScriptValue QDeclarativeVMEMetaObject::method(int index) // XXX We should evaluate all methods in a single big script block to // improve the call time between dynamic methods defined on the same // object - methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code); + methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code, ctxt->url.toString(), + data->lineNumber, 0); } return methods[index]; diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index f13dd34..76390c9 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -94,7 +94,7 @@ struct QDeclarativeVMEMetaData int parameterCount; int bodyOffset; int bodyLength; - int scriptProgram; + int lineNumber; }; PropertyData *propertyData() const { diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index ddb0ece..caf680e 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -508,7 +508,7 @@ void QDeclarativeWorkerScriptEngine::run() Here is an example: \qml - import Qt 4.6 + import Qt 4.7 Rectangle { width: 300 |