QScriptClass::QueryFlags
QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
                                             QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext,
                                             QueryHints hints)
{
    Q_UNUSED(flags);
    lastData = 0;
    lastTNData = 0;

    if (name == m_destroyId.identifier ||
        name == m_toStringId.identifier)
        return QScriptClass::HandlesReadAccess;

    if (!obj)
        return 0;

    QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
    lastData = QDeclarativePropertyCache::property(engine, obj, name, local);
    if ((hints & ImplicitObject) && lastData && lastData->revision != 0) {

        QDeclarativeData *ddata = QDeclarativeData::get(obj);
        if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData)) 
            return 0;
    }

    if (lastData)
        return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;

    if (!(hints & SkipAttachedProperties)) {
        if (!evalContext && context()) {
            // Global object, QScriptContext activation object, QDeclarativeContext object
            QScriptValue scopeNode = scopeChainValue(context(), -3);
            if (scopeNode.isValid()) {
                Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);

                evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
            }
        }

        if (evalContext && evalContext->imports) {
            QDeclarativeTypeNameCache::Data *data = evalContext->imports->data(name);
            if (data) {
                lastTNData = data;
                return QScriptClass::HandlesReadAccess;
            }
        }
    }

    if (!(hints & ImplicitObject)) {
        local.coreIndex = -1;
        lastData = &local;
        return QScriptClass::HandlesWriteAccess;
    }

    return 0;
}
Example #2
0
void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
                                                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('\"');
        context->throwError(error);
        return;
    }

    if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) && 
        !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
        QString error = QLatin1String("Cannot assign to read-only property \"") +
                        toString(name) + QLatin1Char('\"');
        context->throwError(error);
        return;
    }

    QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);

    if (!evalContext) {
        // Global object, QScriptContext activation object, QDeclarativeContext object
        QScriptValue scopeNode = scopeChainValue(context, -3);
        if (scopeNode.isValid()) {
            Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);

            evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
        }
    }

    QDeclarativeAbstractBinding *delBinding =
        QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, 0);
    if (delBinding)
        delBinding->destroy();

    if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
        QObject *o = 0;
        int status = -1;
        int flags = 0;
        void *argv[] = { &o, 0, &status, &flags };
        QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
    } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
        void *a[] = { 0 };
        QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
    } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
        QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
    } else if (value.isUndefined()) {
        QString error = QLatin1String("Cannot assign [undefined] to ") +
                        QLatin1String(QMetaType::typeName(lastData->propType));
        context->throwError(error);
    } else {
        QVariant v;
        if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
            v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
        else
            v = enginePriv->scriptValueToVariant(value, lastData->propType);

        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);
        }
    }
}
void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
                                                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('\"');
        context->throwError(error);
        return;
    }

    if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) && 
        !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
        QString error = QLatin1String("Cannot assign to read-only property \"") +
                        toString(name) + QLatin1Char('\"');
        context->throwError(error);
        return;
    }

    QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);

    if (!evalContext) {
        // Global object, QScriptContext activation object, QDeclarativeContext object
        QScriptValue scopeNode = scopeChainValue(context, -3);
        if (scopeNode.isValid()) {
            Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);

            evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
        }
    }

    QDeclarativeBinding *newBinding = 0;
    if (value.isFunction() && !value.isRegExp()) {
        QScriptContextInfo ctxtInfo(context);
        QDeclarativePropertyCache::ValueTypeData valueTypeData;

        newBinding = new QDeclarativeBinding(value, obj, evalContext);
        newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
        newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext));
        if (newBinding->expression().contains(QLatin1String("this")))
            newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
    }

    QDeclarativeAbstractBinding *delBinding =
        QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding);
    if (delBinding)
        delBinding->destroy();

    if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
        QObject *o = 0;
        int status = -1;
        int flags = 0;
        void *argv[] = { &o, 0, &status, &flags };
        QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
    } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
        void *a[] = { 0 };
        QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
    } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
        QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
    } else if (value.isUndefined()) {
        QString error = QLatin1String("Cannot assign [undefined] to ") +
                        QLatin1String(QMetaType::typeName(lastData->propType));
        context->throwError(error);
    } else if (value.isFunction() && !value.isRegExp()) {
        // this is handled by the binding creation above
    } else {
        //### expand optimization for other known types
        if (lastData->propType == QMetaType::Int && value.isNumber()) {
            int rawValue = qRoundDouble(value.toNumber());
            int status = -1;
            int flags = 0;
            void *a[] = { (void *)&rawValue, 0, &status, &flags };
            QMetaObject::metacall(obj, QMetaObject::WriteProperty,
                                  lastData->coreIndex, a);
            return;
        } else if (lastData->propType == QMetaType::QReal && value.isNumber()) {
            qreal rawValue = qreal(value.toNumber());
            int status = -1;
            int flags = 0;
            void *a[] = { (void *)&rawValue, 0, &status, &flags };
            QMetaObject::metacall(obj, QMetaObject::WriteProperty,
                                  lastData->coreIndex, a);
            return;
        } else if (lastData->propType == QMetaType::QString && value.isString()) {
            const QString &rawValue = value.toString();
            int status = -1;
            int flags = 0;
            void *a[] = { (void *)&rawValue, 0, &status, &flags };
            QMetaObject::metacall(obj, QMetaObject::WriteProperty,
                                  lastData->coreIndex, a);
            return;
        }

        QVariant v;
        if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
            v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
        else
            v = enginePriv->scriptValueToVariant(value, lastData->propType);

        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);
        }
    }
}