forked from qt-creator/qt-creator
		
	QmlJS: Avoid infinite recursion when encountering property loops.
Such as property int foo: bar property int bar: foo. Task-number: QTCREATORBUG-1389 Reviewed-by: Roberto Raggi
This commit is contained in:
		@@ -53,7 +53,7 @@ const Interpreter::Value *Evaluate::operator()(AST::Node *ast)
 | 
			
		||||
    const Value *result = reference(ast);
 | 
			
		||||
 | 
			
		||||
    if (const Reference *ref = value_cast<const Reference *>(result))
 | 
			
		||||
        result = ref->value(_context);
 | 
			
		||||
        result = _context->lookupReference(ref);
 | 
			
		||||
 | 
			
		||||
    if (! result)
 | 
			
		||||
        result = _engine->undefinedValue();
 | 
			
		||||
 
 | 
			
		||||
@@ -1483,6 +1483,18 @@ const ObjectValue *Context::lookupType(const QmlJS::Document *doc, const QString
 | 
			
		||||
    return objectValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Value *Context::lookupReference(const Reference *reference)
 | 
			
		||||
{
 | 
			
		||||
    if (_referenceStack.contains(reference))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    _referenceStack.append(reference);
 | 
			
		||||
    const Value *v = reference->value(this);
 | 
			
		||||
    _referenceStack.removeLast();
 | 
			
		||||
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Value *Context::property(const ObjectValue *object, const QString &name) const
 | 
			
		||||
{
 | 
			
		||||
    const Properties properties = _properties.value(object);
 | 
			
		||||
@@ -1632,7 +1644,7 @@ const ObjectValue *ObjectValue::prototype(Context *context) const
 | 
			
		||||
    const ObjectValue *prototypeObject = value_cast<const ObjectValue *>(_prototype);
 | 
			
		||||
    if (! prototypeObject) {
 | 
			
		||||
        if (const Reference *prototypeReference = value_cast<const Reference *>(_prototype)) {
 | 
			
		||||
            prototypeObject = value_cast<const ObjectValue *>(prototypeReference->value(context));
 | 
			
		||||
            prototypeObject = value_cast<const ObjectValue *>(context->lookupReference(prototypeReference));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return prototypeObject;
 | 
			
		||||
 
 | 
			
		||||
@@ -293,6 +293,7 @@ public:
 | 
			
		||||
    const Value *lookup(const QString &name);
 | 
			
		||||
    const ObjectValue *lookupType(const Document *doc, AST::UiQualifiedId *qmlTypeName);
 | 
			
		||||
    const ObjectValue *lookupType(const Document *doc, const QStringList &qmlTypeName);
 | 
			
		||||
    const Value *lookupReference(const Reference *reference);
 | 
			
		||||
 | 
			
		||||
    const Value *property(const ObjectValue *object, const QString &name) const;
 | 
			
		||||
    void setProperty(const ObjectValue *object, const QString &name, const Value *value);
 | 
			
		||||
@@ -313,6 +314,7 @@ private:
 | 
			
		||||
    ScopeChain _scopeChain;
 | 
			
		||||
    int _qmlScopeObjectIndex;
 | 
			
		||||
    bool _qmlScopeObjectSet;
 | 
			
		||||
    QList<const Reference *> _referenceStack;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QMLJS_EXPORT Reference: public Value
 | 
			
		||||
@@ -322,14 +324,16 @@ public:
 | 
			
		||||
    virtual ~Reference();
 | 
			
		||||
 | 
			
		||||
    Engine *engine() const;
 | 
			
		||||
    virtual const Value *value(Context *context) const;
 | 
			
		||||
 | 
			
		||||
    // Value interface
 | 
			
		||||
    virtual const Reference *asReference() const;
 | 
			
		||||
    virtual void accept(ValueVisitor *) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual const Value *value(Context *context) const;
 | 
			
		||||
 | 
			
		||||
    Engine *_engine;
 | 
			
		||||
    friend class Context;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QMLJS_EXPORT ColorValue: public Value
 | 
			
		||||
@@ -742,9 +746,9 @@ public:
 | 
			
		||||
 | 
			
		||||
    AST::UiQualifiedId *qmlTypeName() const;
 | 
			
		||||
 | 
			
		||||
private:    
 | 
			
		||||
    virtual const Value *value(Context *context) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    AST::UiQualifiedId *_qmlTypeName;
 | 
			
		||||
    const Document *_doc;
 | 
			
		||||
};
 | 
			
		||||
@@ -757,6 +761,7 @@ public:
 | 
			
		||||
    ASTVariableReference(AST::VariableDeclaration *ast, Engine *engine);
 | 
			
		||||
    virtual ~ASTVariableReference();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual const Value *value(Context *context) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -792,6 +797,8 @@ public:
 | 
			
		||||
    QString onChangedSlotName() const { return _onChangedSlotName; }
 | 
			
		||||
 | 
			
		||||
    virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual const Value *value(Context *context) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -809,6 +816,8 @@ public:
 | 
			
		||||
    QString slotName() const { return _slotName; }
 | 
			
		||||
 | 
			
		||||
    virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual const Value *value(Context *context) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user