OSDN Git Service

QmlJS: Avoid infinite recursion when encountering property loops.
authorChristian Kamm <christian.d.kamm@nokia.com>
Tue, 8 Jun 2010 13:36:06 +0000 (15:36 +0200)
committerChristian Kamm <christian.d.kamm@nokia.com>
Tue, 8 Jun 2010 13:37:16 +0000 (15:37 +0200)
Such as
property int foo: bar
property int bar: foo.

Task-number: QTCREATORBUG-1389
Reviewed-by: Roberto Raggi
src/libs/qmljs/qmljsevaluate.cpp
src/libs/qmljs/qmljsinterpreter.cpp
src/libs/qmljs/qmljsinterpreter.h

index d7a7129..2b6821e 100644 (file)
@@ -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();
index a32cd10..a83f241 100644 (file)
@@ -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;
index 50254fd..7ce3fcf 100644 (file)
@@ -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;
 };