コード例 #1
0
ファイル: defaultscriptclass.cpp プロジェクト: KDE/okteta
void DefaultScriptClass::setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value)
{
    const ScriptHandlerInfo::Mode mode = mHandlerInfo->mode();
    Q_ASSERT(mode != ScriptHandlerInfo::None);
    DataInformation* data = toDataInformation(object);
    if (!data)
    {
        mHandlerInfo->logger()->error() << "could not cast data from" << object.data().toString();
        engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Attempting to access an invalid object"));
        return;
    }
    if (mode == ScriptHandlerInfo::Validating)
    {
        //only way write access is allowed is when validating: valid and validationError
        if (data->hasBeenValidated())
            data->logError() << "Cannot modify this object, it has already been validated!";
        else if (name == s_valid)
            data->mValidationSuccessful = value.toBool();
        else if (name == s_validationError)
            data->setValidationError(value.toString());
        else
            data->logError() << "Cannot write to property" << name.toString() << "while validating!";
        return;
    }

    if (mode != ScriptHandlerInfo::Updating)
    {
        data->logError() << "Writing to property" << name.toString() << "is only allowed when updating.";
        return;
    }
    Q_ASSERT(mode == ScriptHandlerInfo::Updating);

    if (name == s_byteOrder)
    {
        data->setByteOrder(ParserUtils::byteOrderFromString(value.toString(),
                LoggerWithContext(data->logger(), data->fullObjectPath())));
    }
    else if (name == s_datatype)
    {
        //change the type of the underlying object
        setDataType(value, data);
    }
    else if (name == s_updateFunc)
    {
        data->setUpdateFunc(value);
    }
    else if (name == s_validationFunc)
    {
        data->setValidationFunc(value);
    }
    else if (name == s_name)
    {
        data->setName(value.toString());
    }
    else if (name == s_customTypeName)
    {
        if (!value.isValid() || value.isNull() || value.isUndefined())
            data->setCustomTypeName(QString()); //unset
        else
            data->setCustomTypeName(value.toString());
    }
    else if (name == s_asStringFunc)
    {
        data->setToStringFunction(value);
    }
    else
    {
        bool setAdditional = setAdditionalProperty(data, name, id, value);
        if (setAdditional)
            return;
        else
        {
            data->logError() << "could not set property with name" << name.toString();
            engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Cannot write property ") + name.toString());
        }
    }
}
コード例 #2
0
ファイル: defaultscriptclass.cpp プロジェクト: KDE/okteta
void DefaultScriptClass::setDataType(const QScriptValue& value, DataInformation* data)
{
    DataInformation* thisObj = toDataInformation(engine()->currentContext()->thisObject());
    Q_CHECK_PTR(thisObj);
    const bool isThisObj = thisObj == data;
    //this object always has mHasBeenUpdated set just before calling updateFunc, so in that case it is okay
    if (data->hasBeenUpdated() && !isThisObj)
    {
        //this element has already been updated (and probably read, replacing it could cause crazy errors
        data->logError() << "Attempting to replace an already updated object. This could cause errors."
                "Current this object: " << (thisObj ? thisObj->fullObjectPath() : QString());
        return;
    }
    //change the type of the underlying object
    DataInformation* newType = ScriptValueConverter::convert(value, data->name(), data->logger(), data);
    if (!newType)
    {
        data->logError() << "Failed to set new type, could not convert value!";
        return;
    }

    DataInformationBase* parent = data->parent();
    Q_CHECK_PTR(parent);
    TopLevelDataInformation* top = data->topLevelDataInformation();
    Q_CHECK_PTR(top);
    //only if parent is toplevel, struct or union, can we replace
    bool replaced = false;
    if (parent->isTopLevel())
    {
        Q_ASSERT(isThisObj); //we can only do this if we are currently at the top level element
        parent->asTopLevel()->setActualDataInformation(newType);
        replaced = true;
    }
    else if (parent->isStruct())
    {
        StructureDataInformation* stru = parent->asStruct();
        int index = stru->indexOf(data);
        Q_ASSERT(index != -1);
        Q_ASSERT(uint(index) < stru->childCount());
        replaced = stru->replaceChildAt(index, newType);
        if (!replaced)
            stru->logError() << "failed to replace child at index" << index;
    }
    else if (parent->isUnion())
    {
        UnionDataInformation* un = parent->asUnion();
        int index = un->indexOf(data);
        Q_ASSERT(index != -1);
        Q_ASSERT(uint(index) < un->childCount());
        replaced = un->replaceChildAt(index, newType);
        if (!replaced)
            un->logError() << "failed to replace child at index" << index;
    }
    else if (parent->isPointer())
    {
        parent->asPointer()->setPointerTarget(newType);
        replaced = true;
    }
    else
    {
        data->logError() << "Failed to set data type since element is not toplevel and parent"
                " is neither struct nor union nor pointer.";
    }
    if (replaced)
    {
        top->setChildDataChanged();
        //if the current object was "this" in javascript we have to replace it
        if (isThisObj)
            engine()->currentContext()->setThisObject(newType->toScriptValue(engine(), mHandlerInfo));
        newType->mHasBeenUpdated = true;
    }
    else
    {
        delete newType; //could not set new type
    }
}