diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri
index 47488948a0baab5a72f60e0b1a98b1331ce9065d..7532a24eb280e5786a5f7f0aba0803a021490226 100644
--- a/src/libs/qmljs/qmljs-lib.pri
+++ b/src/libs/qmljs/qmljs-lib.pri
@@ -30,7 +30,8 @@ HEADERS += \
     $$PWD/qmljstypedescriptionreader.h \
     $$PWD/qmljsscopeastpath.h \
     $$PWD/qmljsvalueowner.h \
-    $$PWD/qmljscontext.h
+    $$PWD/qmljscontext.h \
+    $$PWD/qmljsscopechain.h
 
 SOURCES += \
     $$PWD/qmljsbind.cpp \
@@ -52,7 +53,8 @@ SOURCES += \
     $$PWD/qmljstypedescriptionreader.cpp \
     $$PWD/qmljsscopeastpath.cpp \
     $$PWD/qmljsvalueowner.cpp \
-    $$PWD/qmljscontext.cpp
+    $$PWD/qmljscontext.cpp \
+    $$PWD/qmljsscopechain.cpp
 
 RESOURCES += \
     $$PWD/qmljs.qrc
diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index 1a4bafb350559832f832fcf35e0ac4b1d5a1346e..149812bbbe885a7db9c451a62c9dc64ea3868d95 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -369,7 +369,7 @@ bool Bind::visit(VariableDeclaration *ast)
     if (! ast->name)
         return false;
 
-    ASTVariableReference *ref = new ASTVariableReference(ast, &_valueOwner);
+    ASTVariableReference *ref = new ASTVariableReference(ast, _doc, &_valueOwner);
     if (_currentObjectValue)
         _currentObjectValue->setMember(ast->name->asString(), ref);
     return true;
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 68849e1adc428dae23b936a0442125a7b35c35e5..8924bbaabb20e0632c792c96b328b566608e1f7d 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -365,17 +365,17 @@ private:
 } // end of anonymous namespace
 
 
-Check::Check(Document::Ptr doc, const Context *linkedContextNoScope)
+Check::Check(Document::Ptr doc, const Context *context)
     : _doc(doc)
-    , _context(*linkedContextNoScope)
-    , _scopeBuilder(&_context, doc)
+    , _context(*context)
+    , _scopeChain(doc, &_context)
+    , _scopeBuilder(&_scopeChain)
     , _options(WarnDangerousNonStrictEqualityChecks | WarnBlocks | WarnWith
           | WarnVoid | WarnCommaExpression | WarnExpressionStatement
           | WarnAssignInCondition | WarnUseBeforeDeclaration | WarnDuplicateDeclaration
           | WarnCaseWithoutFlowControlEnd | ErrCheckTypeErrors)
     , _lastValue(0)
 {
-    _scopeBuilder.initializeRootScope();
 }
 
 Check::~Check()
@@ -509,8 +509,7 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
         // suppress subsequent errors about scope object lookup by clearing
         // the scope object list
         // ### todo: better way?
-        _context.scopeChain().qmlScopeObjects.clear();
-        _context.scopeChain().update();
+        _scopeChain.setQmlScopeObjects(QList<const ObjectValue *>());
     }
 
     Node::accept(initializer, this);
@@ -565,7 +564,7 @@ bool Check::visit(UiScriptBinding *ast)
         if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(ast->statement)) {
             ExpressionNode *expr = expStmt->expression;
 
-            Evaluate evaluator(&_context);
+            Evaluate evaluator(&_scopeChain);
             const Value *rhsValue = evaluator(expr);
 
             const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(),
@@ -606,7 +605,7 @@ bool Check::visit(IdentifierExpression *ast)
 
     _lastValue = 0;
     if (ast->name) {
-        Evaluate evaluator(&_context);
+        Evaluate evaluator(&_scopeChain);
         _lastValue = evaluator.reference(ast);
         if (!_lastValue)
             error(ast->identifierToken, tr("unknown identifier"));
@@ -683,7 +682,7 @@ bool Check::visit(BinaryExpression *ast)
     if (ast->op == QSOperator::Equal || ast->op == QSOperator::NotEqual) {
         bool warn = _options & WarnAllNonStrictEqualityChecks;
         if (!warn && _options & WarnDangerousNonStrictEqualityChecks) {
-            Evaluate eval(&_context);
+            Evaluate eval(&_scopeChain);
             const Value *lhs = eval(ast->left);
             const Value *rhs = eval(ast->right);
             warn = shouldAvoidNonStrictEqualityCheck(ast->left, rhs)
@@ -850,7 +849,7 @@ bool Check::visit(DefaultClause *ast)
 /// ### Maybe put this into the context as a helper method.
 const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
 {
-    QList<const ObjectValue *> scopeObjects = _context.scopeChain().qmlScopeObjects;
+    QList<const ObjectValue *> scopeObjects = _scopeChain.qmlScopeObjects();
     if (scopeObjects.isEmpty())
         return 0;
 
@@ -869,7 +868,7 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
     bool isAttachedProperty = false;
     if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
         isAttachedProperty = true;
-        if (const ObjectValue *qmlTypes = _context.scopeChain().qmlTypes)
+        if (const ObjectValue *qmlTypes = _scopeChain.qmlTypes())
             scopeObjects += qmlTypes;
     }
 
diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h
index 5fb2c8bcce2029d9c087757b31d8c318c5775bbf..84a0977c566a7884506450445077765657a3e6ae 100644
--- a/src/libs/qmljs/qmljscheck.h
+++ b/src/libs/qmljs/qmljscheck.h
@@ -36,6 +36,7 @@
 #include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljscontext.h>
 #include <qmljs/qmljsscopebuilder.h>
+#include <qmljs/qmljsscopechain.h>
 #include <qmljs/parser/qmljsastvisitor_p.h>
 
 #include <QtCore/QCoreApplication>
@@ -52,7 +53,8 @@ class QMLJS_EXPORT Check: protected AST::Visitor
     typedef QSet<QString> StringSet;
 
 public:
-    Check(Document::Ptr doc, const Interpreter::Context *linkedContextNoScope);
+    // prefer taking root scope chain?
+    Check(Document::Ptr doc, const Interpreter::Context *context);
     virtual ~Check();
 
     QList<DiagnosticMessage> operator()();
@@ -127,6 +129,7 @@ private:
     Document::Ptr _doc;
 
     Interpreter::Context _context;
+    Interpreter::ScopeChain _scopeChain;
     ScopeBuilder _scopeBuilder;
 
     QList<DiagnosticMessage> _messages;
diff --git a/src/libs/qmljs/qmljscontext.cpp b/src/libs/qmljs/qmljscontext.cpp
index ab914cbfa9e534d177e5f3b974f538ce8634f38d..2d659c0ccbdb5b83759ddf3149e71aedb637ad14 100644
--- a/src/libs/qmljs/qmljscontext.cpp
+++ b/src/libs/qmljs/qmljscontext.cpp
@@ -41,9 +41,7 @@ using namespace QmlJS::Interpreter;
 Context::Context(const QmlJS::Snapshot &snapshot, ValueOwner *valueOwner, const ImportsPerDocument &imports)
     : _snapshot(snapshot),
       _valueOwner(valueOwner),
-      _imports(imports),
-      _qmlScopeObjectIndex(-1),
-      _qmlScopeObjectSet(false)
+      _imports(imports)
 {
 }
 
@@ -62,16 +60,6 @@ QmlJS::Snapshot Context::snapshot() const
     return _snapshot;
 }
 
-const ScopeChain &Context::scopeChain() const
-{
-    return _scopeChain;
-}
-
-ScopeChain &Context::scopeChain()
-{
-    return _scopeChain;
-}
-
 const Imports *Context::imports(const QmlJS::Document *doc) const
 {
     if (!doc)
@@ -79,24 +67,6 @@ const Imports *Context::imports(const QmlJS::Document *doc) const
     return _imports.value(doc).data();
 }
 
-const Value *Context::lookup(const QString &name, const ObjectValue **foundInScope) const
-{
-    QList<const ObjectValue *> scopes = _scopeChain.all();
-    for (int index = scopes.size() - 1; index != -1; --index) {
-        const ObjectValue *scope = scopes.at(index);
-
-        if (const Value *member = scope->lookupMember(name, this)) {
-            if (foundInScope)
-                *foundInScope = scope;
-            return member;
-        }
-    }
-
-    if (foundInScope)
-        *foundInScope = 0;
-    return _valueOwner->undefinedValue();
-}
-
 const ObjectValue *Context::lookupType(const QmlJS::Document *doc, UiQualifiedId *qmlTypeName,
                                        UiQualifiedId *qmlTypeNameEnd) const
 {
@@ -147,18 +117,8 @@ const ObjectValue *Context::lookupType(const QmlJS::Document *doc, const QString
 
 const Value *Context::lookupReference(const Value *value) const
 {
-    const Reference *reference = value_cast<const Reference *>(value);
-    if (!reference)
-        return value;
-
-    if (_referenceStack.contains(reference))
-        return 0;
-
-    _referenceStack.append(reference);
-    const Value *v = reference->value(this);
-    _referenceStack.removeLast();
-
-    return v;
+    ReferenceContext refContext(this);
+    return refContext.lookupReference(value);
 }
 
 QString Context::defaultPropertyName(const ObjectValue *object) const
@@ -176,3 +136,33 @@ QString Context::defaultPropertyName(const ObjectValue *object) const
     }
     return QString();
 }
+
+ReferenceContext::ReferenceContext(const Context *context)
+    : m_context(context)
+{}
+
+const Value *ReferenceContext::lookupReference(const Value *value)
+{
+    const Reference *reference = value_cast<const Reference *>(value);
+    if (!reference)
+        return value;
+
+    if (m_references.contains(reference))
+        return reference; // ### error
+
+    m_references.append(reference);
+    const Value *v = reference->value(this);
+    m_references.removeLast();
+
+    return v;
+}
+
+const Context *ReferenceContext::context() const
+{
+    return m_context;
+}
+
+ReferenceContext::operator const Context *() const
+{
+    return m_context;
+}
diff --git a/src/libs/qmljs/qmljscontext.h b/src/libs/qmljs/qmljscontext.h
index bd5c4cf03d539efeb930a9076dd91049f2003183..5d28c5872a94068aeec2eae8907c1c35288c944a 100644
--- a/src/libs/qmljs/qmljscontext.h
+++ b/src/libs/qmljs/qmljscontext.h
@@ -45,9 +45,12 @@ class Snapshot;
 
 namespace Interpreter {
 
+// shared among threads, completely threadsafe
+// currently also safe to copy, but will be deprecated
 class QMLJS_EXPORT Context
 {
 public:
+    typedef QSharedPointer<Context> Ptr;
     typedef QHash<const Document *, QSharedPointer<const Imports> > ImportsPerDocument;
 
     // Context takes ownership of valueOwner
@@ -57,12 +60,8 @@ public:
     ValueOwner *valueOwner() const;
     Snapshot snapshot() const;
 
-    const ScopeChain &scopeChain() const;
-    ScopeChain &scopeChain();
-
     const Imports *imports(const Document *doc) const;
 
-    const Value *lookup(const QString &name, const ObjectValue **foundInScope = 0) const;
     const ObjectValue *lookupType(const Document *doc, AST::UiQualifiedId *qmlTypeName,
                                   AST::UiQualifiedId *qmlTypeNameEnd = 0) const;
     const ObjectValue *lookupType(const Document *doc, const QStringList &qmlTypeName) const;
@@ -71,19 +70,29 @@ public:
     QString defaultPropertyName(const ObjectValue *object) const;
 
 private:
-    typedef QHash<QString, const Value *> Properties;
-
     Snapshot _snapshot;
     QSharedPointer<ValueOwner> _valueOwner;
     ImportsPerDocument _imports;
-    ScopeChain _scopeChain;
-    int _qmlScopeObjectIndex;
-    bool _qmlScopeObjectSet;
+};
+
+// for looking up references
+class QMLJS_EXPORT ReferenceContext
+{
+public:
+    // implicit conversion ok
+    ReferenceContext(const Context *context);
+
+    const Value *lookupReference(const Value *value);
+
+    const Context *context() const;
+    operator const Context *() const;
 
-    // for avoiding reference cycles during lookup
-    mutable QList<const Reference *> _referenceStack;
+private:
+    const Context *m_context;
+    QList<const Reference *> m_references;
 };
 
+
 } // namespace Interpreter
 } // namespace QmlJS
 
diff --git a/src/libs/qmljs/qmljsevaluate.cpp b/src/libs/qmljs/qmljsevaluate.cpp
index 410d3d3a38369187b4db8cc81188cf11c12f707a..973144fbd5e799b08ae97a68cb438313a91083c0 100644
--- a/src/libs/qmljs/qmljsevaluate.cpp
+++ b/src/libs/qmljs/qmljsevaluate.cpp
@@ -33,15 +33,17 @@
 #include "qmljsevaluate.h"
 #include "qmljscontext.h"
 #include "qmljsvalueowner.h"
+#include "qmljsscopechain.h"
 #include "parser/qmljsast_p.h"
 #include <QtCore/QDebug>
 
 using namespace QmlJS;
 using namespace QmlJS::Interpreter;
 
-Evaluate::Evaluate(const Context *context)
-    : _valueOwner(context->valueOwner()),
-      _context(context),
+Evaluate::Evaluate(const ScopeChain *scopeChain)
+    : _valueOwner(scopeChain->context()->valueOwner()),
+      _context(scopeChain->context()),
+      _scopeChain(scopeChain),
       _scope(_valueOwner->globalObject()),
       _result(0)
 {
@@ -165,7 +167,7 @@ bool Evaluate::visit(AST::UiQualifiedId *ast)
     if (! ast->name)
          return false;
 
-    const Value *value = _context->lookup(ast->name->asString());
+    const Value *value = _scopeChain->lookup(ast->name->asString());
     if (! ast->next) {
         _result = value;
 
@@ -213,7 +215,7 @@ bool Evaluate::visit(AST::IdentifierExpression *ast)
     if (! ast->name)
         return false;
 
-    _result = _context->lookup(ast->name->asString());
+    _result = _scopeChain->lookup(ast->name->asString());
     return false;
 }
 
diff --git a/src/libs/qmljs/qmljsevaluate.h b/src/libs/qmljs/qmljsevaluate.h
index b7fc24fabe36f0f9a2aa74cf757b804a9f455871..d7316449bde2679e7116dd7349f716706e91fe76 100644
--- a/src/libs/qmljs/qmljsevaluate.h
+++ b/src/libs/qmljs/qmljsevaluate.h
@@ -35,6 +35,7 @@
 
 #include "parser/qmljsastvisitor_p.h"
 #include "qmljsdocument.h"
+#include "qmljsscopechain.h"
 
 namespace QmlJS {
 
@@ -49,7 +50,7 @@ namespace Interpreter {
 class QMLJS_EXPORT Evaluate: protected AST::Visitor
 {
 public:
-    Evaluate(const Interpreter::Context *context);
+    Evaluate(const Interpreter::ScopeChain *scopeChain);
     virtual ~Evaluate();
 
     // same as value()
@@ -165,6 +166,7 @@ private:
     QmlJS::Document::Ptr _doc;
     Interpreter::ValueOwner *_valueOwner;
     const Interpreter::Context *_context;
+    const Interpreter::ScopeChain *_scopeChain;
     const Interpreter::ObjectValue *_scope;
     const Interpreter::Value *_result;
 };
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 1002f96162ea47794b7a6e8cc5835007dc4733b0..d44c6065fd3411d4dd369db5e0d73bb9abaea546 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -35,8 +35,9 @@
 #include "qmljslink.h"
 #include "qmljsbind.h"
 #include "qmljsscopebuilder.h"
-#include "qmljstypedescriptionreader.h"
+#include "qmljsscopechain.h"
 #include "qmljsscopeastpath.h"
+#include "qmljstypedescriptionreader.h"
 #include "qmljsvalueowner.h"
 #include "qmljscontext.h"
 #include "parser/qmljsast_p.h"
@@ -688,82 +689,6 @@ void StringValue::accept(ValueVisitor *visitor) const
     visitor->visit(this);
 }
 
-
-ScopeChain::ScopeChain()
-    : globalScope(0)
-    , qmlTypes(0)
-    , jsImports(0)
-{
-}
-
-ScopeChain::QmlComponentChain::QmlComponentChain()
-{
-}
-
-ScopeChain::QmlComponentChain::~QmlComponentChain()
-{
-    qDeleteAll(instantiatingComponents);
-}
-
-void ScopeChain::QmlComponentChain::clear()
-{
-    qDeleteAll(instantiatingComponents);
-    instantiatingComponents.clear();
-    document = Document::Ptr(0);
-}
-
-void ScopeChain::QmlComponentChain::collect(QList<const ObjectValue *> *list) const
-{
-    foreach (const QmlComponentChain *parent, instantiatingComponents)
-        parent->collect(list);
-
-    if (!document)
-        return;
-
-    if (ObjectValue *root = document->bind()->rootObjectValue())
-        list->append(root);
-    if (ObjectValue *ids = document->bind()->idEnvironment())
-        list->append(ids);
-}
-
-void ScopeChain::update()
-{
-    _all.clear();
-
-    _all += globalScope;
-
-    // the root scope in js files doesn't see instantiating components
-    if (jsScopes.count() != 1 || !qmlScopeObjects.isEmpty()) {
-        if (qmlComponentScope) {
-            foreach (const QmlComponentChain *parent, qmlComponentScope->instantiatingComponents)
-                parent->collect(&_all);
-        }
-    }
-
-    ObjectValue *root = 0;
-    ObjectValue *ids = 0;
-    if (qmlComponentScope && qmlComponentScope->document) {
-        root = qmlComponentScope->document->bind()->rootObjectValue();
-        ids = qmlComponentScope->document->bind()->idEnvironment();
-    }
-
-    if (root && !qmlScopeObjects.contains(root))
-        _all += root;
-    _all += qmlScopeObjects;
-    if (ids)
-        _all += ids;
-    if (qmlTypes)
-        _all += qmlTypes;
-    if (jsImports)
-        _all += jsImports;
-    _all += jsScopes;
-}
-
-QList<const ObjectValue *> ScopeChain::all() const
-{
-    return _all;
-}
-
 Reference::Reference(ValueOwner *valueOwner)
     : _valueOwner(valueOwner)
 {
@@ -789,7 +714,7 @@ void Reference::accept(ValueVisitor *visitor) const
     visitor->visit(this);
 }
 
-const Value *Reference::value(const Context *) const
+const Value *Reference::value(const ReferenceContext *) const
 {
     return _valueOwner->undefinedValue();
 }
@@ -1771,8 +1696,10 @@ const QmlJS::Document *ASTObjectValue::document() const
     return _doc;
 }
 
-ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, ValueOwner *valueOwner)
-    : Reference(valueOwner), _ast(ast)
+ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, const QmlJS::Document *doc, ValueOwner *valueOwner)
+    : Reference(valueOwner)
+    , _ast(ast)
+    , _doc(doc)
 {
 }
 
@@ -1780,10 +1707,18 @@ ASTVariableReference::~ASTVariableReference()
 {
 }
 
-const Value *ASTVariableReference::value(const Context *context) const
+const Value *ASTVariableReference::value(const ReferenceContext *referenceContext) const
 {
-    Evaluate check(context);
-    return check(_ast->expression);
+    if (!_ast->expression)
+        return valueOwner()->undefinedValue();
+
+    Document::Ptr doc = _doc->ptr();
+    ScopeChain scopeChain(doc, referenceContext->context());
+    QmlJS::ScopeBuilder builder(&scopeChain);
+    builder.push(QmlJS::ScopeAstPath(doc)(_ast->expression->firstSourceLocation().begin()));
+
+    QmlJS::Evaluate evaluator(&scopeChain);
+    return evaluator(_ast->expression);
 }
 
 ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const QmlJS::Document *doc, ValueOwner *valueOwner)
@@ -1859,9 +1794,9 @@ UiQualifiedId *QmlPrototypeReference::qmlTypeName() const
     return _qmlTypeName;
 }
 
-const Value *QmlPrototypeReference::value(const Context *context) const
+const Value *QmlPrototypeReference::value(const ReferenceContext *referenceContext) const
 {
-    return context->lookupType(_doc, _qmlTypeName);
+    return referenceContext->context()->lookupType(_doc, _qmlTypeName);
 }
 
 ASTPropertyReference::ASTPropertyReference(UiPublicMember *ast, const QmlJS::Document *doc, ValueOwner *valueOwner)
@@ -1886,7 +1821,7 @@ bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *
     return true;
 }
 
-const Value *ASTPropertyReference::value(const Context *context) const
+const Value *ASTPropertyReference::value(const ReferenceContext *referenceContext) const
 {
     if (_ast->statement
             && (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant")
@@ -1896,15 +1831,14 @@ const Value *ASTPropertyReference::value(const Context *context) const
         // ### Improve efficiency by caching the 'use chain' constructed in ScopeBuilder.
 
         QmlJS::Document::Ptr doc = _doc->ptr();
-        Context localContext(*context);
-        QmlJS::ScopeBuilder builder(&localContext, doc);
-        builder.initializeRootScope();
+        ScopeChain scopeChain(doc, referenceContext->context());
+        QmlJS::ScopeBuilder builder(&scopeChain);
 
         int offset = _ast->statement->firstSourceLocation().begin();
         builder.push(ScopeAstPath(doc)(offset));
 
-        Evaluate check(&localContext);
-        return check(_ast->statement);
+        QmlJS::Evaluate evaluator(&scopeChain);
+        return evaluator(_ast->statement);
     }
 
     if (_ast->memberType)
@@ -1934,7 +1868,7 @@ bool ASTSignalReference::getSourceLocation(QString *fileName, int *line, int *co
     return true;
 }
 
-const Value *ASTSignalReference::value(const Context *) const
+const Value *ASTSignalReference::value(const ReferenceContext *) const
 {
     return valueOwner()->undefinedValue();
 }
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 85a49a5ee6aa2ca551ac9e2d8a21d03191f94171..c88e7aaa7939cc47a7d0a0d469f6c52f91cb41eb 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -75,6 +75,7 @@ class Imports;
 class TypeScope;
 class JSImportScope;
 class Context;
+class ReferenceContext;
 
 typedef QList<const Value *> ValueList;
 
@@ -283,40 +284,6 @@ public:
     virtual bool processGeneratedSlot(const QString &name, const Value *value);
 };
 
-class QMLJS_EXPORT ScopeChain
-{
-public:
-    ScopeChain();
-
-    class QMLJS_EXPORT QmlComponentChain
-    {
-        Q_DISABLE_COPY(QmlComponentChain)
-    public:
-        QmlComponentChain();
-        ~QmlComponentChain();
-
-        QList<const QmlComponentChain *> instantiatingComponents;
-        Document::Ptr document;
-
-        void collect(QList<const ObjectValue *> *list) const;
-        void clear();
-    };
-
-    const ObjectValue *globalScope;
-    QSharedPointer<const QmlComponentChain> qmlComponentScope;
-    QList<const ObjectValue *> qmlScopeObjects;
-    const TypeScope *qmlTypes;
-    const JSImportScope *jsImports;
-    QList<const ObjectValue *> jsScopes;
-
-    // rebuilds the flat list of all scopes
-    void update();
-    QList<const ObjectValue *> all() const;
-
-private:
-    QList<const ObjectValue *> _all;
-};
-
 class QMLJS_EXPORT Reference: public Value
 {
 public:
@@ -330,10 +297,10 @@ public:
     virtual void accept(ValueVisitor *) const;
 
 private:
-    virtual const Value *value(const Context *context) const;
+    virtual const Value *value(const ReferenceContext *referenceContext) const;
 
     ValueOwner *_valueOwner;
-    friend class Context;
+    friend class ReferenceContext;
 };
 
 class QMLJS_EXPORT ColorValue: public Value
@@ -724,7 +691,7 @@ public:
     AST::UiQualifiedId *qmlTypeName() const;
 
 private:    
-    virtual const Value *value(const Context *context) const;
+    virtual const Value *value(const ReferenceContext *referenceContext) const;
 
     AST::UiQualifiedId *_qmlTypeName;
     const Document *_doc;
@@ -733,13 +700,14 @@ private:
 class QMLJS_EXPORT ASTVariableReference: public Reference
 {
     AST::VariableDeclaration *_ast;
+    const Document *_doc;
 
 public:
-    ASTVariableReference(AST::VariableDeclaration *ast, ValueOwner *valueOwner);
+    ASTVariableReference(AST::VariableDeclaration *ast, const Document *doc, ValueOwner *valueOwner);
     virtual ~ASTVariableReference();
 
 private:
-    virtual const Value *value(const Context *context) const;
+    virtual const Value *value(const ReferenceContext *referenceContext) const;
 };
 
 class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
@@ -779,7 +747,7 @@ public:
     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
 
 private:
-    virtual const Value *value(const Context *context) const;
+    virtual const Value *value(const ReferenceContext *referenceContext) const;
 };
 
 class QMLJS_EXPORT ASTSignalReference: public Reference
@@ -798,7 +766,7 @@ public:
     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
 
 private:
-    virtual const Value *value(const Context *context) const;
+    virtual const Value *value(const ReferenceContext *referenceContext) const;
 };
 
 class QMLJS_EXPORT ASTObjectValue: public ObjectValue
diff --git a/src/libs/qmljs/qmljslookupcontext.cpp b/src/libs/qmljs/qmljslookupcontext.cpp
index 04cc68938f79bf31c4172d53c48091870b68bd8e..389a23fb86cdfb643599e001c54a34de7f00ce0b 100644
--- a/src/libs/qmljs/qmljslookupcontext.cpp
+++ b/src/libs/qmljs/qmljslookupcontext.cpp
@@ -36,6 +36,7 @@
 #include "qmljsscopebuilder.h"
 #include "qmljsmodelmanagerinterface.h"
 #include "qmljsevaluate.h"
+#include "qmljsscopechain.h"
 
 using namespace QmlJS;
 
@@ -47,26 +48,26 @@ public:
         , context(Link(snapshot,
                        ModelManagerInterface::instance()->importPaths(),
                        ModelManagerInterface::instance()->builtins(doc))())
+        , scopeChain(doc, &context)
     {
-        ScopeBuilder scopeBuilder(&context, doc);
-        scopeBuilder.initializeRootScope();
+        ScopeBuilder scopeBuilder(&scopeChain);
         scopeBuilder.push(path);
     }
 
     LookupContextData(Document::Ptr doc,
-                      const Interpreter::Context &contextWithoutScope,
+                      const Interpreter::Context &context,
                       const QList<AST::Node *> &path)
         : doc(doc)
-        , context(contextWithoutScope)
+        , context(context)
+        , scopeChain(doc, &context)
     {
-        ScopeBuilder scopeBuilder(&context, doc);
-        scopeBuilder.initializeRootScope();
+        ScopeBuilder scopeBuilder(&scopeChain);
         scopeBuilder.push(path);
     }
 
     Document::Ptr doc;
     Interpreter::Context context;
-    // snapshot is in context
+    Interpreter::ScopeChain scopeChain;
 };
 
 LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
@@ -75,9 +76,9 @@ LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const
 }
 
 LookupContext::LookupContext(const Document::Ptr doc,
-                             const Interpreter::Context &contextWithoutScope,
+                             const Interpreter::Context &context,
                              const QList<AST::Node *> &path)
-    : d(new LookupContextData(doc, contextWithoutScope, path))
+    : d(new LookupContextData(doc, context, path))
 {
 }
 
@@ -92,16 +93,16 @@ LookupContext::Ptr LookupContext::create(Document::Ptr doc, const Snapshot &snap
 }
 
 LookupContext::Ptr LookupContext::create(const Document::Ptr doc,
-                                         const Interpreter::Context &linkedContextWithoutScope,
+                                         const Interpreter::Context &context,
                                          const QList<AST::Node *> &path)
 {
-    Ptr ptr(new LookupContext(doc, linkedContextWithoutScope, path));
+    Ptr ptr(new LookupContext(doc, context, path));
     return ptr;
 }
 
 const Interpreter::Value *LookupContext::evaluate(AST::Node *node) const
 {
-    Evaluate check(&d->context);
+    Evaluate check(&d->scopeChain);
     return check(node);
 }
 
@@ -126,3 +127,8 @@ const Interpreter::Context *LookupContext::context() const
 {
     return &d->context;
 }
+
+const Interpreter::ScopeChain &LookupContext::scopeChain() const
+{
+    return d->scopeChain;
+}
diff --git a/src/libs/qmljs/qmljslookupcontext.h b/src/libs/qmljs/qmljslookupcontext.h
index ce4199e092193f10c29ef22885bf117416c4116d..f71ae8028475542265a2121b9d43f85e3a3a2d64 100644
--- a/src/libs/qmljs/qmljslookupcontext.h
+++ b/src/libs/qmljs/qmljslookupcontext.h
@@ -47,6 +47,7 @@ class LookupContextData;
 namespace Interpreter {
 class Value;
 class Context;
+class ScopeChain;
 }
 
 class QMLJS_EXPORT LookupContext
@@ -55,7 +56,7 @@ class QMLJS_EXPORT LookupContext
 
     LookupContext(const Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path);
     LookupContext(const Document::Ptr doc,
-                  const Interpreter::Context &linkedContextWithoutScope,
+                  const Interpreter::Context &context,
                   const QList<AST::Node *> &path);
 
 public:
@@ -67,7 +68,7 @@ public:
     static Ptr create(const Document::Ptr doc, const Snapshot &snapshot,
                       const QList<AST::Node *> &path);
     static Ptr create(const Document::Ptr doc,
-                      const Interpreter::Context &linkedContextWithoutScope,
+                      const Interpreter::Context &context,
                       const QList<AST::Node *> &path);
 
     const Interpreter::Value *evaluate(AST::Node *node) const;
@@ -76,6 +77,7 @@ public:
     Snapshot snapshot() const;
     Interpreter::ValueOwner *valueOwner() const;
     const Interpreter::Context *context() const;
+    const Interpreter::ScopeChain &scopeChain() const;
 
 private:
     QScopedPointer<LookupContextData> d;
diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp
index 10f18e6a803eb70b14839f8ada64476f433e5303..90e97502df3ce04e9ad7c7169b4a3a29f90863e3 100644
--- a/src/libs/qmljs/qmljsscopebuilder.cpp
+++ b/src/libs/qmljs/qmljsscopebuilder.cpp
@@ -35,15 +35,15 @@
 #include "qmljsbind.h"
 #include "qmljscontext.h"
 #include "qmljsevaluate.h"
+#include "qmljsscopechain.h"
 #include "parser/qmljsast_p.h"
 
 using namespace QmlJS;
 using namespace QmlJS::Interpreter;
 using namespace QmlJS::AST;
 
-ScopeBuilder::ScopeBuilder(Context *context, Document::Ptr doc)
-    : _doc(doc)
-    , _context(context)
+ScopeBuilder::ScopeBuilder(ScopeChain *scopeChain)
+    : _scopeChain(scopeChain)
 {
 }
 
@@ -69,16 +69,17 @@ void ScopeBuilder::push(AST::Node *node)
     case Node::Kind_FunctionExpression:
     case Node::Kind_UiPublicMember:
     {
-        ObjectValue *scope = _doc->bind()->findAttachedJSScope(node);
-        if (scope)
-            _context->scopeChain().jsScopes += scope;
+        ObjectValue *scope = _scopeChain->document()->bind()->findAttachedJSScope(node);
+        if (scope) {
+            QList<const ObjectValue *> jsScopes = _scopeChain->jsScopes();
+            jsScopes += scope;
+            _scopeChain->setJsScopes(jsScopes);
+        }
         break;
     }
     default:
         break;
     }
-
-    _context->scopeChain().update();
 }
 
 void ScopeBuilder::push(const QList<AST::Node *> &nodes)
@@ -99,9 +100,14 @@ void ScopeBuilder::pop()
     case Node::Kind_FunctionExpression:
     case Node::Kind_UiPublicMember:
     {
-        ObjectValue *scope = _doc->bind()->findAttachedJSScope(toRemove);
-        if (scope)
-            _context->scopeChain().jsScopes.removeLast();
+        ObjectValue *scope = _scopeChain->document()->bind()->findAttachedJSScope(toRemove);
+        if (scope) {
+            QList<const ObjectValue *> jsScopes = _scopeChain->jsScopes();
+            if (!jsScopes.isEmpty()) {
+                jsScopes.removeLast();
+                _scopeChain->setJsScopes(jsScopes);
+            }
+        }
         break;
     }
     default:
@@ -112,103 +118,12 @@ void ScopeBuilder::pop()
     if (! _nodes.isEmpty()
         && (cast<UiObjectDefinition *>(toRemove) || cast<UiObjectBinding *>(toRemove)))
         setQmlScopeObject(_nodes.last());
-
-    _context->scopeChain().update();
-}
-
-void ScopeBuilder::initializeRootScope()
-{
-    ScopeChain &scopeChain = _context->scopeChain();
-    if (scopeChain.qmlComponentScope
-            && scopeChain.qmlComponentScope->document == _doc) {
-        return;
-    }
-
-    scopeChain = ScopeChain(); // reset
-
-    Interpreter::ValueOwner *valueOwner = _context->valueOwner();
-
-    // ### TODO: This object ought to contain the global namespace additions by QML.
-    scopeChain.globalScope = valueOwner->globalObject();
-
-    if (! _doc) {
-        scopeChain.update();
-        return;
-    }
-
-    Bind *bind = _doc->bind();
-    QHash<Document *, ScopeChain::QmlComponentChain *> componentScopes;
-    const Snapshot &snapshot = _context->snapshot();
-
-    ScopeChain::QmlComponentChain *chain = new ScopeChain::QmlComponentChain;
-    scopeChain.qmlComponentScope = QSharedPointer<const ScopeChain::QmlComponentChain>(chain);
-    if (_doc->qmlProgram()) {
-        componentScopes.insert(_doc.data(), chain);
-        makeComponentChain(_doc, snapshot, chain, &componentScopes);
-
-        if (const Imports *imports = _context->imports(_doc.data())) {
-            scopeChain.qmlTypes = imports->typeScope();
-            scopeChain.jsImports = imports->jsImportScope();
-        }
-    } else {
-        // add scope chains for all components that import this file
-        foreach (Document::Ptr otherDoc, snapshot) {
-            foreach (const ImportInfo &import, otherDoc->bind()->imports()) {
-                if (import.type() == ImportInfo::FileImport && _doc->fileName() == import.name()) {
-                    ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain;
-                    componentScopes.insert(otherDoc.data(), component);
-                    chain->instantiatingComponents += component;
-                    makeComponentChain(otherDoc, snapshot, component, &componentScopes);
-                }
-            }
-        }
-
-        // ### TODO: Which type environment do scripts see?
-
-        if (bind->rootObjectValue())
-            scopeChain.jsScopes += bind->rootObjectValue();
-    }
-
-    scopeChain.update();
-}
-
-void ScopeBuilder::makeComponentChain(
-        Document::Ptr doc,
-        const Snapshot &snapshot,
-        ScopeChain::QmlComponentChain *target,
-        QHash<Document *, ScopeChain::QmlComponentChain *> *components)
-{
-    if (!doc->qmlProgram())
-        return;
-
-    Bind *bind = doc->bind();
-
-    // add scopes for all components instantiating this one
-    foreach (Document::Ptr otherDoc, snapshot) {
-        if (otherDoc == doc)
-            continue;
-        if (otherDoc->bind()->usesQmlPrototype(bind->rootObjectValue(), _context)) {
-            if (components->contains(otherDoc.data())) {
-//                target->instantiatingComponents += components->value(otherDoc.data());
-            } else {
-                ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain;
-                components->insert(otherDoc.data(), component);
-                target->instantiatingComponents += component;
-
-                makeComponentChain(otherDoc, snapshot, component, components);
-            }
-        }
-    }
-
-    // build this component scope
-    target->document = doc;
 }
 
 void ScopeBuilder::setQmlScopeObject(Node *node)
 {
-    ScopeChain &scopeChain = _context->scopeChain();
-
-    if (_doc->bind()->isGroupedPropertyBinding(node)) {
+    QList<const ObjectValue *> qmlScopeObjects;
+    if (_scopeChain->document()->bind()->isGroupedPropertyBinding(node)) {
         UiObjectDefinition *definition = cast<UiObjectDefinition *>(node);
         if (!definition)
             return;
@@ -219,21 +134,21 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
         if (!object)
             return;
 
-        scopeChain.qmlScopeObjects.clear();
-        scopeChain.qmlScopeObjects += object;
+        qmlScopeObjects += object;
+        _scopeChain->setQmlScopeObjects(qmlScopeObjects);
+        return;
     }
 
-    const ObjectValue *scopeObject = _doc->bind()->findQmlObject(node);
+    const ObjectValue *scopeObject = _scopeChain->document()->bind()->findQmlObject(node);
     if (scopeObject) {
-        scopeChain.qmlScopeObjects.clear();
-        scopeChain.qmlScopeObjects += scopeObject;
+        qmlScopeObjects += scopeObject;
     } else {
         return; // Probably syntax errors, where we're working with a "recovered" AST.
     }
 
     // check if the object has a Qt.ListElement or Qt.Connections ancestor
     // ### allow only signal bindings for Connections
-    PrototypeIterator iter(scopeObject, _context);
+    PrototypeIterator iter(scopeObject, _scopeChain->context());
     iter.next();
     while (iter.hasNext()) {
         const ObjectValue *prototype = iter.next();
@@ -242,15 +157,15 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
                     || qmlMetaObject->className() == QLatin1String("Connections")
                     ) && (qmlMetaObject->packageName() == QLatin1String("Qt")
                           || qmlMetaObject->packageName() == QLatin1String("QtQuick"))) {
-                scopeChain.qmlScopeObjects.clear();
+                qmlScopeObjects.clear();
                 break;
             }
         }
     }
 
     // check if the object has a Qt.PropertyChanges ancestor
-    const ObjectValue *prototype = scopeObject->prototype(_context);
-    prototype = isPropertyChangesObject(_context, prototype);
+    const ObjectValue *prototype = scopeObject->prototype(_scopeChain->context());
+    prototype = isPropertyChangesObject(_scopeChain->context(), prototype);
     // find the target script binding
     if (prototype) {
         UiObjectInitializer *initializer = 0;
@@ -264,31 +179,33 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
                     if (scriptBinding->qualifiedId && scriptBinding->qualifiedId->name
                             && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
                             && ! scriptBinding->qualifiedId->next) {
-                        Evaluate evaluator(_context);
+                        Evaluate evaluator(_scopeChain);
                         const Value *targetValue = evaluator(scriptBinding->statement);
 
                         if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
-                            scopeChain.qmlScopeObjects.prepend(target);
+                            qmlScopeObjects.prepend(target);
                         } else {
-                            scopeChain.qmlScopeObjects.clear();
+                            qmlScopeObjects.clear();
                         }
                     }
                 }
             }
         }
     }
+
+    _scopeChain->setQmlScopeObjects(qmlScopeObjects);
 }
 
 const Value *ScopeBuilder::scopeObjectLookup(AST::UiQualifiedId *id)
 {
     // do a name lookup on the scope objects
     const Value *result = 0;
-    foreach (const ObjectValue *scopeObject, _context->scopeChain().qmlScopeObjects) {
+    foreach (const ObjectValue *scopeObject, _scopeChain->qmlScopeObjects()) {
         const ObjectValue *object = scopeObject;
         for (UiQualifiedId *it = id; it; it = it->next) {
             if (!it->name)
                 return 0;
-            result = object->lookupMember(it->name->asString(), _context);
+            result = object->lookupMember(it->name->asString(), _scopeChain->context());
             if (!result)
                 break;
             if (it->next) {
diff --git a/src/libs/qmljs/qmljsscopebuilder.h b/src/libs/qmljs/qmljsscopebuilder.h
index c565a55e12997adfa551102ae5a0f5c222364a2a..34982da9a8e241b6a68e0c3afc46718e190376d4 100644
--- a/src/libs/qmljs/qmljsscopebuilder.h
+++ b/src/libs/qmljs/qmljsscopebuilder.h
@@ -34,12 +34,19 @@
 #define QMLJSSCOPEBUILDER_H
 
 #include <qmljs/qmljsdocument.h>
-#include <qmljs/qmljsinterpreter.h>
 
 #include <QtCore/QList>
 
 namespace QmlJS {
 
+namespace Interpreter {
+class QmlComponentChain;
+class Context;
+class ObjectValue;
+class Value;
+class ScopeChain;
+}
+
 namespace AST {
     class Node;
 }
@@ -47,11 +54,9 @@ namespace AST {
 class QMLJS_EXPORT ScopeBuilder
 {
 public:
-    ScopeBuilder(Interpreter::Context *context, Document::Ptr doc);
+    ScopeBuilder(Interpreter::ScopeChain *scopeChain);
     ~ScopeBuilder();
 
-    void initializeRootScope();
-
     void push(AST::Node *node);
     void push(const QList<AST::Node *> &nodes);
     void pop();
@@ -59,15 +64,10 @@ public:
     static const Interpreter::ObjectValue *isPropertyChangesObject(const Interpreter::Context *context, const Interpreter::ObjectValue *object);
 
 private:
-    void makeComponentChain(Document::Ptr doc, const Snapshot &snapshot,
-                            Interpreter::ScopeChain::QmlComponentChain *target,
-                            QHash<Document *, Interpreter::ScopeChain::QmlComponentChain *> *components);
-
     void setQmlScopeObject(AST::Node *node);
     const Interpreter::Value *scopeObjectLookup(AST::UiQualifiedId *id);
 
-    Document::Ptr _doc;
-    Interpreter::Context *_context;
+    Interpreter::ScopeChain *_scopeChain;
     QList<AST::Node *> _nodes;
 };
 
diff --git a/src/libs/qmljs/qmljsscopechain.cpp b/src/libs/qmljs/qmljsscopechain.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2b5cda90f8365cdae347770cd2db4680a48e70ce
--- /dev/null
+++ b/src/libs/qmljs/qmljsscopechain.cpp
@@ -0,0 +1,291 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#include "qmljsscopechain.h"
+#include "qmljsbind.h"
+
+using namespace QmlJS;
+using namespace QmlJS::Interpreter;
+
+QmlComponentChain::QmlComponentChain(const Document::Ptr &document)
+    : m_document(document)
+{
+}
+
+QmlComponentChain::~QmlComponentChain()
+{
+    qDeleteAll(m_instantiatingComponents);
+}
+
+Document::Ptr QmlComponentChain::document() const
+{
+    return m_document;
+}
+
+QList<const QmlComponentChain *> QmlComponentChain::instantiatingComponents() const
+{
+    return m_instantiatingComponents;
+}
+
+void QmlComponentChain::addInstantiatingComponent(const QmlComponentChain *component)
+{
+    m_instantiatingComponents.append(component);
+}
+
+
+ScopeChain::ScopeChain(const Document::Ptr &document, const Context *context)
+    : m_document(document)
+    , m_context(context)
+    , m_globalScope(0)
+    , m_qmlTypes(0)
+    , m_jsImports(0)
+    , m_modified(false)
+{
+    initializeRootScope();
+}
+
+Document::Ptr ScopeChain::document() const
+{
+    return m_document;
+}
+
+const Context *ScopeChain::context() const
+{
+    return m_context;
+}
+
+const Value * ScopeChain::lookup(const QString &name, const ObjectValue **foundInScope) const
+{
+    QList<const ObjectValue *> scopes = all();
+    for (int index = scopes.size() - 1; index != -1; --index) {
+        const ObjectValue *scope = scopes.at(index);
+
+        if (const Value *member = scope->lookupMember(name, m_context)) {
+            if (foundInScope)
+                *foundInScope = scope;
+            return member;
+        }
+    }
+
+    if (foundInScope)
+        *foundInScope = 0;
+    return m_context->valueOwner()->undefinedValue();
+}
+
+const ObjectValue *ScopeChain::globalScope() const
+{
+    return m_globalScope;
+}
+
+void ScopeChain::setGlobalScope(const ObjectValue *globalScope)
+{
+    m_modified = true;
+    m_globalScope = globalScope;
+}
+
+QSharedPointer<const QmlComponentChain> ScopeChain::qmlComponentChain() const
+{
+    return m_qmlComponentScope;
+}
+
+void ScopeChain::setQmlComponentChain(const QSharedPointer<const QmlComponentChain> &qmlComponentChain)
+{
+    m_modified = true;
+    m_qmlComponentScope = qmlComponentChain;
+}
+
+QList<const ObjectValue *> ScopeChain::qmlScopeObjects() const
+{
+    return m_qmlScopeObjects;
+}
+
+void ScopeChain::setQmlScopeObjects(const QList<const ObjectValue *> &qmlScopeObjects)
+{
+    m_modified = true;
+    m_qmlScopeObjects = qmlScopeObjects;
+}
+
+const TypeScope *ScopeChain::qmlTypes() const
+{
+    return m_qmlTypes;
+}
+
+void ScopeChain::setQmlTypes(const TypeScope *qmlTypes)
+{
+    m_modified = true;
+    m_qmlTypes = qmlTypes;
+}
+
+const JSImportScope *ScopeChain::jsImports() const
+{
+    return m_jsImports;
+}
+
+void ScopeChain::setJsImports(const JSImportScope *jsImports)
+{
+    m_modified = true;
+    m_jsImports = jsImports;
+}
+
+QList<const ObjectValue *> ScopeChain::jsScopes() const
+{
+    return m_jsScopes;
+}
+
+void ScopeChain::setJsScopes(const QList<const ObjectValue *> &jsScopes)
+{
+    m_modified = true;
+    m_jsScopes = jsScopes;
+}
+
+QList<const ObjectValue *> ScopeChain::all() const
+{
+    if (m_modified)
+        update();
+    return m_all;
+}
+
+static void collectScopes(const QmlComponentChain *chain, QList<const ObjectValue *> *target)
+{
+    foreach (const QmlComponentChain *parent, chain->instantiatingComponents())
+        collectScopes(parent, target);
+
+    if (!chain->document())
+        return;
+
+    if (ObjectValue *root = chain->document()->bind()->rootObjectValue())
+        target->append(root);
+    if (ObjectValue *ids = chain->document()->bind()->idEnvironment())
+        target->append(ids);
+}
+
+void ScopeChain::update() const
+{
+    m_all.clear();
+
+    m_all += m_globalScope;
+
+    // the root scope in js files doesn't see instantiating components
+    if (m_jsScopes.count() != 1 || !m_qmlScopeObjects.isEmpty()) {
+        if (m_qmlComponentScope) {
+            foreach (const QmlComponentChain *parent, m_qmlComponentScope->instantiatingComponents())
+                collectScopes(parent, &m_all);
+        }
+    }
+
+    ObjectValue *root = 0;
+    ObjectValue *ids = 0;
+    if (m_qmlComponentScope && m_qmlComponentScope->document()) {
+        const Bind *bind = m_qmlComponentScope->document()->bind();
+        root = bind->rootObjectValue();
+        ids = bind->idEnvironment();
+    }
+
+    if (root && !m_qmlScopeObjects.contains(root))
+        m_all += root;
+    m_all += m_qmlScopeObjects;
+    if (ids)
+        m_all += ids;
+    if (m_qmlTypes)
+        m_all += m_qmlTypes;
+    if (m_jsImports)
+        m_all += m_jsImports;
+    m_all += m_jsScopes;
+}
+
+void ScopeChain::initializeRootScope()
+{
+    ValueOwner *valueOwner = m_context->valueOwner();
+    const Snapshot &snapshot = m_context->snapshot();
+    Bind *bind = m_document->bind();
+
+    m_globalScope = valueOwner->globalObject();
+
+    QHash<Document *, QmlComponentChain *> componentScopes;
+    QmlComponentChain *chain = new QmlComponentChain(m_document);
+    m_qmlComponentScope = QSharedPointer<const QmlComponentChain>(chain);
+
+    if (m_document->qmlProgram()) {
+        componentScopes.insert(m_document.data(), chain);
+        makeComponentChain(chain, snapshot, &componentScopes);
+
+        if (const Imports *imports = m_context->imports(m_document.data())) {
+            m_qmlTypes = imports->typeScope();
+            m_jsImports = imports->jsImportScope();
+        }
+    } else {
+        // add scope chains for all components that import this file
+        foreach (Document::Ptr otherDoc, snapshot) {
+            foreach (const ImportInfo &import, otherDoc->bind()->imports()) {
+                if (import.type() == ImportInfo::FileImport && m_document->fileName() == import.name()) {
+                    QmlComponentChain *component = new QmlComponentChain(otherDoc);
+                    componentScopes.insert(otherDoc.data(), component);
+                    chain->addInstantiatingComponent(component);
+                    makeComponentChain(component, snapshot, &componentScopes);
+                }
+            }
+        }
+
+        // ### TODO: Which type environment do scripts see?
+
+        if (bind->rootObjectValue())
+            m_jsScopes += bind->rootObjectValue();
+    }
+}
+
+void ScopeChain::makeComponentChain(
+        QmlComponentChain *target,
+        const Snapshot &snapshot,
+        QHash<Document *, QmlComponentChain *> *components)
+{
+    Document::Ptr doc = target->document();
+    if (!doc->qmlProgram())
+        return;
+
+    const Bind *bind = doc->bind();
+
+    // add scopes for all components instantiating this one
+    foreach (Document::Ptr otherDoc, snapshot) {
+        if (otherDoc == doc)
+            continue;
+        if (otherDoc->bind()->usesQmlPrototype(bind->rootObjectValue(), m_context)) {
+            if (!components->contains(otherDoc.data())) {
+                QmlComponentChain *component = new QmlComponentChain(otherDoc);
+                components->insert(otherDoc.data(), component);
+                target->addInstantiatingComponent(component);
+
+                makeComponentChain(component, snapshot, components);
+            }
+        }
+    }
+}
+
diff --git a/src/libs/qmljs/qmljsscopechain.h b/src/libs/qmljs/qmljsscopechain.h
new file mode 100644
index 0000000000000000000000000000000000000000..b937cc6809a7d8f78e2ef700015962c221502a63
--- /dev/null
+++ b/src/libs/qmljs/qmljsscopechain.h
@@ -0,0 +1,127 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#ifndef QMLJS_SCOPECHAIN_H
+#define QMLJS_SCOPECHAIN_H
+
+#include "qmljs_global.h"
+#include "qmljsdocument.h"
+#include "qmljscontext.h"
+
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+
+namespace QmlJS {
+namespace Interpreter {
+
+class ObjectValue;
+class TypeScope;
+class JSImportScope;
+class Context;
+class Value;
+
+class QMLJS_EXPORT QmlComponentChain
+{
+    Q_DISABLE_COPY(QmlComponentChain)
+public:
+    QmlComponentChain(const Document::Ptr &document);
+    ~QmlComponentChain();
+
+    Document::Ptr document() const;
+    QList<const QmlComponentChain *> instantiatingComponents() const;
+
+    // takes ownership
+    void addInstantiatingComponent(const QmlComponentChain *component);
+
+private:
+    QList<const QmlComponentChain *> m_instantiatingComponents;
+    Document::Ptr m_document;
+};
+
+// scope chains are copyable
+// constructing a new scope chain is currently too expensive:
+// building the instantiating component chain needs to be sped up
+class QMLJS_EXPORT ScopeChain
+{
+public:
+    explicit ScopeChain(const Document::Ptr &document, const Context *context);
+
+    Document::Ptr document() const;
+    const Context *context() const;
+
+    const Value *lookup(const QString &name, const ObjectValue **foundInScope = 0) const;
+
+    const ObjectValue *globalScope() const;
+    void setGlobalScope(const ObjectValue *globalScope);
+
+    QSharedPointer<const QmlComponentChain> qmlComponentChain() const;
+    void setQmlComponentChain(const QSharedPointer<const QmlComponentChain> &qmlComponentChain);
+
+    QList<const ObjectValue *> qmlScopeObjects() const;
+    void setQmlScopeObjects(const QList<const ObjectValue *> &qmlScopeObjects);
+
+    const TypeScope *qmlTypes() const;
+    void setQmlTypes(const TypeScope *qmlTypes);
+
+    const JSImportScope *jsImports() const;
+    void setJsImports(const JSImportScope *jsImports);
+
+    QList<const ObjectValue *> jsScopes() const;
+    void setJsScopes(const QList<const ObjectValue *> &jsScopes);
+
+    QList<const ObjectValue *> all() const;
+
+private:
+    void update() const;
+    void initializeRootScope();
+    void makeComponentChain(QmlComponentChain *target, const Snapshot &snapshot,
+                            QHash<Document *, QmlComponentChain *> *components);
+
+
+    Document::Ptr m_document;
+    const Context *m_context;
+
+    const ObjectValue *m_globalScope;
+    QSharedPointer<const QmlComponentChain> m_qmlComponentScope;
+    QList<const ObjectValue *> m_qmlScopeObjects;
+    const TypeScope *m_qmlTypes;
+    const JSImportScope *m_jsImports;
+    QList<const ObjectValue *> m_jsScopes;
+
+    bool m_modified;
+    mutable QList<const ObjectValue *> m_all;
+};
+
+} // namespace Interpreter
+} // namespace QmlJS
+
+#endif // QMLJS_SCOPECHAIN_H
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 461745619f2ad962f35b4ceac1910499ad0725ca..5db49ed7331d6fe78c3871fb7831c1a4e69e67d0 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -50,6 +50,7 @@
 #include <qmljs/qmljscontext.h>
 #include <qmljs/qmljslink.h>
 #include <qmljs/qmljsscopebuilder.h>
+#include <qmljs/qmljsscopechain.h>
 #include <qmljs/parser/qmljsast_p.h>
 #include <qmljs/qmljscheck.h>
 #include <qmljs/qmljsmodelmanagerinterface.h>
@@ -336,11 +337,10 @@ public:
         , m_link(snapshot, importPaths,
                  QmlJS::ModelManagerInterface::instance()->builtins(doc))
         , m_context(new Interpreter::Context(m_link(doc, &m_diagnosticLinkMessages)))
-        , m_scopeBuilder(m_context, doc)
+        , m_scopeChain(doc, m_context)
+        , m_scopeBuilder(&m_scopeChain)
     {
         m_lookupContext = LookupContext::create(doc, *m_context, QList<AST::Node*>());
-        // cheaper than calling m_scopeBuilder.initializeRootScope() again
-        *m_context = *m_lookupContext->context();
     }
 
     ~ReadingContext()
@@ -407,7 +407,7 @@ public:
     /// ### Maybe put this into the context as a helper method.
     bool lookupProperty(const QString &prefix, const UiQualifiedId *id, const Interpreter::Value **property = 0, const Interpreter::ObjectValue **parentObject = 0, QString *name = 0)
     {
-        QList<const Interpreter::ObjectValue *> scopeObjects = m_context->scopeChain().qmlScopeObjects;
+        QList<const Interpreter::ObjectValue *> scopeObjects = m_scopeChain.qmlScopeObjects();
         if (scopeObjects.isEmpty())
             return false;
 
@@ -433,7 +433,7 @@ public:
         bool isAttachedProperty = false;
         if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
             isAttachedProperty = true;
-            if (const Interpreter::ObjectValue *qmlTypes = m_context->scopeChain().qmlTypes)
+            if (const Interpreter::ObjectValue *qmlTypes = m_scopeChain.qmlTypes())
                 scopeObjects += qmlTypes;
         }
 
@@ -594,12 +594,12 @@ public:
         const Interpreter::ObjectValue *rhsValueObject = 0;
         QString rhsValueName;
         if (IdentifierExpression *idExp = cast<IdentifierExpression *>(eStmt->expression)) {
-            if (!m_context->scopeChain().qmlScopeObjects.isEmpty())
-                rhsValueObject = m_context->scopeChain().qmlScopeObjects.last();
+            if (!m_scopeChain.qmlScopeObjects().isEmpty())
+                rhsValueObject = m_scopeChain.qmlScopeObjects().last();
             if (idExp->name)
                 rhsValueName = idExp->name->asString();
         } else if (FieldMemberExpression *memberExp = cast<FieldMemberExpression *>(eStmt->expression)) {
-            Evaluate evaluate(m_context);
+            Evaluate evaluate(&m_scopeChain);
             const Interpreter::Value *result = evaluate(memberExp->base);
             rhsValueObject = result->asObjectValue();
 
@@ -634,6 +634,7 @@ private:
     QList<DiagnosticMessage> m_diagnosticLinkMessages;
     Interpreter::Context *m_context;
     LookupContext::Ptr m_lookupContext;
+    Interpreter::ScopeChain m_scopeChain;
     ScopeBuilder m_scopeBuilder;
 };
 
diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp
index 031447eb5f85f680c81ff8f03b7dc8a786574fb2..a2079ccac5f162da95630704ec667f207292a264 100644
--- a/src/plugins/qmljseditor/qmljscompletionassist.cpp
+++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp
@@ -48,6 +48,7 @@
 #include <qmljs/parser/qmljsast_p.h>
 #include <qmljs/qmljsinterpreter.h>
 #include <qmljs/qmljscontext.h>
+#include <qmljs/qmljsscopechain.h>
 #include <qmljs/qmljslookupcontext.h>
 #include <qmljs/qmljsscanner.h>
 #include <qmljs/qmljsbind.h>
@@ -86,15 +87,15 @@ class EnumerateProperties: private Interpreter::MemberProcessor
     bool _globalCompletion;
     bool _enumerateGeneratedSlots;
     bool _enumerateSlots;
-    const Interpreter::Context *_context;
+    const Interpreter::ScopeChain *_scopeChain;
     const Interpreter::ObjectValue *_currentObject;
 
 public:
-    EnumerateProperties(const Interpreter::Context *context)
+    EnumerateProperties(const Interpreter::ScopeChain *scopeChain)
         : _globalCompletion(false),
           _enumerateGeneratedSlots(false),
           _enumerateSlots(true),
-          _context(context),
+          _scopeChain(scopeChain),
           _currentObject(0)
     {
     }
@@ -131,7 +132,7 @@ public:
         _properties.clear();
         _currentObject = 0;
 
-        foreach (const Interpreter::ObjectValue *scope, _context->scopeChain().all())
+        foreach (const Interpreter::ObjectValue *scope, _scopeChain->all())
             enumerateProperties(scope);
 
         return _properties;
@@ -192,7 +193,7 @@ private:
             return;
 
         _processed.insert(object);
-        enumerateProperties(object->prototype(_context));
+        enumerateProperties(object->prototype(_scopeChain->context()));
 
         object->processMembers(this);
     }
@@ -422,6 +423,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface
     const QList<AST::Node *> path = semanticInfo.rangePath(m_interface->position());
     LookupContext::Ptr lookupContext = semanticInfo.lookupContext(path);
     const Interpreter::Context *context = lookupContext->context();
+    const Interpreter::ScopeChain &scopeChain = lookupContext->scopeChain();
 
     // Search for the operator that triggered the completion.
     QChar completionOperator;
@@ -521,7 +523,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface
             doJsKeywordCompletion = false;
             doQmlTypeCompletion = true;
 
-            EnumerateProperties enumerateProperties(context);
+            EnumerateProperties enumerateProperties(&scopeChain);
             enumerateProperties.setGlobalCompletion(true);
             enumerateProperties.setEnumerateGeneratedSlots(true);
             enumerateProperties.setEnumerateSlots(false);
@@ -539,8 +541,8 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface
                                       contextFinder.isAfterOnInLhsOfBinding());
 
             if (ScopeBuilder::isPropertyChangesObject(context, qmlScopeType)
-                    && context->scopeChain().qmlScopeObjects.size() == 2) {
-                addCompletions(enumerateProperties(context->scopeChain().qmlScopeObjects.first()),
+                    && scopeChain.qmlScopeObjects().size() == 2) {
+                addCompletions(enumerateProperties(scopeChain.qmlScopeObjects().first()),
                                m_interface->symbolIcon(),
                                SymbolOrder);
             }
@@ -564,15 +566,15 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface
             doQmlTypeCompletion = true;
 
         if (doQmlTypeCompletion) {
-            if (const Interpreter::ObjectValue *qmlTypes = context->scopeChain().qmlTypes) {
-                EnumerateProperties enumerateProperties(context);
+            if (const Interpreter::ObjectValue *qmlTypes = scopeChain.qmlTypes()) {
+                EnumerateProperties enumerateProperties(&scopeChain);
                 addCompletions(enumerateProperties(qmlTypes), m_interface->symbolIcon(), TypeOrder);
             }
         }
 
         if (doGlobalCompletion) {
             // It's a global completion.
-            EnumerateProperties enumerateProperties(context);
+            EnumerateProperties enumerateProperties(&scopeChain);
             enumerateProperties.setGlobalCompletion(true);
             addCompletions(enumerateProperties(), m_interface->symbolIcon(), SymbolOrder);
         }
@@ -619,7 +621,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface
             //qDebug() << "type:" << interp->typeId(value);
 
             if (value && completionOperator == QLatin1Char('.')) { // member completion
-                EnumerateProperties enumerateProperties(context);
+                EnumerateProperties enumerateProperties(&scopeChain);
                 if (contextFinder.isInLhsOfBinding() && qmlScopeType) {
                     enumerateProperties.setEnumerateGeneratedSlots(true);
                     addCompletionsPropertyLhs(enumerateProperties(value),
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index ebfdf17f0c42143a22c3a97f45064e8829970f1e..1e722884bb6c1342fbaaa0af24d2776d8b386ef0 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -1260,7 +1260,7 @@ TextEditor::BaseTextEditorWidget::Link QmlJSTextEditorWidget::findLinkAt(const Q
     }
 
     LookupContext::Ptr lookupContext = semanticInfo.lookupContext(semanticInfo.rangePath(cursorPosition));
-    Evaluate evaluator(lookupContext->context());
+    Evaluate evaluator(&lookupContext->scopeChain());
     const Interpreter::Value *value = evaluator.reference(node);
 
     QString fileName;
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index 436af01a5f708ab868512f2e7c722fd6d3921367..1921ebc95d292b880d377f322742f84044952cf2 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -80,10 +80,9 @@ public:
 
     FindUsages(Document::Ptr doc, Context *context)
         : _doc(doc)
-        , _context(context)
-        , _builder(context, doc)
+        , _scopeChain(doc, context)
+        , _builder(&_scopeChain)
     {
-        _builder.initializeRootScope();
     }
 
     Result operator()(const QString &name, const ObjectValue *scope)
@@ -106,7 +105,7 @@ protected:
     {
         if (node->name
                 && node->name->asString() == _name
-                && _context->scopeChain().qmlScopeObjects.contains(_scope)) {
+                && _scopeChain.qmlScopeObjects().contains(_scope)) {
             _usages.append(node->identifierToken);
         }
         if (AST::cast<Block *>(node->statement)) {
@@ -176,7 +175,7 @@ protected:
             return false;
 
         const ObjectValue *scope;
-        _context->lookup(_name, &scope);
+        _scopeChain.lookup(_name, &scope);
         if (!scope)
             return false;
         if (check(scope)) {
@@ -188,14 +187,14 @@ protected:
         // so it might still be a use - we just found a different value in a different scope first
 
         // if scope is one of these, our match wasn't inside the instantiating components list
-        const ScopeChain &chain = _context->scopeChain();
-        if (chain.jsScopes.contains(scope)
-                || chain.qmlScopeObjects.contains(scope)
-                || chain.qmlTypes == scope
-                || chain.globalScope == scope)
+        const ScopeChain &chain = _scopeChain;
+        if (chain.jsScopes().contains(scope)
+                || chain.qmlScopeObjects().contains(scope)
+                || chain.qmlTypes() == scope
+                || chain.globalScope() == scope)
             return false;
 
-        if (contains(chain.qmlComponentScope.data()))
+        if (contains(chain.qmlComponentChain().data()))
             _usages.append(node->identifierToken);
 
         return false;
@@ -206,7 +205,7 @@ protected:
         if (!node->name || node->name->asString() != _name)
             return true;
 
-        Evaluate evaluate(_context);
+        Evaluate evaluate(&_scopeChain);
         const Value *lhsValue = evaluate(node->base);
         if (!lhsValue)
             return true;
@@ -245,19 +244,19 @@ protected:
     }
 
 private:
-    bool contains(const ScopeChain::QmlComponentChain *chain)
+    bool contains(const QmlComponentChain *chain)
     {
-        if (!chain || !chain->document)
+        if (!chain || !chain->document())
             return false;
 
-        if (chain->document->bind()->idEnvironment()->lookupMember(_name, _context))
-            return chain->document->bind()->idEnvironment() == _scope;
-        const ObjectValue *root = chain->document->bind()->rootObjectValue();
-        if (root->lookupMember(_name, _context)) {
+        if (chain->document()->bind()->idEnvironment()->lookupMember(_name, _scopeChain.context()))
+            return chain->document()->bind()->idEnvironment() == _scope;
+        const ObjectValue *root = chain->document()->bind()->rootObjectValue();
+        if (root->lookupMember(_name, _scopeChain.context())) {
             return check(root);
         }
 
-        foreach (const ScopeChain::QmlComponentChain *parent, chain->instantiatingComponents) {
+        foreach (const QmlComponentChain *parent, chain->instantiatingComponents()) {
             if (contains(parent))
                 return true;
         }
@@ -269,13 +268,13 @@ private:
         if (!s)
             return false;
         const ObjectValue *definingObject;
-        s->lookupMember(_name, _context, &definingObject);
+        s->lookupMember(_name, _scopeChain.context(), &definingObject);
         return definingObject == _scope;
     }
 
     bool checkQmlScope()
     {
-        foreach (const ObjectValue *s, _context->scopeChain().qmlScopeObjects) {
+        foreach (const ObjectValue *s, _scopeChain.qmlScopeObjects()) {
             if (check(s))
                 return true;
         }
@@ -285,14 +284,14 @@ private:
     bool checkLookup()
     {
         const ObjectValue *scope = 0;
-        _context->lookup(_name, &scope);
+        _scopeChain.lookup(_name, &scope);
         return check(scope);
     }
 
     Result _usages;
 
     Document::Ptr _doc;
-    Context *_context;
+    ScopeChain _scopeChain;
     ScopeBuilder _builder;
 
     QString _name;
@@ -307,9 +306,9 @@ public:
     FindTypeUsages(Document::Ptr doc, Context *context)
         : _doc(doc)
         , _context(context)
-        , _builder(context, doc)
+        , _scopeChain(doc, context)
+        , _builder(&_scopeChain)
     {
-        _builder.initializeRootScope();
     }
 
     Result operator()(const QString &name, const ObjectValue *typeValue)
@@ -380,7 +379,7 @@ protected:
             return false;
 
         const ObjectValue *scope;
-        const Value *objV = _context->lookup(_name, &scope);
+        const Value *objV = _scopeChain.lookup(_name, &scope);
         if (objV == _typeValue)
             _usages.append(node->identifierToken);
         return false;
@@ -390,7 +389,7 @@ protected:
     {
         if (!node->name || node->name->asString() != _name)
             return true;
-        Evaluate evaluate(_context);
+        Evaluate evaluate(&_scopeChain);
         const Value *lhsValue = evaluate(node->base);
         if (!lhsValue)
             return true;
@@ -452,6 +451,7 @@ private:
 
     Document::Ptr _doc;
     Context *_context;
+    ScopeChain _scopeChain;
     ScopeBuilder _builder;
 
     QString _name;
@@ -466,8 +466,8 @@ public:
         TypeKind
     };
 
-    FindTargetExpression(Document::Ptr doc, Context *context)
-        : _doc(doc), _context(context)
+    FindTargetExpression(Document::Ptr doc, const ScopeChain *scopeChain)
+        : _doc(doc), _scopeChain(scopeChain)
     {
     }
 
@@ -488,7 +488,7 @@ public:
     const ObjectValue *scope()
     {
         if (!_scope)
-            _context->lookup(_name, &_scope);
+            _scopeChain->lookup(_name, &_scope);
         return _scope;
     }
 
@@ -524,7 +524,7 @@ protected:
             _name = node->name->asString();
             if ((!_name.isEmpty()) && _name.at(0).isUpper()) {
                 // a possible type
-                _targetValue = _context->lookup(_name, &_scope);
+                _targetValue = _scopeChain->lookup(_name, &_scope);
                 if (value_cast<const ObjectValue*>(_targetValue))
                     _typeKind = TypeKind;
             }
@@ -539,14 +539,14 @@ protected:
             _name = node->name->asString();
             if ((!_name.isEmpty()) && _name.at(0).isUpper()) {
                 // a possible type
-                Evaluate evaluate(_context);
+                Evaluate evaluate(_scopeChain);
                 const Value *lhsValue = evaluate(node->base);
                 if (!lhsValue)
                     return true;
                 const ObjectValue *lhsObj = lhsValue->asObjectValue();
                 if (lhsObj) {
                     _scope = lhsObj;
-                    _targetValue = lhsObj->lookupMember(_name, _context);
+                    _targetValue = lhsObj->lookupMember(_name, _scopeChain->context());
                     _typeKind = TypeKind;
                 }
             }
@@ -593,7 +593,7 @@ protected:
         if (containsOffset(node->typeToken)){
             if (node->memberType){
                 _name = node->memberType->asString();
-                _targetValue = _context->lookupType(_doc.data(), QStringList(_name));
+                _targetValue = _scopeChain->context()->lookupType(_doc.data(), QStringList(_name));
                 _scope = 0;
                 _typeKind = TypeKind;
             }
@@ -654,7 +654,7 @@ private:
     {
         for (UiQualifiedId *att = id; att; att = att->next) {
             if (att->name && containsOffset(att->identifierToken)) {
-                _targetValue = _context->lookupType(_doc.data(), id, att->next);
+                _targetValue = _scopeChain->context()->lookupType(_doc.data(), id, att->next);
                 _scope = 0;
                 _name = att->name->asString();
                 _typeKind = TypeKind;
@@ -666,7 +666,7 @@ private:
 
     void setScope(Node *node)
     {
-        Evaluate evaluate(_context);
+        Evaluate evaluate(_scopeChain);
         const Value *v = evaluate(node);
         if (v)
             _scope = v->asObjectValue();
@@ -677,7 +677,7 @@ private:
     const Value *_targetValue;
     Node *_objectNode;
     Document::Ptr _doc;
-    Context *_context;
+    const ScopeChain *_scopeChain;
     quint32 _offset;
     Kind _typeKind;
 };
@@ -823,12 +823,12 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
     Link link(snapshot, modelManager->importPaths(), modelManager->builtins(doc));
     Context context = link();
 
-    ScopeBuilder builder(&context, doc);
-    builder.initializeRootScope();
+    ScopeChain scopeChain(doc, &context);
+    ScopeBuilder builder(&scopeChain);
     ScopeAstPath astPath(doc);
     builder.push(astPath(offset));
 
-    FindTargetExpression findTarget(doc, &context);
+    FindTargetExpression findTarget(doc, &scopeChain);
     findTarget(offset);
     const QString &name = findTarget.name();
     if (name.isEmpty())
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index ee7a17deb13b549791eaafa6a56fd91e6faf7ab4..57f1921f4b86076612619501eb405ea45f1c3ae6 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -186,7 +186,7 @@ bool HoverHandler::matchColorItem(const LookupContext::Ptr &lookupContext,
     } else if (const AST::UiPublicMember *publicMember =
                AST::cast<const AST::UiPublicMember *>(member)) {
         if (publicMember->name && posIsInSource(pos, publicMember->statement)) {
-            value = lookupContext->context()->lookup(publicMember->name->asString());
+            value = lookupContext->scopeChain().lookup(publicMember->name->asString());
             if (const Interpreter::Reference *ref = value->asReference())
                 value = lookupContext->context()->lookupReference(ref);
                 color = textAt(qmlDocument,
@@ -306,7 +306,7 @@ static const Interpreter::ObjectValue *isMember(const LookupContext::Ptr &lookup
         if (!identExp->name)
             return 0;
         *name = identExp->name->asString();
-        lookupContext->context()->lookup(*name, &owningObject);
+        lookupContext->scopeChain().lookup(*name, &owningObject);
     } else if (AST::FieldMemberExpression *fme = AST::cast<AST::FieldMemberExpression *>(node)) {
         if (!fme->base || !fme->name)
             return 0;
@@ -321,7 +321,7 @@ static const Interpreter::ObjectValue *isMember(const LookupContext::Ptr &lookup
         if (!qid->name)
             return 0;
         *name = qid->name->asString();
-        const Interpreter::Value *value = lookupContext->context()->lookup(*name, &owningObject);
+        const Interpreter::Value *value = lookupContext->scopeChain().lookup(*name, &owningObject);
         for (AST::UiQualifiedId *it = qid->next; it; it = it->next) {
             if (!value)
                 return 0;
diff --git a/src/plugins/qmljseditor/quicktoolbar.cpp b/src/plugins/qmljseditor/quicktoolbar.cpp
index 4d86052feb00fec90839184926f3c5764cb7f0d2..9c4fe1a372bd5fe7d1d494ebcd24c45dd0cb2c6c 100644
--- a/src/plugins/qmljseditor/quicktoolbar.cpp
+++ b/src/plugins/qmljseditor/quicktoolbar.cpp
@@ -78,7 +78,7 @@ static inline const Interpreter::ObjectValue * getPropertyChangesTarget(Node *no
                 if (scriptBinding->qualifiedId
                         && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
                         && ! scriptBinding->qualifiedId->next) {
-                    Evaluate evaluator(lookupContext->context());
+                    Evaluate evaluator(&lookupContext->scopeChain());
                     const Interpreter::Value *targetValue = evaluator(scriptBinding->statement);
                     if (const Interpreter::ObjectValue *targetObject = Interpreter::value_cast<const Interpreter::ObjectValue *>(targetValue)) {
                         return targetObject;