diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index c7e387bd9a1a5731513012a40e229ad4e4ff775f..5076ef912162b12194db7fcb7f8d935b1b0cc25f 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -139,6 +139,9 @@ ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitia
 
     // normal component instance
     ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, &_interp);
+    QmlPrototypeReference *prototypeReference = new QmlPrototypeReference(qualifiedTypeNameId, &_interp);
+    objectValue->setPrototype(prototypeReference);
+
     parentObjectValue = switchObjectValue(objectValue);
 
     if (parentObjectValue)
@@ -241,9 +244,9 @@ bool Bind::visit(FunctionDeclaration *ast)
 {
     if (!ast->name)
         return false;
-    // the first declaration counts
-    if (_currentObjectValue->property(ast->name->asString()))
-        return false;
+    // ### FIXME: the first declaration counts
+    //if (_currentObjectValue->property(ast->name->asString(), 0))
+    //    return false;
 
     ASTFunctionValue *function = new ASTFunctionValue(ast, &_interp);
     // ### set the function's scope.
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 31b4567af3e35a1be819d2142310cfed4865bef0..f25a7df52f0e68469b6f371f2420979237cd6555 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -177,7 +177,7 @@ bool Check::visit(AST::UiQualifiedId *ast)
             if (! name)
                 break;
 
-            const Value *value = base->property(name->asString());
+            const Value *value = base->property(name->asString(), _context);
             if (! it->next)
                 _result = value;
             else
@@ -311,7 +311,7 @@ bool Check::visit(AST::FieldMemberExpression *ast)
 
     if (const Interpreter::Value *base = _engine->convertToObject(check(ast->base))) {
         if (const Interpreter::ObjectValue *obj = base->asObjectValue()) {
-            _result = obj->property(ast->name->asString());
+            _result = obj->property(ast->name->asString(), _context);
         }
     }
 
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 0a650c98177f08ea6397b42ee9b36aa397f08141..9cbce73e0064b09a9bd5d2bd55e632c49f855861 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -162,9 +162,9 @@ QmlObjectValue::QmlObjectValue(const QMetaObject *metaObject, const QString &qml
 
 QmlObjectValue::~QmlObjectValue() {}
 
-const Value *QmlObjectValue::lookupMember(const QString &name) const
+const Value *QmlObjectValue::lookupMember(const QString &name, Context *context) const
 {
-    return ObjectValue::lookupMember(name);
+    return ObjectValue::lookupMember(name, context);
 }
 
 const Value *QmlObjectValue::findOrCreateSignature(int index, const QMetaMethod &method, QString *methodName) const
@@ -708,6 +708,16 @@ void Context::setLookupMode(LookupMode lookupMode)
     _lookupMode = lookupMode;
 }
 
+const ObjectValue *Context::typeEnvironment() const
+{
+    return _typeEnvironment;
+}
+
+void Context::setTypeEnvironment(const ObjectValue *typeEnvironment)
+{
+    _typeEnvironment = typeEnvironment;
+}
+
 void Context::pushScope(const ObjectValue *object)
 {
     _scopeChain.append(object);
@@ -718,12 +728,12 @@ void Context::popScope()
     _scopeChain.removeLast();
 }
 
-const Value *Context::lookup(const QString &name) const
+const Value *Context::lookup(const QString &name)
 {
     for (int index = _scopeChain.size() - 1; index != -1; --index) {
         const ObjectValue *scope = _scopeChain.at(index);
 
-        if (const Value *member = scope->lookupMember(name)) {
+        if (const Value *member = scope->lookupMember(name, this)) {
             if (_lookupMode == JSLookup || ! dynamic_cast<const ASTVariableReference *>(member)) {
                 return member;
             }
@@ -733,6 +743,24 @@ const Value *Context::lookup(const QString &name) const
     return _engine->undefinedValue();
 }
 
+const ObjectValue *Context::lookupType(AST::UiQualifiedId *qmlTypeName)
+{
+    const ObjectValue *objectValue = _typeEnvironment;
+
+    for (UiQualifiedId *iter = qmlTypeName; objectValue && iter; iter = iter->next) {
+        if (! iter->name)
+            return 0;
+
+        const Value *value = objectValue->property(iter->name->asString(), this);
+        if (!value)
+            return 0;
+
+        objectValue = value->asObjectValue();
+    }
+
+    return objectValue;
+}
+
 const Value *Context::property(const ObjectValue *object, const QString &name) const
 {
     const Properties properties = _properties.value(object);
@@ -833,9 +861,21 @@ void ObjectValue::setClassName(const QString &className)
     _className = className;
 }
 
-const ObjectValue *ObjectValue::prototype() const
+const ObjectValue *ObjectValue::prototype(Context *context) const
 {
-    return _prototype;
+    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));
+        }
+    }
+    return prototypeObject;
+}
+
+void ObjectValue::setPrototype(const Value *prototype)
+{
+    // ### FIXME: Check for cycles.
+    _prototype = prototype;
 }
 
 void ObjectValue::setProperty(const QString &name, const Value *value)
@@ -858,23 +898,14 @@ void ObjectValue::accept(ValueVisitor *visitor) const
     visitor->visit(this);
 }
 
-const Value *ObjectValue::property(const QString &name) const
+const Value *ObjectValue::property(const QString &name, Context *context) const
 {
-    return lookupMember(name);
-}
-
-void ObjectValue::setPrototype(const ObjectValue *prototype)
-{
-    QSet<const ObjectValue *> processed;
-
-    if (! prototype || checkPrototype(prototype, &processed))
-        _prototype = prototype;
-    else
-        qWarning() << "**** invalid prototype:";
+    return lookupMember(name, context);
 }
 
-bool ObjectValue::checkPrototype(const ObjectValue *proto, QSet<const ObjectValue *> *processed) const
+bool ObjectValue::checkPrototype(const ObjectValue *, QSet<const ObjectValue *> *) const
 {
+#if 0
     const int previousSize = processed->size();
     processed->insert(this);
 
@@ -887,7 +918,7 @@ bool ObjectValue::checkPrototype(const ObjectValue *proto, QSet<const ObjectValu
 
         return true;
     }
-
+#endif
     return false;
 }
 
@@ -903,7 +934,7 @@ void ObjectValue::processMembers(MemberProcessor *processor) const
     }
 }
 
-const Value *ObjectValue::lookupMember(const QString &name) const
+const Value *ObjectValue::lookupMember(const QString &name, Context *context) const
 {
     if (const Value *m = _members.value(name))
         return m;
@@ -914,17 +945,19 @@ const Value *ObjectValue::lookupMember(const QString &name) const
             return slowLookup.value();
     }
 
-    if (_prototype) {
-        if (const Value *m = _prototype->lookupMember(name))
+    const ObjectValue *prototypeObject = prototype(context);
+    if (prototypeObject) {
+        if (const Value *m = prototypeObject->lookupMember(name, context))
             return m;
     }
 
     return 0;
 }
 
-Activation::Activation()
+Activation::Activation(Context *parentContext)
     : _thisObject(0),
-      _calledAsFunction(true)
+      _calledAsFunction(true),
+      _parentContext(parentContext)
 {
 }
 
@@ -932,6 +965,17 @@ Activation::~Activation()
 {
 }
 
+Context *Activation::parentContext() const
+{
+    return _parentContext;
+}
+
+Context *Activation::context() const
+{
+    // ### FIXME: Real context for activations.
+    return 0;
+}
+
 bool Activation::calledAsConstructor() const
 {
     return ! _calledAsFunction;
@@ -1083,12 +1127,12 @@ const Value *Function::argument(int index) const
     return _arguments.at(index);
 }
 
-const Value *Function::property(const QString &name) const
+const Value *Function::property(const QString &name, Context *context) const
 {
     if (name == "length")
         return engine()->numberValue();
 
-    return FunctionValue::property(name);
+    return FunctionValue::property(name, context);
 }
 
 const Value *Function::invoke(const Activation *activation) const
@@ -1148,14 +1192,14 @@ void ConvertToNumber::visit(const StringValue *)
 
 void ConvertToNumber::visit(const ObjectValue *object)
 {
-    if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf"))) {
+    if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf", 0))) {
         _result = value_cast<const NumberValue *>(valueOfMember->call(object)); // ### invoke convert-to-number?
     }
 }
 
 void ConvertToNumber::visit(const FunctionValue *object)
 {
-    if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf"))) {
+    if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf", 0))) {
         _result = value_cast<const NumberValue *>(valueOfMember->call(object)); // ### invoke convert-to-number?
     }
 }
@@ -1209,14 +1253,14 @@ void ConvertToString::visit(const StringValue *value)
 
 void ConvertToString::visit(const ObjectValue *object)
 {
-    if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString"))) {
+    if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString", 0))) {
         _result = value_cast<const StringValue *>(toStringMember->call(object)); // ### invoke convert-to-string?
     }
 }
 
 void ConvertToString::visit(const FunctionValue *object)
 {
-    if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString"))) {
+    if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString", 0))) {
         _result = value_cast<const StringValue *>(toStringMember->call(object)); // ### invoke convert-to-string?
     }
 }
@@ -1947,3 +1991,24 @@ bool ASTFunctionValue::isVariadic() const
 {
     return true;
 }
+
+QmlPrototypeReference::QmlPrototypeReference(AST::UiQualifiedId *qmlTypeName, Engine *engine)
+    : Reference(engine),
+      _qmlTypeName(qmlTypeName)
+{
+}
+
+QmlPrototypeReference::~QmlPrototypeReference()
+{
+}
+
+UiQualifiedId *QmlPrototypeReference::qmlTypeName() const
+{
+    return _qmlTypeName;
+}
+
+const Value *QmlPrototypeReference::value(Context *context) const
+{
+    return context->lookupType(_qmlTypeName);
+}
+
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 1d3e261e883fe59f83705eb9d498f96751f28974..8144c9950dfeeb00f6544a595b0af5aa9effce56 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -229,10 +229,14 @@ public:
     LookupMode lookupMode() const;
     void setLookupMode(LookupMode lookupMode);
 
+    const ObjectValue *typeEnvironment() const;
+    void setTypeEnvironment(const ObjectValue *typeEnvironment);
+
     void pushScope(const ObjectValue *object);
     void popScope();
 
-    const Value *lookup(const QString &name) const;
+    const Value *lookup(const QString &name);
+    const ObjectValue *lookupType(AST::UiQualifiedId *qmlTypeName);
 
     const Value *property(const ObjectValue *object, const QString &name) const;
     void setProperty(const ObjectValue *object, const QString &name, const Value *value);
@@ -242,6 +246,7 @@ private:
 
     Engine *_engine;
     LookupMode _lookupMode;
+    const ObjectValue *_typeEnvironment;
     QHash<const ObjectValue *, Properties> _properties;
     ScopeChain _scopeChain;
 };
@@ -274,16 +279,16 @@ public:
     QString className() const;
     void setClassName(const QString &className);
 
-    const ObjectValue *prototype() const;
-    void setPrototype(const ObjectValue *prototype);
+    const ObjectValue *prototype(Context *context) const;
+    void setPrototype(const Value *prototype);
 
     virtual void processMembers(MemberProcessor *processor) const;
 
-    virtual const Value *property(const QString &name) const;
+    virtual const Value *property(const QString &name, Context *context) const;
     virtual void setProperty(const QString &name, const Value *value);
     virtual void removeProperty(const QString &name);
 
-    virtual const Value *lookupMember(const QString &name) const;
+    virtual const Value *lookupMember(const QString &name, Context *context) const;
 
     // Value interface
     virtual const ObjectValue *asObjectValue() const;
@@ -294,7 +299,7 @@ private:
 
 private:
     Engine *_engine;
-    const ObjectValue *_prototype;
+    const Value *_prototype;
     QHash<QString, const Value *> _members;
     QString _className;
 };
@@ -307,7 +312,7 @@ public:
     QmlObjectValue(const QMetaObject *metaObject, const QString &qmlTypeName, int majorVersion, int minorVersion, Engine *engine);
     virtual ~QmlObjectValue();
 
-    virtual const Value *lookupMember(const QString &name) const;
+    virtual const Value *lookupMember(const QString &name, Context *context) const;
     virtual void processMembers(MemberProcessor *processor) const;
     const Value *propertyValue(const QMetaProperty &prop) const;
 
@@ -336,9 +341,12 @@ private:
 class QMLJS_EXPORT Activation
 {
 public:
-    Activation();
+    explicit Activation(Context *parentContext = 0);
     virtual ~Activation();
 
+    Context *context() const;
+    Context *parentContext() const;
+
     bool calledAsConstructor() const;
     void setCalledAsConstructor(bool calledAsConstructor);
 
@@ -355,6 +363,7 @@ private:
     ObjectValue *_thisObject;
     ValueList _arguments;
     bool _calledAsFunction;
+    Context *_parentContext;
 };
 
 
@@ -398,7 +407,7 @@ public:
     void setReturnValue(const Value *returnValue);
 
     // ObjectValue interface
-    virtual const Value *property(const QString &name) const;
+    virtual const Value *property(const QString &name, Context *context) const;
 
     // FunctionValue interface
     virtual const Value *returnValue() const;
@@ -614,6 +623,20 @@ private:
 
 
 // internal
+class QMLJS_EXPORT QmlPrototypeReference: public Reference
+{
+public:
+    QmlPrototypeReference(AST::UiQualifiedId *qmlTypeName, Engine *engine);
+    virtual ~QmlPrototypeReference();
+
+    AST::UiQualifiedId *qmlTypeName() const;
+
+    virtual const Value *value(Context *context) const;
+
+private:
+    AST::UiQualifiedId *_qmlTypeName;
+};
+
 class QMLJS_EXPORT ASTObjectValue: public ObjectValue
 {
     AST::UiQualifiedId *_typeName;
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index 6ce97d04f6249eeeda9900a2765b2ac175ecd6a0..2b786b6d12d71d834a054618dcfbdb83bd36c607 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -23,16 +23,6 @@ Link::Link(Document::Ptr currentDoc, const Snapshot &snapshot, Interpreter::Engi
 
 Link::~Link()
 {
-    // unset all prototypes
-    foreach (Document::Ptr doc, _docs) {
-        BindPtr bind = doc->bind();
-
-        if (doc->qmlProgram()) {
-            foreach (ObjectValue *object, bind->_qmlObjects) {
-                object->setPrototype(0);
-            }
-        }
-    }
 }
 
 Context *Link::context()
@@ -90,31 +80,20 @@ void Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
     if (bind->_idEnvironment)
         _context.pushScope(bind->_idEnvironment);
 
-    if (const ObjectValue *typeEnvironment = _typeEnvironments.value(doc.data()))
+    if (const ObjectValue *typeEnvironment = _typeEnvironments.value(doc.data())) {
         _context.pushScope(typeEnvironment);
+        _context.setTypeEnvironment(typeEnvironment);
+    }
 }
 
 void Link::linkImports()
 {
     foreach (Document::Ptr doc, _docs) {
-        BindPtr bind = doc->bind();
-
         ObjectValue *typeEnv = engine()->newObject(/*prototype =*/0); // ### FIXME
         _typeEnvironments.insert(doc.data(), typeEnv);
 
         // Populate the _typeEnvironment with imports.
         populateImportedTypes(typeEnv, doc);
-
-        // Set the prototypes.
-        QHashIterator<Node *, ObjectValue *> it(bind->_qmlObjects);
-        while (it.hasNext()) {
-            it.next();
-            Node *binding = it.key();
-            ObjectValue *value = it.value();
-
-            if (UiQualifiedId *qualifiedId = qualifiedTypeNameId(binding))
-                value->setPrototype(lookupType(typeEnv, qualifiedId));
-        }
     }
 }
 
@@ -260,24 +239,6 @@ void Link::importNonFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, A
     }
 }
 
-const ObjectValue *Link::lookupType(ObjectValue *env, UiQualifiedId *id)
-{
-    const ObjectValue *objectValue = env;
-
-    for (UiQualifiedId *iter = id; objectValue && iter; iter = iter->next) {
-        if (! iter->name)
-            return 0;
-
-        const Value *value = objectValue->property(iter->name->asString());
-        if (!value)
-            return 0;
-
-        objectValue = value->asObjectValue();
-    }
-
-    return objectValue;
-}
-
 UiQualifiedId *Link::qualifiedTypeNameId(Node *node)
 {
     if (UiObjectBinding *binding = AST::cast<UiObjectBinding *>(node))
diff --git a/src/libs/qmljs/qmljslink.h b/src/libs/qmljs/qmljslink.h
index 8c346ac62bec3daa250d6bbdec0b704f4e7b78c9..c588c37b16b163cea3363928502705ccf092c0c2 100644
--- a/src/libs/qmljs/qmljslink.h
+++ b/src/libs/qmljs/qmljslink.h
@@ -31,7 +31,6 @@ public:
 
 private:
     static QList<Document::Ptr> reachableDocuments(Document::Ptr startDoc, const Snapshot &snapshot);
-    static const Interpreter::ObjectValue *lookupType(Interpreter::ObjectValue *env, AST::UiQualifiedId *id);
     static AST::UiQualifiedId *qualifiedTypeNameId(AST::Node *node);
 
     void linkImports();
diff --git a/src/plugins/qmljseditor/qmlcodecompletion.cpp b/src/plugins/qmljseditor/qmlcodecompletion.cpp
index fed3ee48e2c916737218a1a8f8168ef00daca37e..0a97e19a68e04fb60d04d8d6dedc0c09a21041ad 100644
--- a/src/plugins/qmljseditor/qmlcodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmlcodecompletion.cpp
@@ -219,7 +219,7 @@ private:
             return;
 
         _processed.insert(object);
-        enumerateProperties(object->prototype());
+        enumerateProperties(object->prototype(_context));
 
         object->processMembers(this);
     }
diff --git a/src/plugins/qmljseditor/qmlhoverhandler.cpp b/src/plugins/qmljseditor/qmlhoverhandler.cpp
index 8b94716a170aa60ead59ec5f02c50e23cf2d9d88..5885be5383b4373e788912b45756bc5455147f8a 100644
--- a/src/plugins/qmljseditor/qmlhoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmlhoverhandler.cpp
@@ -179,7 +179,7 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
             const Interpreter::Value *value = check(node);
 
             QStringList baseClasses;
-            m_toolTip = prettyPrint(value, &interp, &baseClasses);
+            m_toolTip = prettyPrint(value, link.context(), &baseClasses);
 
             foreach (const QString &baseClass, baseClasses) {
                 QString helpId = QLatin1String("QML.");
@@ -210,10 +210,10 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
     }
 }
 
-QString QmlHoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value, QmlJS::Interpreter::Engine *interp,
+QString QmlHoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value, QmlJS::Interpreter::Context *context,
                                      QStringList *baseClasses) const
 {
-    if (!value)
+    if (! value)
         return QString();
 
     if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) {
@@ -223,14 +223,14 @@ QString QmlHoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value, Qml
             if (! className.isEmpty())
                 baseClasses->append(className);
 
-            objectValue = objectValue->prototype();
+            objectValue = objectValue->prototype(context);
         } while (objectValue);
 
         if (! baseClasses->isEmpty())
             return baseClasses->first();
     }
 
-    QString typeId = interp->typeId(value);
+    QString typeId = context->engine()->typeId(value);
 
     if (typeId == QLatin1String("undefined"))
         typeId.clear();
diff --git a/src/plugins/qmljseditor/qmlhoverhandler.h b/src/plugins/qmljseditor/qmlhoverhandler.h
index 0f481e444bcf4d9ce7c2411c609a2927a34f8960..e564f58d53e77dd2420f274d0f4ca57a18ee0f42 100644
--- a/src/plugins/qmljseditor/qmlhoverhandler.h
+++ b/src/plugins/qmljseditor/qmlhoverhandler.h
@@ -47,6 +47,7 @@ class IEditor;
 namespace QmlJS {
     namespace Interpreter {
         class Engine;
+        class Context;
         class Value;
     }
 }
@@ -74,7 +75,7 @@ private slots:
 
 private:
     void updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos);
-    QString prettyPrint(const QmlJS::Interpreter::Value *value, QmlJS::Interpreter::Engine *interp,
+    QString prettyPrint(const QmlJS::Interpreter::Value *value, QmlJS::Interpreter::Context *context,
                         QStringList *baseClasses) const;
 
 private: