2010-01-21 15:54:19 +01:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
**
|
2010-03-05 11:25:49 +01:00
|
|
|
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
2010-01-21 15:54:19 +01:00
|
|
|
**
|
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
|
|
**
|
|
|
|
** Commercial Usage
|
|
|
|
**
|
|
|
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
|
|
|
** accordance with the Qt Commercial License Agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and Nokia.
|
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
**
|
|
|
|
** Alternatively, 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.
|
|
|
|
**
|
|
|
|
** If you are unsure which license is appropriate for your use, please
|
|
|
|
** contact the sales department at http://qt.nokia.com/contact.
|
|
|
|
**
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include "qmljsinterpreter.h"
|
2010-02-15 11:52:39 +01:00
|
|
|
#include "qmljsevaluate.h"
|
2010-02-04 10:19:37 +01:00
|
|
|
#include "qmljslink.h"
|
2010-06-25 17:10:14 +02:00
|
|
|
#include "qmljsbind.h"
|
2010-04-22 15:59:21 +02:00
|
|
|
#include "qmljsscopebuilder.h"
|
2010-02-03 14:31:03 +01:00
|
|
|
#include "parser/qmljsast_p.h"
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
#include <QtCore/QFile>
|
2010-06-01 15:10:20 +02:00
|
|
|
#include <QtCore/QDir>
|
2010-03-01 13:01:05 +01:00
|
|
|
#include <QtCore/QString>
|
|
|
|
#include <QtCore/QStringList>
|
2010-01-24 19:31:38 +01:00
|
|
|
#include <QtCore/QMetaObject>
|
|
|
|
#include <QtCore/QMetaProperty>
|
2010-03-01 13:01:05 +01:00
|
|
|
#include <QtCore/QXmlStreamReader>
|
2010-06-01 15:10:20 +02:00
|
|
|
#include <QtCore/QProcess>
|
2010-01-21 15:54:19 +01:00
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
|
|
|
using namespace QmlJS::Interpreter;
|
2010-02-03 14:31:03 +01:00
|
|
|
using namespace QmlJS::AST;
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class LookupMember: public MemberProcessor
|
|
|
|
{
|
|
|
|
QString _name;
|
|
|
|
const Value *_value;
|
|
|
|
|
|
|
|
bool process(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
if (_value)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (name == _name) {
|
|
|
|
_value = value;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
LookupMember(const QString &name)
|
|
|
|
: _name(name), _value(0) {}
|
|
|
|
|
|
|
|
const Value *value() const { return _value; }
|
|
|
|
|
|
|
|
virtual bool processProperty(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processEnumerator(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processSignal(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processSlot(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processGeneratedSlot(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end of anonymous namespace
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
namespace QmlJS {
|
|
|
|
namespace Interpreter {
|
|
|
|
|
|
|
|
class FakeMetaEnum {
|
2010-03-01 14:34:08 +01:00
|
|
|
QString m_name;
|
|
|
|
QStringList m_keys;
|
|
|
|
QList<int> m_values;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
FakeMetaEnum(const QString &name)
|
2010-03-01 14:34:08 +01:00
|
|
|
: m_name(name)
|
2010-03-01 13:01:05 +01:00
|
|
|
{}
|
|
|
|
|
2010-04-06 11:44:55 +02:00
|
|
|
QString name() const
|
|
|
|
{ return m_name; }
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
void addKey(const QString &key, int value)
|
2010-03-01 14:34:08 +01:00
|
|
|
{ m_keys.append(key); m_values.append(value); }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
QString key(int index) const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_keys.at(index); }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
int keyCount() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_keys.size(); }
|
2010-04-29 15:52:17 +02:00
|
|
|
|
|
|
|
QStringList keys() const
|
|
|
|
{ return m_keys; }
|
2010-03-01 13:01:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FakeMetaMethod {
|
|
|
|
public:
|
|
|
|
enum {
|
|
|
|
Signal,
|
|
|
|
Slot,
|
|
|
|
Method
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
Private,
|
|
|
|
Protected,
|
|
|
|
Public
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
FakeMetaMethod(const QString &name, const QString &returnType = QString())
|
2010-03-03 15:33:14 +01:00
|
|
|
: m_name(name), m_returnType(returnType), m_methodTy(Method), m_methodAccess(Public)
|
2010-03-01 13:01:05 +01:00
|
|
|
{}
|
|
|
|
|
|
|
|
QString methodName() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_name; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
QStringList parameterNames() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_paramNames; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
QStringList parameterTypes() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_paramTypes; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
void addParameter(const QString &name, const QString &type)
|
2010-03-01 14:34:08 +01:00
|
|
|
{ m_paramNames.append(name); m_paramTypes.append(type); }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
int methodType() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_methodTy; }
|
2010-03-01 13:01:05 +01:00
|
|
|
void setMethodType(int methodType)
|
2010-03-01 14:34:08 +01:00
|
|
|
{ m_methodTy = methodType; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
int access() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_methodAccess; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
private:
|
2010-03-01 14:34:08 +01:00
|
|
|
QString m_name;
|
|
|
|
QString m_returnType;
|
|
|
|
QStringList m_paramNames;
|
|
|
|
QStringList m_paramTypes;
|
|
|
|
int m_methodTy;
|
|
|
|
int m_methodAccess;
|
2010-03-01 13:01:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FakeMetaProperty {
|
2010-03-01 14:34:08 +01:00
|
|
|
QString m_propertyName;
|
|
|
|
QString m_type;
|
|
|
|
bool m_isList;
|
2010-11-11 10:29:32 +01:00
|
|
|
bool m_isWritable;
|
|
|
|
bool m_isPointer;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
public:
|
2010-11-11 10:29:32 +01:00
|
|
|
FakeMetaProperty(const QString &name, const QString &type, bool isList, bool isWritable, bool isPointer)
|
|
|
|
: m_propertyName(name), m_type(type), m_isList(isList), m_isWritable(isWritable), m_isPointer(isPointer)
|
2010-03-01 13:01:05 +01:00
|
|
|
{}
|
|
|
|
|
|
|
|
QString name() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_propertyName; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
QString typeName() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_type; }
|
2010-04-06 12:56:53 +02:00
|
|
|
|
|
|
|
bool isList() const
|
|
|
|
{ return m_isList; }
|
2010-11-11 10:29:32 +01:00
|
|
|
|
|
|
|
bool isWritable() const
|
|
|
|
{ return m_isWritable; }
|
|
|
|
|
|
|
|
bool isPointer() const
|
|
|
|
{ return m_isPointer; }
|
2010-03-01 13:01:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FakeMetaObject {
|
2010-09-30 11:21:23 +02:00
|
|
|
Q_DISABLE_COPY(FakeMetaObject)
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-09-30 11:21:23 +02:00
|
|
|
public:
|
|
|
|
class Export {
|
|
|
|
public:
|
|
|
|
QString package;
|
|
|
|
QString type;
|
|
|
|
QmlJS::ComponentVersion version;
|
|
|
|
QString packageNameVersion;
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
QList<Export> m_exports;
|
2010-03-01 14:34:08 +01:00
|
|
|
const FakeMetaObject *m_super;
|
|
|
|
QString m_superName;
|
|
|
|
QList<FakeMetaEnum> m_enums;
|
2010-04-06 11:44:55 +02:00
|
|
|
QHash<QString, int> m_enumNameToIndex;
|
2010-03-01 14:34:08 +01:00
|
|
|
QList<FakeMetaProperty> m_props;
|
2010-04-06 11:44:55 +02:00
|
|
|
QHash<QString, int> m_propNameToIdx;
|
2010-03-01 14:34:08 +01:00
|
|
|
QList<FakeMetaMethod> m_methods;
|
2010-03-31 14:18:57 +02:00
|
|
|
QString m_defaultPropertyName;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
public:
|
2010-09-30 11:21:23 +02:00
|
|
|
FakeMetaObject()
|
|
|
|
: m_super(0)
|
2010-06-09 14:27:30 +02:00
|
|
|
{
|
2010-09-30 11:21:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void addExport(const QString &name, const QString &package, QmlJS::ComponentVersion version)
|
|
|
|
{
|
|
|
|
Export exp;
|
|
|
|
exp.type = name;
|
|
|
|
exp.package = package;
|
|
|
|
exp.version = version;
|
|
|
|
exp.packageNameVersion = QString::fromLatin1("%1.%2 %3.%4").arg(
|
2010-06-09 14:27:30 +02:00
|
|
|
package, name,
|
2010-09-30 11:21:23 +02:00
|
|
|
QString::number(version.majorVersion()),
|
|
|
|
QString::number(version.minorVersion()));
|
|
|
|
m_exports.append(exp);
|
2010-06-09 14:27:30 +02:00
|
|
|
}
|
2010-09-30 11:21:23 +02:00
|
|
|
QList<Export> exports() const
|
|
|
|
{ return m_exports; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
void setSuperclassName(const QString &superclass)
|
2010-03-01 14:34:08 +01:00
|
|
|
{ m_superName = superclass; }
|
2010-03-01 13:01:05 +01:00
|
|
|
QString superclassName() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_superName; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
void setSuperclass(FakeMetaObject *superClass)
|
2010-03-01 14:34:08 +01:00
|
|
|
{ m_super = superClass; }
|
2010-03-01 13:01:05 +01:00
|
|
|
const FakeMetaObject *superClass() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_super; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
void addEnum(const FakeMetaEnum &fakeEnum)
|
2010-04-06 11:44:55 +02:00
|
|
|
{ m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); }
|
2010-03-01 13:01:05 +01:00
|
|
|
int enumeratorCount() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_enums.size(); }
|
2010-03-01 13:01:05 +01:00
|
|
|
int enumeratorOffset() const
|
|
|
|
{ return 0; }
|
|
|
|
FakeMetaEnum enumerator(int index) const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_enums.at(index); }
|
2010-04-06 11:44:55 +02:00
|
|
|
int enumeratorIndex(const QString &name) const
|
|
|
|
{ return m_enumNameToIndex.value(name, -1); }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
void addProperty(const FakeMetaProperty &property)
|
2010-04-06 11:44:55 +02:00
|
|
|
{ m_propNameToIdx.insert(property.name(), m_props.size()); m_props.append(property); }
|
2010-03-01 13:01:05 +01:00
|
|
|
int propertyCount() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_props.size(); }
|
2010-03-01 13:01:05 +01:00
|
|
|
int propertyOffset() const
|
|
|
|
{ return 0; }
|
|
|
|
FakeMetaProperty property(int index) const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_props.at(index); }
|
2010-04-06 11:44:55 +02:00
|
|
|
int propertyIndex(const QString &name) const
|
|
|
|
{ return m_propNameToIdx.value(name, -1); }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
void addMethod(const FakeMetaMethod &method)
|
2010-03-01 14:34:08 +01:00
|
|
|
{ m_methods.append(method); }
|
2010-03-01 13:01:05 +01:00
|
|
|
int methodCount() const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_methods.size(); }
|
2010-03-01 13:01:05 +01:00
|
|
|
int methodOffset() const
|
|
|
|
{ return 0; }
|
|
|
|
FakeMetaMethod method(int index) const
|
2010-03-01 14:34:08 +01:00
|
|
|
{ return m_methods.at(index); }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-03-31 14:18:57 +02:00
|
|
|
QString defaultPropertyName() const
|
|
|
|
{ return m_defaultPropertyName; }
|
|
|
|
|
|
|
|
void setDefaultPropertyName(const QString defaultPropertyName)
|
|
|
|
{ m_defaultPropertyName = defaultPropertyName; }
|
2010-03-01 13:01:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end of Interpreter namespace
|
|
|
|
} // end of QmlJS namespace
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
namespace {
|
|
|
|
|
2010-01-26 10:50:30 +01:00
|
|
|
class MetaFunction: public FunctionValue
|
|
|
|
{
|
2010-03-01 13:01:05 +01:00
|
|
|
FakeMetaMethod _method;
|
2010-01-26 10:50:30 +01:00
|
|
|
|
|
|
|
public:
|
2010-03-01 13:01:05 +01:00
|
|
|
MetaFunction(const FakeMetaMethod &method, Engine *engine)
|
2010-01-26 10:50:30 +01:00
|
|
|
: FunctionValue(engine), _method(method)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const Value *returnValue() const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual int argumentCount() const
|
|
|
|
{
|
|
|
|
return _method.parameterNames().size();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const Value *argument(int) const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual QString argumentName(int index) const
|
|
|
|
{
|
|
|
|
if (index < _method.parameterNames().size())
|
|
|
|
return _method.parameterNames().at(index);
|
|
|
|
|
|
|
|
return FunctionValue::argumentName(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool isVariadic() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const Value *invoke(const Activation *) const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
class QmlXmlReader
|
|
|
|
{
|
2010-05-19 13:42:56 +02:00
|
|
|
Q_DECLARE_TR_FUNCTIONS(QmlJS::Interpreter::QmlXmlReader)
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
public:
|
|
|
|
QmlXmlReader(QIODevice *dev)
|
|
|
|
: _xml(dev)
|
2010-06-04 10:48:38 +02:00
|
|
|
, _objects(0)
|
2010-03-01 13:01:05 +01:00
|
|
|
{}
|
|
|
|
|
2010-06-01 15:10:20 +02:00
|
|
|
QmlXmlReader(const QByteArray &data)
|
|
|
|
: _xml(data)
|
|
|
|
{}
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
bool operator()(QMap<QString, FakeMetaObject *> *objects) {
|
|
|
|
Q_ASSERT(objects);
|
|
|
|
_objects = objects;
|
|
|
|
|
|
|
|
if (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == "module")
|
|
|
|
readModule();
|
|
|
|
else
|
2010-05-19 13:32:11 +02:00
|
|
|
_xml.raiseError(tr("The file is not module file."));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return !_xml.error();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString errorMessage() const {
|
|
|
|
return _xml.errorString();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void unexpectedElement(const QStringRef &child, const QString &parent) {
|
2010-05-19 13:32:11 +02:00
|
|
|
_xml.raiseError(tr("Unexpected element <%1> in <%2>").arg(child.toString(), parent));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ignoreAttr(const QXmlStreamAttribute &attr) {
|
|
|
|
qDebug() << "** ignoring attribute" << attr.name().toString()
|
|
|
|
<< "in tag" << _xml.name();
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidAttr(const QString &value, const QString &attrName, const QString &tag) {
|
2010-05-19 13:32:11 +02:00
|
|
|
_xml.raiseError(tr("invalid value '%1' for attribute %2 in <%3>").arg(value, attrName, tag));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void noValidAttr(const QString &attrName, const QString &tag) {
|
2010-05-19 13:32:11 +02:00
|
|
|
_xml.raiseError(tr("<%1> has no valid %2 attribute").arg(tag, attrName));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void readModule()
|
|
|
|
{
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == QLatin1String("module"));
|
|
|
|
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes())
|
|
|
|
ignoreAttr(attr);
|
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == QLatin1String("type"))
|
|
|
|
readType();
|
|
|
|
else
|
|
|
|
unexpectedElement(_xml.name(), QLatin1String("module"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void readType()
|
|
|
|
{
|
|
|
|
const QLatin1String tag("type");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
2010-04-29 14:06:10 +02:00
|
|
|
bool doInsert = true;
|
2010-03-31 14:18:57 +02:00
|
|
|
QString name, defaultPropertyName;
|
2010-06-01 15:36:52 +02:00
|
|
|
QmlJS::ComponentVersion version;
|
2010-03-01 13:01:05 +01:00
|
|
|
QString extends;
|
2010-09-30 11:21:23 +02:00
|
|
|
QString id;
|
2010-03-01 13:01:05 +01:00
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
2010-09-30 11:21:23 +02:00
|
|
|
id = attr.value().toString();
|
|
|
|
if (id.isEmpty()) {
|
2010-03-01 13:01:05 +01:00
|
|
|
invalidAttr(name, QLatin1String("name"), tag);
|
|
|
|
return;
|
|
|
|
}
|
2010-03-31 14:18:57 +02:00
|
|
|
} else if (attr.name() == QLatin1String("defaultProperty")) {
|
|
|
|
defaultPropertyName = attr.value().toString();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (attr.name() == QLatin1String("extends")) {
|
|
|
|
if (! attr.value().isEmpty())
|
|
|
|
extends = attr.value().toString();
|
2010-04-29 14:06:10 +02:00
|
|
|
|
|
|
|
if (extends == name) {
|
|
|
|
invalidAttr(extends, QLatin1String("extends"), tag);
|
|
|
|
doInsert = false;
|
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-30 11:21:23 +02:00
|
|
|
FakeMetaObject *metaObject = new FakeMetaObject;
|
2010-03-01 13:01:05 +01:00
|
|
|
if (! extends.isEmpty())
|
|
|
|
metaObject->setSuperclassName(extends);
|
2010-03-31 14:18:57 +02:00
|
|
|
if (! defaultPropertyName.isEmpty())
|
|
|
|
metaObject->setDefaultPropertyName(defaultPropertyName);
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == QLatin1String("property"))
|
|
|
|
readProperty(metaObject);
|
|
|
|
else if (_xml.name() == QLatin1String("enum"))
|
|
|
|
readEnum(metaObject);
|
|
|
|
else if (_xml.name() == QLatin1String("signal"))
|
|
|
|
readSignal(metaObject);
|
|
|
|
else if (_xml.name() == QLatin1String("method"))
|
|
|
|
readMethod(metaObject);
|
2010-09-30 11:21:23 +02:00
|
|
|
else if (_xml.name() == QLatin1String("exports"))
|
|
|
|
readExports(metaObject);
|
2010-03-01 13:01:05 +01:00
|
|
|
else
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
|
|
|
|
2010-10-07 14:12:45 +02:00
|
|
|
metaObject->addExport(id, QString(), QmlJS::ComponentVersion());
|
2010-09-30 11:21:23 +02:00
|
|
|
|
|
|
|
if (doInsert) {
|
|
|
|
_objects->insert(id, metaObject);
|
|
|
|
} else {
|
2010-04-29 14:06:10 +02:00
|
|
|
delete metaObject;
|
2010-09-30 11:21:23 +02:00
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool split(const QString &name, QString *packageName, QString *className) {
|
2010-03-25 15:23:57 +01:00
|
|
|
int dotIdx = name.lastIndexOf(QLatin1Char('.'));
|
2010-03-01 13:01:05 +01:00
|
|
|
if (dotIdx != -1) {
|
|
|
|
if (packageName)
|
|
|
|
*packageName = name.left(dotIdx);
|
|
|
|
if (className)
|
|
|
|
*className = name.mid(dotIdx + 1);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
if (packageName)
|
|
|
|
packageName->clear();
|
|
|
|
if (className)
|
|
|
|
*className = name;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void readProperty(FakeMetaObject *metaObject)
|
|
|
|
{
|
|
|
|
const QLatin1String tag("property");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
QString name, type;
|
|
|
|
bool isList = false;
|
2010-11-11 10:29:32 +01:00
|
|
|
bool isWritable = false;
|
|
|
|
bool isPointer = false;
|
2010-03-01 13:01:05 +01:00
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
|
|
|
name = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("type")) {
|
|
|
|
type = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("isList")) {
|
|
|
|
if (attr.value() == QLatin1String("true")) {
|
|
|
|
isList = true;
|
|
|
|
} else if (attr.value() == QLatin1String("false")) {
|
|
|
|
isList = false;
|
|
|
|
} else {
|
2010-11-11 10:29:32 +01:00
|
|
|
invalidAttr(attr.value().toString(), QLatin1String("isList"), tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (attr.name() == QLatin1String("isWritable")) {
|
|
|
|
if (attr.value() == QLatin1String("true")) {
|
|
|
|
isWritable = true;
|
|
|
|
} else if (attr.value() == QLatin1String("false")) {
|
|
|
|
isWritable = false;
|
|
|
|
} else {
|
|
|
|
invalidAttr(attr.value().toString(), QLatin1String("isWritable"), tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (attr.name() == QLatin1String("isPointer")) {
|
|
|
|
if (attr.value() == QLatin1String("true")) {
|
|
|
|
isPointer = true;
|
|
|
|
} else if (attr.value() == QLatin1String("false")) {
|
|
|
|
isPointer = false;
|
|
|
|
} else {
|
|
|
|
invalidAttr(attr.value().toString(), QLatin1String("isPointer"), tag);
|
2010-03-01 13:01:05 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.isEmpty())
|
|
|
|
noValidAttr(QLatin1String("name"), tag);
|
|
|
|
else if (type.isEmpty())
|
|
|
|
noValidAttr(QLatin1String("type"), tag);
|
|
|
|
else
|
2010-11-11 10:29:32 +01:00
|
|
|
createProperty(metaObject, name, type, isList, isWritable, isPointer);
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void createProperty(FakeMetaObject *metaObject, const QString &name,
|
2010-11-11 10:29:32 +01:00
|
|
|
const QString &type, bool isList, bool isWritable, bool isPointer) {
|
2010-03-01 13:01:05 +01:00
|
|
|
Q_ASSERT(metaObject);
|
|
|
|
|
2010-11-11 10:29:32 +01:00
|
|
|
metaObject->addProperty(FakeMetaProperty(name, type, isList, isWritable, isPointer));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void readEnum(FakeMetaObject *metaObject)
|
|
|
|
{
|
|
|
|
Q_ASSERT(metaObject);
|
|
|
|
|
|
|
|
QLatin1String tag("enum");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
QString name;
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
|
|
|
name = attr.value().toString();
|
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.isEmpty()) {
|
|
|
|
noValidAttr(QLatin1String("name"), tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
FakeMetaEnum metaEnum(name);
|
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == QLatin1String("enumerator"))
|
|
|
|
readEnumerator(&metaEnum);
|
|
|
|
else
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
2010-03-26 14:16:03 +01:00
|
|
|
|
|
|
|
metaObject->addEnum(metaEnum);
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void readEnumerator(FakeMetaEnum *metaEnum)
|
|
|
|
{
|
|
|
|
Q_ASSERT(metaEnum);
|
|
|
|
|
|
|
|
QLatin1String tag("enumerator");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
QString name;
|
|
|
|
int value = 0;
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
|
|
|
name = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("value")) {
|
|
|
|
const QString valueStr = attr.value().toString();
|
|
|
|
bool ok = false;
|
|
|
|
value = valueStr.toInt(&ok);
|
|
|
|
if (!ok) {
|
|
|
|
invalidAttr(valueStr, QLatin1String("value"), tag);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.isEmpty())
|
|
|
|
noValidAttr(QLatin1String("name"), tag);
|
|
|
|
else
|
|
|
|
metaEnum->addKey(name, value);
|
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void readSignal(FakeMetaObject *metaObject)
|
|
|
|
{
|
|
|
|
Q_ASSERT(metaObject);
|
|
|
|
QLatin1String tag("signal");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
QString name;
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
|
|
|
name = attr.value().toString();
|
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.isEmpty()) {
|
|
|
|
noValidAttr(QLatin1String("name"), tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
FakeMetaMethod method(name);
|
|
|
|
method.setMethodType(FakeMetaMethod::Signal);
|
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == QLatin1String("param")) {
|
|
|
|
readParam(&method);
|
|
|
|
} else {
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
|
|
|
}
|
2010-03-03 15:29:58 +01:00
|
|
|
|
|
|
|
metaObject->addMethod(method);
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void readParam(FakeMetaMethod *method)
|
|
|
|
{
|
|
|
|
Q_ASSERT(method);
|
|
|
|
QLatin1String tag("param");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
QString name, type;
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
|
|
|
name = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("type")) {
|
|
|
|
type = attr.value().toString();
|
2010-11-11 10:29:32 +01:00
|
|
|
} else if (attr.name() == QLatin1String("isPointer")) {
|
2010-03-01 13:01:05 +01:00
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// note: name attribute is optional
|
|
|
|
if (type.isEmpty())
|
|
|
|
noValidAttr(QLatin1String("type"), tag);
|
|
|
|
|
|
|
|
method->addParameter(name, type);
|
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void readMethod(FakeMetaObject *metaObject)
|
|
|
|
{
|
|
|
|
Q_ASSERT(metaObject);
|
|
|
|
QLatin1String tag("method");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
QString name, type;
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("name")) {
|
|
|
|
name = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("type")) {
|
|
|
|
type = attr.value().toString();
|
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// note: type attribute is optional, in which case it's a void method.
|
|
|
|
if (name.isEmpty()) {
|
|
|
|
noValidAttr(QLatin1String("name"), tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
FakeMetaMethod method(name, type);
|
2010-06-28 09:41:04 +02:00
|
|
|
method.setMethodType(FakeMetaMethod::Slot);
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == QLatin1String("param")) {
|
|
|
|
readParam(&method);
|
|
|
|
} else {
|
|
|
|
unexpectedElement(_xml.name(), tag);
|
|
|
|
}
|
|
|
|
}
|
2010-03-03 15:29:58 +01:00
|
|
|
|
|
|
|
metaObject->addMethod(method);
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
2010-09-30 11:21:23 +02:00
|
|
|
void readExports(FakeMetaObject *metaObject)
|
|
|
|
{
|
|
|
|
Q_ASSERT(metaObject);
|
|
|
|
QLatin1String tag("exports");
|
|
|
|
QLatin1String childTag("export");
|
|
|
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
|
|
|
|
|
|
|
while (_xml.readNextStartElement()) {
|
|
|
|
if (_xml.name() == childTag) {
|
|
|
|
QString type;
|
|
|
|
QString package;
|
|
|
|
QmlJS::ComponentVersion version;
|
|
|
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
|
|
|
if (attr.name() == QLatin1String("module")) {
|
|
|
|
package = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("type")) {
|
|
|
|
type = attr.value().toString();
|
|
|
|
} else if (attr.name() == QLatin1String("version")) {
|
|
|
|
QString versionStr = attr.value().toString();
|
|
|
|
int dotIdx = versionStr.indexOf('.');
|
|
|
|
if (dotIdx == -1) {
|
|
|
|
bool ok = false;
|
|
|
|
const int major = versionStr.toInt(&ok);
|
|
|
|
if (!ok) {
|
|
|
|
invalidAttr(versionStr, QLatin1String("version"), childTag);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
version = QmlJS::ComponentVersion(major, QmlJS::ComponentVersion::NoVersion);
|
|
|
|
} else {
|
|
|
|
bool ok = false;
|
|
|
|
const int major = versionStr.left(dotIdx).toInt(&ok);
|
|
|
|
if (!ok) {
|
|
|
|
invalidAttr(versionStr, QLatin1String("version"), childTag);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const int minor = versionStr.mid(dotIdx + 1).toInt(&ok);
|
|
|
|
if (!ok) {
|
|
|
|
invalidAttr(versionStr, QLatin1String("version"), childTag);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
version = QmlJS::ComponentVersion(major, minor);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ignoreAttr(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
metaObject->addExport(type, package, version);
|
|
|
|
} else {
|
|
|
|
unexpectedElement(_xml.name(), childTag);
|
|
|
|
}
|
|
|
|
_xml.skipCurrentElement(); // the <export> tag should be empty anyhow
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
private:
|
|
|
|
QXmlStreamReader _xml;
|
|
|
|
QMap<QString, FakeMetaObject *> *_objects;
|
|
|
|
};
|
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
} // end of anonymous namespace
|
|
|
|
|
2010-10-19 16:15:32 +02:00
|
|
|
QmlObjectValue::QmlObjectValue(const FakeMetaObject *metaObject, const QString &className,
|
|
|
|
const QString &packageName, const QmlJS::ComponentVersion version, Engine *engine)
|
2010-01-28 15:50:58 +01:00
|
|
|
: ObjectValue(engine),
|
2010-09-30 11:21:23 +02:00
|
|
|
_metaObject(metaObject),
|
2010-10-19 16:15:32 +02:00
|
|
|
_packageName(packageName),
|
|
|
|
_componentVersion(version)
|
2010-01-27 12:40:02 +01:00
|
|
|
{
|
2010-10-19 16:15:32 +02:00
|
|
|
setClassName(className);
|
2010-01-27 12:40:02 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
QmlObjectValue::~QmlObjectValue()
|
|
|
|
{}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
const Value *QmlObjectValue::findOrCreateSignature(int index, const FakeMetaMethod &method, QString *methodName) const
|
2010-02-01 13:54:44 +01:00
|
|
|
{
|
2010-03-01 13:01:05 +01:00
|
|
|
*methodName = method.methodName();
|
2010-02-01 13:54:44 +01:00
|
|
|
const Value *value = _metaSignature.value(index);
|
|
|
|
if (! value) {
|
|
|
|
value = new MetaFunction(method, engine());
|
|
|
|
_metaSignature.insert(index, value);
|
2010-01-24 13:29:46 +01:00
|
|
|
}
|
2010-02-01 13:54:44 +01:00
|
|
|
return value;
|
2010-01-26 14:50:52 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
void QmlObjectValue::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
2010-02-01 13:54:44 +01:00
|
|
|
// process the meta enums
|
2010-03-01 13:01:05 +01:00
|
|
|
for (int index = _metaObject->enumeratorOffset(); index < _metaObject->enumeratorCount(); ++index) {
|
|
|
|
FakeMetaEnum e = _metaObject->enumerator(index);
|
2010-01-28 15:50:58 +01:00
|
|
|
|
|
|
|
for (int i = 0; i < e.keyCount(); ++i) {
|
2010-03-01 13:01:05 +01:00
|
|
|
processor->processEnumerator(e.key(i), engine()->numberValue());
|
2010-01-28 15:50:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
// process the meta properties
|
|
|
|
for (int index = 0; index < _metaObject->propertyCount(); ++index) {
|
2010-03-01 13:01:05 +01:00
|
|
|
FakeMetaProperty prop = _metaObject->property(index);
|
2010-01-25 14:48:44 +01:00
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processProperty(prop.name(), propertyValue(prop));
|
|
|
|
}
|
2010-01-26 10:10:11 +01:00
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
// process the meta methods
|
|
|
|
for (int index = 0; index < _metaObject->methodCount(); ++index) {
|
2010-03-01 13:01:05 +01:00
|
|
|
FakeMetaMethod method = _metaObject->method(index);
|
2010-02-01 13:54:44 +01:00
|
|
|
QString methodName;
|
|
|
|
const Value *signature = findOrCreateSignature(index, method, &methodName);
|
2010-01-26 10:19:42 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
if (method.methodType() == FakeMetaMethod::Slot && method.access() == FakeMetaMethod::Public) {
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processSlot(methodName, signature);
|
2010-01-26 10:19:42 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (method.methodType() == FakeMetaMethod::Signal && method.access() != FakeMetaMethod::Private) {
|
2010-01-26 14:50:52 +01:00
|
|
|
// process the signal
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processSignal(methodName, signature);
|
2010-01-26 10:19:42 +01:00
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
QString slotName;
|
|
|
|
slotName += QLatin1String("on");
|
|
|
|
slotName += methodName.at(0).toUpper();
|
|
|
|
slotName += methodName.midRef(1);
|
2010-01-25 14:48:44 +01:00
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
// process the generated slot
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processGeneratedSlot(slotName, signature);
|
2010-01-26 14:50:52 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
ObjectValue::processMembers(processor);
|
|
|
|
}
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
|
2010-01-26 14:50:52 +01:00
|
|
|
{
|
2010-03-01 13:01:05 +01:00
|
|
|
const QString typeName = prop.typeName();
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
// ### Verify type resolving.
|
2010-06-01 15:10:20 +02:00
|
|
|
QmlObjectValue *objectValue = engine()->cppQmlTypes().typeForImport(typeName);
|
2010-11-11 11:11:48 +01:00
|
|
|
if (objectValue) {
|
|
|
|
QString packageClassName = objectValue->nameInPackage(packageName());
|
|
|
|
if (!packageClassName.isEmpty())
|
|
|
|
objectValue = engine()->cppQmlTypes().typeForImport(packageName() + '.' + packageClassName);
|
2010-03-01 13:01:05 +01:00
|
|
|
return objectValue;
|
2010-11-11 11:11:48 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
const Value *value = engine()->undefinedValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
if (typeName == QLatin1String("QByteArray")
|
|
|
|
|| typeName == QLatin1String("string")
|
2010-11-11 16:04:55 +01:00
|
|
|
|| typeName == QLatin1String("QString")) {
|
2010-01-26 14:50:52 +01:00
|
|
|
value = engine()->stringValue();
|
2010-11-11 16:04:55 +01:00
|
|
|
} else if (typeName == QLatin1String("QUrl")) {
|
|
|
|
value = engine()->urlValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("bool")) {
|
2010-01-26 14:50:52 +01:00
|
|
|
value = engine()->booleanValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("int")
|
2010-11-10 16:31:20 +01:00
|
|
|
|| typeName == QLatin1String("long")) {
|
2010-11-11 16:04:55 +01:00
|
|
|
value = engine()->intValue();
|
2010-11-10 16:31:20 +01:00
|
|
|
} else if (typeName == QLatin1String("float")
|
|
|
|
|| typeName == QLatin1String("double")
|
|
|
|
|| typeName == QLatin1String("qreal")) {
|
2010-11-11 16:04:55 +01:00
|
|
|
// ### Review: more types here?
|
|
|
|
value = engine()->realValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QFont")) {
|
2010-09-24 14:01:10 +02:00
|
|
|
value = engine()->qmlFontObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QPoint")
|
|
|
|
|| typeName == QLatin1String("QPointF")
|
|
|
|
|| typeName == QLatin1String("QVector2D")) {
|
2010-09-24 14:01:10 +02:00
|
|
|
value = engine()->qmlPointObject();
|
2010-04-15 11:36:12 +02:00
|
|
|
} else if (typeName == QLatin1String("QSize")
|
|
|
|
|| typeName == QLatin1String("QSizeF")) {
|
2010-09-24 14:01:10 +02:00
|
|
|
value = engine()->qmlSizeObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QRect")
|
|
|
|
|| typeName == QLatin1String("QRectF")) {
|
2010-09-24 14:01:10 +02:00
|
|
|
value = engine()->qmlRectObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QVector3D")) {
|
2010-09-24 14:01:10 +02:00
|
|
|
value = engine()->qmlVector3DObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QColor")) {
|
2010-02-23 14:36:38 +01:00
|
|
|
value = engine()->colorValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QDeclarativeAnchorLine")) {
|
2010-02-23 17:02:50 +01:00
|
|
|
value = engine()->anchorLineValue();
|
2010-02-19 15:10:39 +01:00
|
|
|
}
|
|
|
|
|
2010-04-29 15:52:17 +02:00
|
|
|
// might be an enum
|
|
|
|
int enumIndex = _metaObject->enumeratorIndex(prop.typeName());
|
|
|
|
if (enumIndex != -1) {
|
|
|
|
const FakeMetaEnum &metaEnum = _metaObject->enumerator(enumIndex);
|
|
|
|
value = new QmlEnumValue(metaEnum, engine());
|
|
|
|
}
|
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
return value;
|
|
|
|
}
|
2010-02-19 15:10:39 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
QString QmlObjectValue::packageName() const
|
2010-10-19 16:15:32 +02:00
|
|
|
{ return _packageName; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-11-11 11:11:48 +01:00
|
|
|
QString QmlObjectValue::nameInPackage(const QString &packageName) const
|
|
|
|
{
|
|
|
|
foreach (const FakeMetaObject::Export &exp, _metaObject->exports())
|
|
|
|
if (exp.package == packageName)
|
|
|
|
return exp.type;
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-06-01 15:36:52 +02:00
|
|
|
QmlJS::ComponentVersion QmlObjectValue::version() const
|
2010-10-19 16:15:32 +02:00
|
|
|
{ return _componentVersion; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-03-31 14:18:57 +02:00
|
|
|
QString QmlObjectValue::defaultPropertyName() const
|
|
|
|
{ return _metaObject->defaultPropertyName(); }
|
|
|
|
|
2010-04-06 11:44:55 +02:00
|
|
|
QString QmlObjectValue::propertyType(const QString &propertyName) const
|
|
|
|
{
|
|
|
|
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
|
2010-11-10 16:38:41 +01:00
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
2010-04-06 11:44:55 +02:00
|
|
|
if (propIdx != -1) {
|
2010-11-10 16:38:41 +01:00
|
|
|
return iter->property(propIdx).typeName();
|
2010-04-06 11:44:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:38:41 +01:00
|
|
|
bool QmlObjectValue::isListProperty(const QString &propertyName) const
|
2010-04-06 12:56:53 +02:00
|
|
|
{
|
2010-11-10 16:38:41 +01:00
|
|
|
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
|
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return iter->property(propIdx).isList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2010-04-06 12:56:53 +02:00
|
|
|
}
|
|
|
|
|
2010-04-06 11:44:55 +02:00
|
|
|
bool QmlObjectValue::isEnum(const QString &typeName) const
|
|
|
|
{
|
|
|
|
return _metaObject->enumeratorIndex(typeName) != -1;
|
|
|
|
}
|
|
|
|
|
2010-11-11 10:29:32 +01:00
|
|
|
bool QmlObjectValue::isWritable(const QString &propertyName) const
|
|
|
|
{
|
|
|
|
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
|
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return iter->property(propIdx).isWritable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QmlObjectValue::isPointer(const QString &propertyName) const
|
|
|
|
{
|
|
|
|
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
|
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return iter->property(propIdx).isPointer();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-11 10:46:19 +01:00
|
|
|
bool QmlObjectValue::hasLocalProperty(const QString &typeName) const
|
|
|
|
{
|
|
|
|
int idx = _metaObject->propertyIndex(typeName);
|
|
|
|
if (idx == -1)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QmlObjectValue::hasProperty(const QString &propertyName) const
|
|
|
|
{
|
|
|
|
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
|
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-04-06 15:40:47 +02:00
|
|
|
bool QmlObjectValue::enumContainsKey(const QString &enumName, const QString &enumKeyName) const
|
|
|
|
{
|
|
|
|
int idx = _metaObject->enumeratorIndex(enumName);
|
|
|
|
if (idx == -1)
|
|
|
|
return false;
|
|
|
|
const FakeMetaEnum &fme = _metaObject->enumerator(idx);
|
|
|
|
for (int i = 0; i < fme.keyCount(); ++i) {
|
|
|
|
if (fme.key(i) == enumKeyName)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-11 10:46:19 +01:00
|
|
|
QStringList QmlObjectValue::keysForEnum(const QString &enumName) const
|
|
|
|
{
|
|
|
|
int idx = _metaObject->enumeratorIndex(enumName);
|
|
|
|
if (idx == -1)
|
|
|
|
return QStringList();
|
|
|
|
const FakeMetaEnum &fme = _metaObject->enumerator(idx);
|
|
|
|
return fme.keys();
|
|
|
|
}
|
|
|
|
|
2010-06-07 17:33:44 +02:00
|
|
|
// Returns true if this object is in a package or if there is an object that
|
|
|
|
// has this one in its prototype chain and is itself in a package.
|
|
|
|
bool QmlObjectValue::hasChildInPackage() const
|
|
|
|
{
|
|
|
|
if (!packageName().isEmpty())
|
|
|
|
return true;
|
2010-06-09 14:27:30 +02:00
|
|
|
QHashIterator<QString, QmlObjectValue *> it(engine()->cppQmlTypes().types());
|
2010-06-01 15:10:20 +02:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
2010-06-09 14:27:30 +02:00
|
|
|
const FakeMetaObject *other = it.value()->_metaObject;
|
2010-10-27 16:51:55 +02:00
|
|
|
// if it has only the default no-package export, it is not really exported
|
|
|
|
if (other->exports().size() <= 1)
|
2010-06-07 17:33:44 +02:00
|
|
|
continue;
|
|
|
|
for (const FakeMetaObject *iter = other; iter; iter = iter->superClass()) {
|
|
|
|
if (iter == _metaObject) // this object is a parent of other
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
bool QmlObjectValue::isDerivedFrom(const FakeMetaObject *base) const
|
2010-02-19 15:10:39 +01:00
|
|
|
{
|
2010-03-01 13:01:05 +01:00
|
|
|
for (const FakeMetaObject *iter = _metaObject; iter; iter = iter->superClass()) {
|
2010-02-19 15:10:39 +01:00
|
|
|
if (iter == base)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-04-29 15:52:17 +02:00
|
|
|
QmlEnumValue::QmlEnumValue(const FakeMetaEnum &metaEnum, Engine *engine)
|
|
|
|
: NumberValue(),
|
|
|
|
_metaEnum(new FakeMetaEnum(metaEnum))
|
|
|
|
{
|
|
|
|
engine->registerValue(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlEnumValue::~QmlEnumValue()
|
|
|
|
{
|
|
|
|
delete _metaEnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString QmlEnumValue::name() const
|
|
|
|
{
|
|
|
|
return _metaEnum->name();
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList QmlEnumValue::keys() const
|
|
|
|
{
|
|
|
|
return _metaEnum->keys();
|
|
|
|
}
|
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
namespace {
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// constructors
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class ObjectCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ObjectCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FunctionCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FunctionCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class ArrayCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ArrayCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class StringCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
StringCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class BooleanCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
BooleanCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class NumberCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NumberCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class DateCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DateCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class RegExpCtor: public Function
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
RegExpCtor(Engine *engine);
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
virtual const Value *invoke(const Activation *activation) const;
|
2010-01-24 11:10:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
ObjectCtor::ObjectCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionCtor::FunctionCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayCtor::ArrayCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StringCtor::StringCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BooleanCtor::BooleanCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NumberCtor::NumberCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
DateCtor::DateCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RegExpCtor::RegExpCtor(Engine *engine)
|
|
|
|
: Function(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *ObjectCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
if (activation->calledAsFunction())
|
|
|
|
thisObject = engine()->newObject();
|
|
|
|
|
|
|
|
thisObject->setClassName("Object");
|
|
|
|
thisObject->setPrototype(engine()->objectPrototype());
|
|
|
|
thisObject->setProperty("length", engine()->numberValue());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *FunctionCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
if (activation->calledAsFunction())
|
|
|
|
thisObject = engine()->newObject();
|
|
|
|
|
|
|
|
thisObject->setClassName("Function");
|
|
|
|
thisObject->setPrototype(engine()->functionPrototype());
|
|
|
|
thisObject->setProperty("length", engine()->numberValue());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *ArrayCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
if (activation->calledAsFunction())
|
|
|
|
thisObject = engine()->newObject();
|
2010-01-24 11:10:01 +01:00
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
thisObject->setClassName("Array");
|
|
|
|
thisObject->setPrototype(engine()->arrayPrototype());
|
|
|
|
thisObject->setProperty("length", engine()->numberValue());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *StringCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
if (activation->calledAsFunction())
|
|
|
|
return engine()->convertToString(activation->thisObject());
|
2010-01-24 11:10:01 +01:00
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
thisObject->setClassName("String");
|
|
|
|
thisObject->setPrototype(engine()->stringPrototype());
|
|
|
|
thisObject->setProperty("length", engine()->numberValue());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *BooleanCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
if (activation->calledAsFunction())
|
|
|
|
return engine()->convertToBoolean(activation->thisObject());
|
|
|
|
|
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
thisObject->setClassName("Boolean");
|
|
|
|
thisObject->setPrototype(engine()->booleanPrototype());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *NumberCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
if (activation->calledAsFunction())
|
|
|
|
return engine()->convertToNumber(activation->thisObject());
|
|
|
|
|
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
thisObject->setClassName("Number");
|
|
|
|
thisObject->setPrototype(engine()->numberPrototype());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *DateCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
if (activation->calledAsFunction())
|
|
|
|
return engine()->stringValue();
|
|
|
|
|
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
thisObject->setClassName("Date");
|
|
|
|
thisObject->setPrototype(engine()->datePrototype());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *RegExpCtor::invoke(const Activation *activation) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
ObjectValue *thisObject = activation->thisObject();
|
|
|
|
if (activation->calledAsFunction())
|
|
|
|
thisObject = engine()->newObject();
|
|
|
|
|
|
|
|
thisObject->setClassName("RegExp");
|
|
|
|
thisObject->setPrototype(engine()->regexpPrototype());
|
|
|
|
thisObject->setProperty("source", engine()->stringValue());
|
|
|
|
thisObject->setProperty("global", engine()->booleanValue());
|
|
|
|
thisObject->setProperty("ignoreCase", engine()->booleanValue());
|
|
|
|
thisObject->setProperty("multiline", engine()->booleanValue());
|
|
|
|
thisObject->setProperty("lastIndex", engine()->numberValue());
|
|
|
|
return thisObject;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} // end of anonymous namespace
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ValueVisitor
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueVisitor::ValueVisitor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueVisitor::~ValueVisitor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const NullValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const UndefinedValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const NumberValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const BooleanValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const StringValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const ObjectValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const FunctionValue *)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
void ValueVisitor::visit(const Reference *)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
void ValueVisitor::visit(const ColorValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
void ValueVisitor::visit(const AnchorLineValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Value
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-01-24 11:10:01 +01:00
|
|
|
Value::Value()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::~Value()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-08 12:50:10 +01:00
|
|
|
bool Value::getSourceLocation(QString *, int *, int *) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const NullValue *Value::asNullValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const UndefinedValue *Value::asUndefinedValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const NumberValue *Value::asNumberValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:31:20 +01:00
|
|
|
const IntValue *Value::asIntValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const RealValue *Value::asRealValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const BooleanValue *Value::asBooleanValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringValue *Value::asStringValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-11 16:04:55 +01:00
|
|
|
const UrlValue *Value::asUrlValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const ObjectValue *Value::asObjectValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Value::asFunctionValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
const Reference *Value::asReference() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
const ColorValue *Value::asColorValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
const AnchorLineValue *Value::asAnchorLineValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Values
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-01-24 11:10:01 +01:00
|
|
|
const NullValue *NullValue::asNullValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NullValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const UndefinedValue *UndefinedValue::asUndefinedValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndefinedValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const NumberValue *NumberValue::asNumberValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:31:20 +01:00
|
|
|
const RealValue *RealValue::asRealValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const IntValue *IntValue::asIntValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void NumberValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const BooleanValue *BooleanValue::asBooleanValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BooleanValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringValue *StringValue::asStringValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-11-11 16:04:55 +01:00
|
|
|
const UrlValue *UrlValue::asUrlValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void StringValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
|
2010-02-19 10:14:34 +01:00
|
|
|
ScopeChain::ScopeChain()
|
|
|
|
: globalScope(0)
|
|
|
|
, qmlTypes(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-22 11:21:03 +01:00
|
|
|
ScopeChain::QmlComponentChain::QmlComponentChain()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ScopeChain::QmlComponentChain::~QmlComponentChain()
|
|
|
|
{
|
|
|
|
qDeleteAll(instantiatingComponents);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScopeChain::QmlComponentChain::clear()
|
|
|
|
{
|
|
|
|
qDeleteAll(instantiatingComponents);
|
|
|
|
instantiatingComponents.clear();
|
2010-06-25 17:10:14 +02:00
|
|
|
document = Document::Ptr(0);
|
2010-02-22 11:21:03 +01:00
|
|
|
}
|
|
|
|
|
2010-08-30 14:12:06 +02:00
|
|
|
void ScopeChain::QmlComponentChain::collect(QList<const ObjectValue *> *list) const
|
2010-02-19 10:14:34 +01:00
|
|
|
{
|
2010-08-30 14:12:06 +02:00
|
|
|
foreach (const QmlComponentChain *parent, instantiatingComponents)
|
|
|
|
parent->collect(list);
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-06-25 17:10:14 +02:00
|
|
|
if (!document)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ObjectValue *root = document->bind()->rootObjectValue())
|
|
|
|
list->append(root);
|
|
|
|
if (ObjectValue *ids = document->bind()->idEnvironment())
|
2010-02-19 10:14:34 +01:00
|
|
|
list->append(ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScopeChain::update()
|
|
|
|
{
|
2010-02-22 10:21:07 +01:00
|
|
|
_all.clear();
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-02-22 10:21:07 +01:00
|
|
|
_all += globalScope;
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-04-22 15:59:21 +02:00
|
|
|
// the root scope in js files doesn't see instantiating components
|
|
|
|
if (jsScopes.count() != 1 || !qmlScopeObjects.isEmpty()) {
|
2010-08-27 09:37:01 +02:00
|
|
|
if (qmlComponentScope) {
|
2010-08-30 14:12:06 +02:00
|
|
|
foreach (const QmlComponentChain *parent, qmlComponentScope->instantiatingComponents)
|
|
|
|
parent->collect(&_all);
|
2010-08-27 09:37:01 +02:00
|
|
|
}
|
2010-04-22 15:59:21 +02:00
|
|
|
}
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-06-25 17:10:14 +02:00
|
|
|
ObjectValue *root = 0;
|
|
|
|
ObjectValue *ids = 0;
|
2010-08-27 09:37:01 +02:00
|
|
|
if (qmlComponentScope && qmlComponentScope->document) {
|
|
|
|
root = qmlComponentScope->document->bind()->rootObjectValue();
|
|
|
|
ids = qmlComponentScope->document->bind()->idEnvironment();
|
2010-06-25 17:10:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (root && !qmlScopeObjects.contains(root))
|
|
|
|
_all += root;
|
2010-02-22 10:21:07 +01:00
|
|
|
_all += qmlScopeObjects;
|
2010-06-25 17:10:14 +02:00
|
|
|
if (ids)
|
|
|
|
_all += ids;
|
2010-02-19 10:14:34 +01:00
|
|
|
if (qmlTypes)
|
2010-02-22 10:21:07 +01:00
|
|
|
_all += qmlTypes;
|
|
|
|
_all += jsScopes;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<const ObjectValue *> ScopeChain::all() const
|
|
|
|
{
|
|
|
|
return _all;
|
2010-02-19 10:14:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-26 10:50:00 +02:00
|
|
|
Context::Context()
|
|
|
|
: _engine(new Engine),
|
2010-02-16 10:36:09 +01:00
|
|
|
_qmlScopeObjectIndex(-1),
|
|
|
|
_qmlScopeObjectSet(false)
|
2010-02-03 10:24:25 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Context::~Context()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-08-26 10:50:00 +02:00
|
|
|
// the engine is only guaranteed to live as long as the context
|
2010-02-03 10:24:25 +01:00
|
|
|
Engine *Context::engine() const
|
|
|
|
{
|
2010-08-26 10:50:00 +02:00
|
|
|
return _engine.data();
|
2010-02-03 10:24:25 +01:00
|
|
|
}
|
|
|
|
|
2010-02-19 10:14:34 +01:00
|
|
|
const ScopeChain &Context::scopeChain() const
|
|
|
|
{
|
|
|
|
return _scopeChain;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScopeChain &Context::scopeChain()
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
return _scopeChain;
|
|
|
|
}
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
const TypeEnvironment *Context::typeEnvironment(const QmlJS::Document *doc) const
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
2010-08-26 11:32:04 +02:00
|
|
|
if (!doc)
|
|
|
|
return 0;
|
2010-03-16 16:34:33 +01:00
|
|
|
return _typeEnvironments.value(doc->fileName(), 0);
|
2010-02-03 15:39:57 +01:00
|
|
|
}
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
void Context::setTypeEnvironment(const QmlJS::Document *doc, const TypeEnvironment *typeEnvironment)
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
2010-08-26 11:32:04 +02:00
|
|
|
if (!doc)
|
|
|
|
return;
|
2010-03-16 16:34:33 +01:00
|
|
|
_typeEnvironments[doc->fileName()] = typeEnvironment;
|
2010-02-03 15:39:57 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 14:05:34 +02:00
|
|
|
const Value *Context::lookup(const QString &name, const ObjectValue **foundInScope) const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
2010-02-22 10:21:07 +01:00
|
|
|
QList<const ObjectValue *> scopes = _scopeChain.all();
|
2010-02-19 10:14:34 +01:00
|
|
|
for (int index = scopes.size() - 1; index != -1; --index) {
|
|
|
|
const ObjectValue *scope = scopes.at(index);
|
2010-02-03 14:31:03 +01:00
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const Value *member = scope->lookupMember(name, this)) {
|
2010-09-24 14:05:34 +02:00
|
|
|
if (foundInScope)
|
|
|
|
*foundInScope = scope;
|
2010-06-25 13:01:55 +02:00
|
|
|
return member;
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-24 14:05:34 +02:00
|
|
|
if (foundInScope)
|
|
|
|
*foundInScope = 0;
|
2010-02-03 14:31:03 +01:00
|
|
|
return _engine->undefinedValue();
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const ObjectValue *Context::lookupType(const QmlJS::Document *doc, UiQualifiedId *qmlTypeName) const
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
2010-02-04 09:44:43 +01:00
|
|
|
const ObjectValue *objectValue = typeEnvironment(doc);
|
2010-05-11 15:26:54 +02:00
|
|
|
if (!objectValue)
|
|
|
|
return 0;
|
2010-02-03 15:39:57 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const ObjectValue *Context::lookupType(const QmlJS::Document *doc, const QStringList &qmlTypeName) const
|
2010-04-29 11:41:28 +02:00
|
|
|
{
|
|
|
|
const ObjectValue *objectValue = typeEnvironment(doc);
|
|
|
|
|
|
|
|
foreach (const QString &name, qmlTypeName) {
|
2010-06-04 10:14:22 +02:00
|
|
|
if (!objectValue)
|
|
|
|
return 0;
|
|
|
|
|
2010-04-29 11:41:28 +02:00
|
|
|
const Value *value = objectValue->property(name, this);
|
|
|
|
if (!value)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
objectValue = value->asObjectValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
return objectValue;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *Context::lookupReference(const Reference *reference) const
|
2010-06-08 15:36:06 +02:00
|
|
|
{
|
|
|
|
if (_referenceStack.contains(reference))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
_referenceStack.append(reference);
|
|
|
|
const Value *v = reference->value(this);
|
|
|
|
_referenceStack.removeLast();
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
const Value *Context::property(const ObjectValue *object, const QString &name) const
|
|
|
|
{
|
|
|
|
const Properties properties = _properties.value(object);
|
|
|
|
return properties.value(name, engine()->undefinedValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Context::setProperty(const ObjectValue *object, const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
_properties[object].insert(name, value);
|
|
|
|
}
|
|
|
|
|
2010-08-26 10:50:00 +02:00
|
|
|
QString Context::defaultPropertyName(const ObjectValue *object) const
|
2010-05-31 12:21:12 +02:00
|
|
|
{
|
2010-11-12 14:53:00 +01:00
|
|
|
PrototypeIterator iter(object, this);
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const ObjectValue *o = iter.next();
|
2010-05-31 12:21:12 +02:00
|
|
|
if (const ASTObjectValue *astObjValue = dynamic_cast<const ASTObjectValue *>(o)) {
|
|
|
|
QString defaultProperty = astObjValue->defaultPropertyName();
|
|
|
|
if (!defaultProperty.isEmpty())
|
|
|
|
return defaultProperty;
|
|
|
|
} else if (const QmlObjectValue *qmlValue = dynamic_cast<const QmlObjectValue *>(o)) {
|
|
|
|
return qmlValue->defaultPropertyName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-02-03 14:31:03 +01:00
|
|
|
Reference::Reference(Engine *engine)
|
|
|
|
: _engine(engine)
|
2010-02-03 10:24:25 +01:00
|
|
|
{
|
2010-02-03 14:31:03 +01:00
|
|
|
_engine->registerValue(this);
|
2010-02-03 10:24:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Reference::~Reference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-03 14:31:03 +01:00
|
|
|
Engine *Reference::engine() const
|
|
|
|
{
|
|
|
|
return _engine;
|
|
|
|
}
|
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
const Reference *Reference::asReference() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Reference::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *Reference::value(const Context *) const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
return _engine->undefinedValue();
|
|
|
|
}
|
2010-02-03 10:24:25 +01:00
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
void ColorValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ColorValue *ColorValue::asColorValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
void AnchorLineValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AnchorLineValue *AnchorLineValue::asAnchorLineValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:10:11 +01:00
|
|
|
MemberProcessor::MemberProcessor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MemberProcessor::~MemberProcessor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemberProcessor::processProperty(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-28 15:50:58 +01:00
|
|
|
bool MemberProcessor::processEnumerator(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:10:11 +01:00
|
|
|
bool MemberProcessor::processSignal(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemberProcessor::processSlot(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:19:42 +01:00
|
|
|
bool MemberProcessor::processGeneratedSlot(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
ObjectValue::ObjectValue(Engine *engine)
|
2010-01-28 14:11:56 +01:00
|
|
|
: _engine(engine),
|
2010-02-03 10:59:52 +01:00
|
|
|
_prototype(0)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-02-03 14:31:03 +01:00
|
|
|
engine->registerValue(this);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue::~ObjectValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Engine *ObjectValue::engine() const
|
|
|
|
{
|
|
|
|
return _engine;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ObjectValue::className() const
|
|
|
|
{
|
|
|
|
return _className;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::setClassName(const QString &className)
|
|
|
|
{
|
|
|
|
_className = className;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const ObjectValue *ObjectValue::prototype(const Context *context) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
const ObjectValue *prototypeObject = value_cast<const ObjectValue *>(_prototype);
|
|
|
|
if (! prototypeObject) {
|
|
|
|
if (const Reference *prototypeReference = value_cast<const Reference *>(_prototype)) {
|
2010-06-08 15:36:06 +02:00
|
|
|
prototypeObject = value_cast<const ObjectValue *>(context->lookupReference(prototypeReference));
|
2010-02-03 15:39:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return prototypeObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::setPrototype(const Value *prototype)
|
|
|
|
{
|
|
|
|
// ### FIXME: Check for cycles.
|
|
|
|
_prototype = prototype;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::setProperty(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
_members[name] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::removeProperty(const QString &name)
|
|
|
|
{
|
|
|
|
_members.remove(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *ObjectValue::asObjectValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ObjectValue::property(const QString &name, const Context *context) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
return lookupMember(name, context);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
bool ObjectValue::checkPrototype(const ObjectValue *, QSet<const ObjectValue *> *) const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
#if 0
|
2010-01-21 15:54:19 +01:00
|
|
|
const int previousSize = processed->size();
|
|
|
|
processed->insert(this);
|
|
|
|
|
|
|
|
if (previousSize != processed->size()) {
|
|
|
|
if (this == proto)
|
|
|
|
return false;
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
if (prototype() && ! prototype()->checkPrototype(proto, processed))
|
2010-01-21 15:54:19 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2010-02-03 15:39:57 +01:00
|
|
|
#endif
|
2010-01-21 15:54:19 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ObjectValue::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
|
|
|
QHashIterator<QString, const Value *> it(_members);
|
|
|
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
|
2010-01-26 10:10:11 +01:00
|
|
|
if (! processor->processProperty(it.key(), it.value()))
|
2010-01-24 11:10:01 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ObjectValue::lookupMember(const QString &name, const Context *context, bool examinePrototypes) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-01-24 13:29:46 +01:00
|
|
|
if (const Value *m = _members.value(name))
|
2010-01-24 11:10:01 +01:00
|
|
|
return m;
|
2010-02-01 13:54:44 +01:00
|
|
|
else {
|
|
|
|
LookupMember slowLookup(name);
|
|
|
|
processMembers(&slowLookup);
|
|
|
|
if (slowLookup.value())
|
|
|
|
return slowLookup.value();
|
|
|
|
}
|
2010-01-24 11:10:01 +01:00
|
|
|
|
2010-04-06 11:44:55 +02:00
|
|
|
if (examinePrototypes) {
|
2010-11-12 14:53:00 +01:00
|
|
|
PrototypeIterator iter(this, context);
|
|
|
|
iter.next(); // skip this
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const ObjectValue *prototypeObject = iter.next();
|
|
|
|
if (const Value *m = prototypeObject->lookupMember(name, context, false))
|
2010-04-06 11:44:55 +02:00
|
|
|
return m;
|
|
|
|
}
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-12 14:53:00 +01:00
|
|
|
PrototypeIterator::PrototypeIterator(const ObjectValue *start, const Context *context)
|
|
|
|
: m_current(0)
|
|
|
|
, m_next(start)
|
|
|
|
, m_context(context)
|
|
|
|
{
|
|
|
|
if (start)
|
|
|
|
m_prototypes.reserve(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PrototypeIterator::hasNext()
|
|
|
|
{
|
|
|
|
if (m_next)
|
|
|
|
return true;
|
|
|
|
if (!m_current)
|
|
|
|
return false;
|
|
|
|
m_next = m_current->prototype(m_context);
|
|
|
|
if (!m_next || m_prototypes.contains(m_next)) {
|
|
|
|
m_next = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *PrototypeIterator::next()
|
|
|
|
{
|
|
|
|
if (hasNext()) {
|
|
|
|
m_current = m_next;
|
|
|
|
m_prototypes += m_next;
|
|
|
|
m_next = 0;
|
|
|
|
return m_current;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *PrototypeIterator::peekNext()
|
|
|
|
{
|
|
|
|
if (hasNext()) {
|
|
|
|
return m_next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<const ObjectValue *> PrototypeIterator::all()
|
|
|
|
{
|
|
|
|
while (hasNext())
|
|
|
|
next();
|
|
|
|
return m_prototypes;
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
Activation::Activation(Context *parentContext)
|
2010-01-28 14:11:56 +01:00
|
|
|
: _thisObject(0),
|
2010-02-03 15:39:57 +01:00
|
|
|
_calledAsFunction(true),
|
|
|
|
_parentContext(parentContext)
|
2010-01-24 11:35:11 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Activation::~Activation()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
Context *Activation::parentContext() const
|
|
|
|
{
|
|
|
|
return _parentContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context *Activation::context() const
|
|
|
|
{
|
|
|
|
// ### FIXME: Real context for activations.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
bool Activation::calledAsConstructor() const
|
|
|
|
{
|
|
|
|
return ! _calledAsFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setCalledAsConstructor(bool calledAsConstructor)
|
|
|
|
{
|
|
|
|
_calledAsFunction = ! calledAsConstructor;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Activation::calledAsFunction() const
|
|
|
|
{
|
|
|
|
return _calledAsFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setCalledAsFunction(bool calledAsFunction)
|
|
|
|
{
|
|
|
|
_calledAsFunction = calledAsFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Activation::thisObject() const
|
|
|
|
{
|
|
|
|
return _thisObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setThisObject(ObjectValue *thisObject)
|
|
|
|
{
|
|
|
|
_thisObject = thisObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueList Activation::arguments() const
|
|
|
|
{
|
|
|
|
return _arguments;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setArguments(const ValueList &arguments)
|
|
|
|
{
|
|
|
|
_arguments = arguments;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
FunctionValue::FunctionValue(Engine *engine)
|
|
|
|
: ObjectValue(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionValue::~FunctionValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::construct(const ValueList &actuals) const
|
|
|
|
{
|
2010-01-28 14:11:56 +01:00
|
|
|
Activation activation;
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setCalledAsConstructor(true);
|
|
|
|
activation.setThisObject(engine()->newObject());
|
|
|
|
activation.setArguments(actuals);
|
|
|
|
return invoke(&activation);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::call(const ValueList &actuals) const
|
|
|
|
{
|
2010-01-28 14:11:56 +01:00
|
|
|
Activation activation;
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setCalledAsFunction(true);
|
|
|
|
activation.setThisObject(engine()->globalObject()); // ### FIXME: it should be `null'
|
|
|
|
activation.setArguments(actuals);
|
|
|
|
return invoke(&activation);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::call(const ObjectValue *thisObject, const ValueList &actuals) const
|
|
|
|
{
|
2010-01-28 14:11:56 +01:00
|
|
|
Activation activation;
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setCalledAsFunction(true);
|
|
|
|
activation.setThisObject(const_cast<ObjectValue *>(thisObject)); // ### FIXME: remove the const_cast
|
|
|
|
activation.setArguments(actuals);
|
|
|
|
return invoke(&activation);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 10:50:30 +01:00
|
|
|
const Value *FunctionValue::returnValue() const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
int FunctionValue::argumentCount() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:50:30 +01:00
|
|
|
const Value *FunctionValue::argument(int) const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString FunctionValue::argumentName(int index) const
|
|
|
|
{
|
2010-02-01 12:43:36 +01:00
|
|
|
return QString::fromLatin1("arg%1").arg(index + 1);
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionValue::isVariadic() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::invoke(const Activation *activation) const
|
|
|
|
{
|
|
|
|
return activation->thisObject(); // ### FIXME: it should return undefined
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const FunctionValue *FunctionValue::asFunctionValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FunctionValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
Function::Function(Engine *engine)
|
|
|
|
: FunctionValue(engine), _returnValue(0)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
setClassName("Function");
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
Function::~Function()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void Function::addArgument(const Value *argument)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_arguments.push_back(argument);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *Function::returnValue() const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
return _returnValue;
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void Function::setReturnValue(const Value *returnValue)
|
|
|
|
{
|
|
|
|
_returnValue = returnValue;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
int Function::argumentCount() const
|
|
|
|
{
|
|
|
|
return _arguments.size();
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *Function::argument(int index) const
|
|
|
|
{
|
|
|
|
return _arguments.at(index);
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *Function::property(const QString &name, const Context *context) const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
|
|
|
if (name == "length")
|
|
|
|
return engine()->numberValue();
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
return FunctionValue::property(name, context);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *Function::invoke(const Activation *activation) const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
return activation->thisObject(); // ### FIXME it should return undefined
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// typing environment
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-06-10 10:48:23 +02:00
|
|
|
QList<const FakeMetaObject *> CppQmlTypesLoader::builtinObjects;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-06-01 15:10:20 +02:00
|
|
|
QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles)
|
|
|
|
{
|
|
|
|
QMap<QString, FakeMetaObject *> newObjects;
|
2010-03-01 13:01:05 +01:00
|
|
|
QStringList errorMsgs;
|
|
|
|
|
|
|
|
foreach (const QFileInfo &xmlFile, xmlFiles) {
|
|
|
|
QFile file(xmlFile.absoluteFilePath());
|
|
|
|
if (file.open(QIODevice::ReadOnly)) {
|
|
|
|
QmlXmlReader read(&file);
|
2010-06-01 15:10:20 +02:00
|
|
|
if (!read(&newObjects)) {
|
2010-03-01 13:01:05 +01:00
|
|
|
errorMsgs.append(read.errorMessage());
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
} else {
|
2010-05-19 13:32:11 +02:00
|
|
|
errorMsgs.append(QmlXmlReader::tr("%1: %2").arg(xmlFile.absoluteFilePath(),
|
|
|
|
file.errorString()));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
if (errorMsgs.isEmpty()) {
|
|
|
|
setSuperClasses(&newObjects);
|
2010-06-01 15:10:20 +02:00
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
// we need to go from QList<T *> of newObjects.values() to QList<const T *>
|
|
|
|
// and there seems to be no better way
|
|
|
|
QMapIterator<QString, FakeMetaObject *> it(newObjects);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
2010-06-10 10:48:23 +02:00
|
|
|
builtinObjects.append(it.value());
|
2010-06-09 14:27:30 +02:00
|
|
|
}
|
|
|
|
}
|
2010-06-02 15:07:27 +02:00
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
return errorMsgs;
|
2010-06-01 15:10:20 +02:00
|
|
|
}
|
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
QString CppQmlTypesLoader::parseQmlTypeXml(const QByteArray &xml, QMap<QString, FakeMetaObject *> *newObjects)
|
2010-06-01 15:10:20 +02:00
|
|
|
{
|
2010-06-09 14:27:30 +02:00
|
|
|
QmlXmlReader reader(xml);
|
|
|
|
if (!reader(newObjects)) {
|
|
|
|
if (reader.errorMessage().isEmpty())
|
|
|
|
return QLatin1String("unknown error");
|
|
|
|
return reader.errorMessage();
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
2010-06-09 14:27:30 +02:00
|
|
|
setSuperClasses(newObjects);
|
|
|
|
return QString();
|
2010-06-01 15:10:20 +02:00
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
void CppQmlTypesLoader::setSuperClasses(QMap<QString, FakeMetaObject *> *newObjects)
|
2010-06-01 15:10:20 +02:00
|
|
|
{
|
2010-06-09 14:27:30 +02:00
|
|
|
QMapIterator<QString, FakeMetaObject *> it(*newObjects);
|
2010-06-01 15:10:20 +02:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
FakeMetaObject *obj = it.value();
|
|
|
|
|
|
|
|
const QString superName = obj->superclassName();
|
|
|
|
if (! superName.isEmpty()) {
|
2010-06-09 14:27:30 +02:00
|
|
|
FakeMetaObject *superClass = newObjects->value(superName);
|
2010-06-01 15:10:20 +02:00
|
|
|
if (superClass)
|
|
|
|
obj->setSuperclass(superClass);
|
2010-06-09 14:27:30 +02:00
|
|
|
else
|
|
|
|
qWarning() << "QmlJS::Interpreter::MetaTypeSystem: Can't find superclass" << superName << "for" << it.key();
|
2010-06-01 15:10:20 +02:00
|
|
|
}
|
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
2010-06-09 15:46:54 +02:00
|
|
|
void CppQmlTypes::load(Engine *engine, const QList<const FakeMetaObject *> &objects)
|
2010-03-01 13:01:05 +01:00
|
|
|
{
|
2010-06-09 14:27:30 +02:00
|
|
|
// load
|
|
|
|
foreach (const FakeMetaObject *metaObject, objects) {
|
2010-09-30 11:21:23 +02:00
|
|
|
for (int i = 0; i < metaObject->exports().size(); ++i) {
|
|
|
|
const FakeMetaObject::Export &exp = metaObject->exports().at(i);
|
|
|
|
// make sure we're not loading duplicate objects
|
|
|
|
if (_typesByFullyQualifiedName.contains(exp.packageNameVersion))
|
|
|
|
continue;
|
|
|
|
|
2010-10-19 16:15:32 +02:00
|
|
|
QmlObjectValue *objectValue = new QmlObjectValue(
|
|
|
|
metaObject, exp.type, exp.package, exp.version, engine);
|
2010-09-30 11:21:23 +02:00
|
|
|
_typesByPackage[exp.package].append(objectValue);
|
|
|
|
_typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
|
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
2010-10-19 16:15:32 +02:00
|
|
|
// set prototypes
|
2010-06-09 14:27:30 +02:00
|
|
|
foreach (const FakeMetaObject *metaObject, objects) {
|
2010-09-30 11:21:23 +02:00
|
|
|
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
|
|
|
|
QmlObjectValue *objectValue = _typesByFullyQualifiedName.value(exp.packageNameVersion);
|
|
|
|
if (!objectValue || !metaObject->superClass())
|
|
|
|
continue;
|
2010-10-19 16:15:32 +02:00
|
|
|
|
|
|
|
// set prototypes for whole chain, creating new QmlObjectValues if necessary
|
|
|
|
// for instance, if an type isn't exported in the package of the super type
|
|
|
|
// Example: QObject (Qt, QtQuick) -> Positioner (not exported) -> Column (Qt, QtQuick)
|
|
|
|
// needs to create Positioner (Qt) and Positioner (QtQuick)
|
|
|
|
bool created = true;
|
|
|
|
QmlObjectValue *v = objectValue;
|
|
|
|
const FakeMetaObject *fmo = metaObject;
|
|
|
|
while (created && fmo->superClass()) {
|
|
|
|
QmlObjectValue *superValue = getOrCreate(exp.package, fmo->superclassName(),
|
|
|
|
fmo->superClass(), engine, &created);
|
|
|
|
v->setPrototype(superValue);
|
|
|
|
v = superValue;
|
|
|
|
fmo = fmo->superClass();
|
2010-09-30 11:21:23 +02:00
|
|
|
}
|
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-02 15:27:39 +02:00
|
|
|
QList<QmlObjectValue *> CppQmlTypes::typesForImport(const QString &packageName, QmlJS::ComponentVersion version) const
|
2010-03-01 13:01:05 +01:00
|
|
|
{
|
|
|
|
QMap<QString, QmlObjectValue *> objectValuesByName;
|
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
foreach (QmlObjectValue *qmlObjectValue, _typesByPackage.value(packageName)) {
|
2010-06-01 15:36:52 +02:00
|
|
|
if (qmlObjectValue->version() <= version) {
|
2010-03-01 13:01:05 +01:00
|
|
|
// we got a candidate.
|
|
|
|
const QString typeName = qmlObjectValue->className();
|
|
|
|
QmlObjectValue *previousCandidate = objectValuesByName.value(typeName, 0);
|
|
|
|
if (previousCandidate) {
|
|
|
|
// check if our new candidate is newer than the one we found previously
|
2010-06-01 15:36:52 +02:00
|
|
|
if (previousCandidate->version() < qmlObjectValue->version()) {
|
2010-03-01 13:01:05 +01:00
|
|
|
// the new candidate has a higher version no. than the one we found previously, so replace it
|
|
|
|
objectValuesByName.insert(typeName, qmlObjectValue);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
objectValuesByName.insert(typeName, qmlObjectValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return objectValuesByName.values();
|
|
|
|
}
|
|
|
|
|
2010-11-11 11:11:48 +01:00
|
|
|
QmlObjectValue *CppQmlTypes::typeForImport(const QString &qualifiedName,
|
|
|
|
QmlJS::ComponentVersion version) const
|
2010-03-01 13:01:05 +01:00
|
|
|
{
|
|
|
|
QString name = qualifiedName;
|
|
|
|
QString packageName;
|
|
|
|
int dotIdx = name.indexOf(QLatin1Char('.'));
|
|
|
|
if (dotIdx != -1) {
|
|
|
|
packageName = name.left(dotIdx);
|
|
|
|
name = name.mid(dotIdx + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlObjectValue *previousCandidate = 0;
|
2010-06-09 14:27:30 +02:00
|
|
|
foreach (QmlObjectValue *qmlObjectValue, _typesByPackage.value(packageName)) {
|
2010-03-01 13:01:05 +01:00
|
|
|
const QString typeName = qmlObjectValue->className();
|
|
|
|
if (typeName != name)
|
|
|
|
continue;
|
2010-11-11 11:11:48 +01:00
|
|
|
if (version.isValid() && version < qmlObjectValue->version())
|
|
|
|
continue;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
|
|
|
if (previousCandidate) {
|
|
|
|
// check if our new candidate is newer than the one we found previously
|
2010-06-01 15:36:52 +02:00
|
|
|
if (previousCandidate->version() < qmlObjectValue->version()) {
|
2010-03-01 13:01:05 +01:00
|
|
|
// the new candidate has a higher version no. than the one we found previously, so replace it
|
|
|
|
previousCandidate = qmlObjectValue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
previousCandidate = qmlObjectValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return previousCandidate;
|
|
|
|
}
|
|
|
|
|
2010-06-01 15:10:20 +02:00
|
|
|
bool CppQmlTypes::hasPackage(const QString &package) const
|
2010-03-16 16:34:33 +01:00
|
|
|
{
|
2010-06-09 14:27:30 +02:00
|
|
|
return _typesByPackage.contains(package);
|
2010-03-16 16:34:33 +01:00
|
|
|
}
|
|
|
|
|
2010-10-19 16:15:32 +02:00
|
|
|
QString CppQmlTypes::qualifiedName(const QString &package, const QString &type, QmlJS::ComponentVersion version)
|
|
|
|
{
|
|
|
|
return QString("%1.%2 %3.%4").arg(
|
|
|
|
package, type,
|
|
|
|
QString::number(version.majorVersion()),
|
|
|
|
QString::number(version.minorVersion()));
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const
|
|
|
|
{
|
|
|
|
return _typesByFullyQualifiedName.value(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const QString &type, QmlJS::ComponentVersion version) const
|
|
|
|
{
|
|
|
|
return typeByQualifiedName(qualifiedName(package, type, version));
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &cppName,
|
|
|
|
const FakeMetaObject *metaObject, Engine *engine, bool *created)
|
|
|
|
{
|
|
|
|
QString typeName = cppName;
|
|
|
|
ComponentVersion version;
|
|
|
|
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
|
|
|
|
if (exp.package == package) {
|
|
|
|
typeName = exp.type;
|
|
|
|
version = exp.version;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString qName = qualifiedName(package, typeName, version);
|
|
|
|
QmlObjectValue *value = typeByQualifiedName(qName);
|
|
|
|
if (!value) {
|
|
|
|
*created = true;
|
|
|
|
value = new QmlObjectValue(
|
|
|
|
metaObject, typeName, package, QmlJS::ComponentVersion(), engine);
|
|
|
|
_typesByFullyQualifiedName[qName] = value;
|
|
|
|
} else {
|
|
|
|
*created = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
ConvertToNumber::ConvertToNumber(Engine *engine)
|
|
|
|
: _engine(engine), _result(0)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToNumber::operator()(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousValue = switchResult(0);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return switchResult(previousValue);
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToNumber::switchResult(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousResult = _result;
|
|
|
|
_result = value;
|
|
|
|
return previousResult;
|
|
|
|
}
|
|
|
|
|
2010-01-26 15:12:47 +01:00
|
|
|
void ConvertToNumber::visit(const NullValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->numberValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const UndefinedValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->numberValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const NumberValue *value)
|
|
|
|
{
|
|
|
|
_result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const BooleanValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->numberValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const StringValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->numberValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const ObjectValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const NumberValue *>(valueOfMember->call(object)); // ### invoke convert-to-number?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const FunctionValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const NumberValue *>(valueOfMember->call(object)); // ### invoke convert-to-number?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
ConvertToString::ConvertToString(Engine *engine)
|
|
|
|
: _engine(engine), _result(0)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToString::operator()(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousValue = switchResult(0);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return switchResult(previousValue);
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToString::switchResult(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousResult = _result;
|
|
|
|
_result = value;
|
|
|
|
return previousResult;
|
|
|
|
}
|
|
|
|
|
2010-01-26 15:12:47 +01:00
|
|
|
void ConvertToString::visit(const NullValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->stringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const UndefinedValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->stringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const NumberValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->stringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const BooleanValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->stringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const StringValue *value)
|
|
|
|
{
|
|
|
|
_result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const ObjectValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const StringValue *>(toStringMember->call(object)); // ### invoke convert-to-string?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const FunctionValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const StringValue *>(toStringMember->call(object)); // ### invoke convert-to-string?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-22 14:42:15 +01:00
|
|
|
ConvertToObject::ConvertToObject(Engine *engine)
|
|
|
|
: _engine(engine), _result(0)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToObject::operator()(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousValue = switchResult(0);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return switchResult(previousValue);
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToObject::switchResult(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousResult = _result;
|
|
|
|
_result = value;
|
|
|
|
return previousResult;
|
|
|
|
}
|
|
|
|
|
2010-01-22 14:42:15 +01:00
|
|
|
void ConvertToObject::visit(const NullValue *value)
|
|
|
|
{
|
|
|
|
_result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToObject::visit(const UndefinedValue *)
|
|
|
|
{
|
|
|
|
_result = _engine->nullValue();
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ConvertToObject::visit(const NumberValue *value)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueList actuals;
|
|
|
|
actuals.append(value);
|
|
|
|
_result = _engine->numberCtor()->construct(actuals);
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ConvertToObject::visit(const BooleanValue *value)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueList actuals;
|
|
|
|
actuals.append(value);
|
|
|
|
_result = _engine->booleanCtor()->construct(actuals);
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ConvertToObject::visit(const StringValue *value)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueList actuals;
|
|
|
|
actuals.append(value);
|
|
|
|
_result = _engine->stringCtor()->construct(actuals);
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToObject::visit(const ObjectValue *object)
|
|
|
|
{
|
|
|
|
_result = object;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToObject::visit(const FunctionValue *object)
|
|
|
|
{
|
|
|
|
_result = object;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
QString TypeId::operator()(const Value *value)
|
|
|
|
{
|
|
|
|
_result = QLatin1String("unknown");
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return _result;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const NullValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("null");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const UndefinedValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("undefined");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const NumberValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("number");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const BooleanValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("boolean");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const StringValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("string");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const ObjectValue *object)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = object->className();
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
if (_result.isEmpty())
|
|
|
|
_result = QLatin1String("object");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const FunctionValue *object)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = object->className();
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
if (_result.isEmpty())
|
|
|
|
_result = QLatin1String("Function");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
void TypeId::visit(const ColorValue *)
|
|
|
|
{
|
|
|
|
_result = QLatin1String("string");
|
|
|
|
}
|
|
|
|
|
|
|
|
void TypeId::visit(const AnchorLineValue *)
|
|
|
|
{
|
|
|
|
_result = QLatin1String("AnchorLine");
|
|
|
|
}
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
Engine::Engine()
|
|
|
|
: _objectPrototype(0),
|
|
|
|
_functionPrototype(0),
|
|
|
|
_numberPrototype(0),
|
|
|
|
_booleanPrototype(0),
|
|
|
|
_stringPrototype(0),
|
|
|
|
_arrayPrototype(0),
|
|
|
|
_datePrototype(0),
|
|
|
|
_regexpPrototype(0),
|
|
|
|
_objectCtor(0),
|
|
|
|
_functionCtor(0),
|
|
|
|
_arrayCtor(0),
|
|
|
|
_stringCtor(0),
|
|
|
|
_booleanCtor(0),
|
|
|
|
_numberCtor(0),
|
|
|
|
_dateCtor(0),
|
|
|
|
_regexpCtor(0),
|
|
|
|
_globalObject(0),
|
|
|
|
_mathObject(0),
|
2010-02-10 15:51:21 +01:00
|
|
|
_qtObject(0),
|
2010-01-26 11:06:28 +01:00
|
|
|
_qmlKeysObject(0),
|
2010-09-24 14:01:10 +02:00
|
|
|
_qmlFontObject(0),
|
|
|
|
_qmlPointObject(0),
|
|
|
|
_qmlSizeObject(0),
|
|
|
|
_qmlRectObject(0),
|
|
|
|
_qmlVector3DObject(0),
|
2010-01-21 15:54:19 +01:00
|
|
|
_convertToNumber(this),
|
|
|
|
_convertToString(this),
|
|
|
|
_convertToObject(this)
|
|
|
|
{
|
|
|
|
initializePrototypes();
|
2010-01-26 14:50:52 +01:00
|
|
|
|
2010-06-10 10:48:23 +02:00
|
|
|
_cppQmlTypes.load(this, CppQmlTypesLoader::builtinObjects);
|
2010-10-19 11:08:09 +02:00
|
|
|
|
|
|
|
// the 'Qt' object is dumped even though it is not exported
|
|
|
|
// it contains useful information, in particular on enums - add the
|
|
|
|
// object as a prototype to our custom Qt object to offer these for completion
|
|
|
|
_qtObject->setPrototype(_cppQmlTypes.typeForImport(QLatin1String("Qt")));
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
Engine::~Engine()
|
|
|
|
{
|
2010-02-03 14:31:03 +01:00
|
|
|
qDeleteAll(_registeredValues);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const NullValue *Engine::nullValue() const
|
|
|
|
{
|
|
|
|
return &_nullValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const UndefinedValue *Engine::undefinedValue() const
|
|
|
|
{
|
|
|
|
return &_undefinedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const NumberValue *Engine::numberValue() const
|
|
|
|
{
|
|
|
|
return &_numberValue;
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:31:20 +01:00
|
|
|
const RealValue *Engine::realValue() const
|
|
|
|
{
|
|
|
|
return &_realValue;
|
|
|
|
}
|
2010-11-11 16:04:55 +01:00
|
|
|
|
2010-11-10 16:31:20 +01:00
|
|
|
const IntValue *Engine::intValue() const
|
|
|
|
{
|
|
|
|
return &_intValue;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const BooleanValue *Engine::booleanValue() const
|
|
|
|
{
|
|
|
|
return &_booleanValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringValue *Engine::stringValue() const
|
|
|
|
{
|
|
|
|
return &_stringValue;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-11-11 16:04:55 +01:00
|
|
|
const UrlValue *Engine::urlValue() const
|
|
|
|
{
|
|
|
|
return &_urlValue;
|
|
|
|
}
|
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
const ColorValue *Engine::colorValue() const
|
|
|
|
{
|
|
|
|
return &_colorValue;
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
const AnchorLineValue *Engine::anchorLineValue() const
|
|
|
|
{
|
|
|
|
return &_anchorLineValue;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *Engine::newArray()
|
|
|
|
{
|
|
|
|
return arrayCtor()->construct();
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
ObjectValue *Engine::newObject()
|
|
|
|
{
|
|
|
|
return newObject(_objectPrototype);
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::newObject(const ObjectValue *prototype)
|
|
|
|
{
|
|
|
|
ObjectValue *object = new ObjectValue(this);
|
|
|
|
object->setPrototype(prototype);
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2010-01-28 14:11:56 +01:00
|
|
|
Function *Engine::newFunction()
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
Function *function = new Function(this);
|
|
|
|
function->setPrototype(functionPrototype());
|
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
ObjectValue *Engine::globalObject() const
|
|
|
|
{
|
|
|
|
return _globalObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::objectPrototype() const
|
|
|
|
{
|
|
|
|
return _objectPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::functionPrototype() const
|
|
|
|
{
|
|
|
|
return _functionPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::numberPrototype() const
|
|
|
|
{
|
|
|
|
return _numberPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::booleanPrototype() const
|
|
|
|
{
|
|
|
|
return _booleanPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::stringPrototype() const
|
|
|
|
{
|
|
|
|
return _stringPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::arrayPrototype() const
|
|
|
|
{
|
|
|
|
return _arrayPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::datePrototype() const
|
|
|
|
{
|
|
|
|
return _datePrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Engine::regexpPrototype() const
|
|
|
|
{
|
|
|
|
return _regexpPrototype;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::objectCtor() const
|
|
|
|
{
|
|
|
|
return _objectCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::functionCtor() const
|
|
|
|
{
|
|
|
|
return _functionCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::arrayCtor() const
|
|
|
|
{
|
|
|
|
return _arrayCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::stringCtor() const
|
|
|
|
{
|
|
|
|
return _stringCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::booleanCtor() const
|
|
|
|
{
|
|
|
|
return _booleanCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::numberCtor() const
|
|
|
|
{
|
|
|
|
return _numberCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::dateCtor() const
|
|
|
|
{
|
|
|
|
return _dateCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Engine::regexpCtor() const
|
|
|
|
{
|
|
|
|
return _regexpCtor;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *Engine::mathObject() const
|
|
|
|
{
|
|
|
|
return _mathObject;
|
|
|
|
}
|
|
|
|
|
2010-02-10 15:51:21 +01:00
|
|
|
const ObjectValue *Engine::qtObject() const
|
|
|
|
{
|
|
|
|
return _qtObject;
|
|
|
|
}
|
|
|
|
|
2010-02-03 14:31:03 +01:00
|
|
|
void Engine::registerValue(Value *value)
|
2010-01-26 10:50:30 +01:00
|
|
|
{
|
2010-09-24 13:54:28 +02:00
|
|
|
QMutexLocker locker(&_mutex);
|
2010-02-03 14:31:03 +01:00
|
|
|
_registeredValues.append(value);
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *Engine::convertToBoolean(const Value *value)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
|
|
|
return _convertToNumber(value); // ### implement convert to bool
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *Engine::convertToNumber(const Value *value)
|
|
|
|
{
|
|
|
|
return _convertToNumber(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *Engine::convertToString(const Value *value)
|
|
|
|
{
|
|
|
|
return _convertToString(value);
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *Engine::convertToObject(const Value *value)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
return _convertToObject(value);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
QString Engine::typeId(const Value *value)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
return _typeId(value);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount)
|
|
|
|
{
|
|
|
|
Function *function = newFunction();
|
|
|
|
function->setReturnValue(result);
|
|
|
|
for (int i = 0; i < argumentCount; ++i)
|
|
|
|
function->addArgument(undefinedValue()); // ### introduce unknownValue
|
|
|
|
object->setProperty(name, function);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::addFunction(ObjectValue *object, const QString &name, int argumentCount)
|
|
|
|
{
|
|
|
|
Function *function = newFunction();
|
|
|
|
for (int i = 0; i < argumentCount; ++i)
|
|
|
|
function->addArgument(undefinedValue()); // ### introduce unknownValue
|
|
|
|
object->setProperty(name, function);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::initializePrototypes()
|
|
|
|
{
|
|
|
|
_objectPrototype = newObject(/*prototype = */ 0);
|
|
|
|
_functionPrototype = newObject(_objectPrototype);
|
|
|
|
_numberPrototype = newObject(_objectPrototype);
|
|
|
|
_booleanPrototype = newObject(_objectPrototype);
|
|
|
|
_stringPrototype = newObject(_objectPrototype);
|
|
|
|
_arrayPrototype = newObject(_objectPrototype);
|
|
|
|
_datePrototype = newObject(_objectPrototype);
|
|
|
|
_regexpPrototype = newObject(_objectPrototype);
|
|
|
|
|
|
|
|
// set up the Global object
|
|
|
|
_globalObject = newObject();
|
|
|
|
_globalObject->setClassName("Global");
|
|
|
|
|
|
|
|
// set up the default Object prototype
|
|
|
|
_objectCtor = new ObjectCtor(this);
|
|
|
|
_objectCtor->setPrototype(_functionPrototype);
|
|
|
|
_objectCtor->setProperty("prototype", _objectPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_objectCtor->setReturnValue(newObject());
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_functionCtor = new FunctionCtor(this);
|
|
|
|
_functionCtor->setPrototype(_functionPrototype);
|
|
|
|
_functionCtor->setProperty("prototype", _functionPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_functionCtor->setReturnValue(newFunction());
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_arrayCtor = new ArrayCtor(this);
|
|
|
|
_arrayCtor->setPrototype(_functionPrototype);
|
|
|
|
_arrayCtor->setProperty("prototype", _arrayPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_arrayCtor->setReturnValue(newArray());
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_stringCtor = new StringCtor(this);
|
|
|
|
_stringCtor->setPrototype(_functionPrototype);
|
|
|
|
_stringCtor->setProperty("prototype", _stringPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_stringCtor->setReturnValue(stringValue());
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_booleanCtor = new BooleanCtor(this);
|
|
|
|
_booleanCtor->setPrototype(_functionPrototype);
|
|
|
|
_booleanCtor->setProperty("prototype", _booleanPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_booleanCtor->setReturnValue(booleanValue());
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_numberCtor = new NumberCtor(this);
|
|
|
|
_numberCtor->setPrototype(_functionPrototype);
|
|
|
|
_numberCtor->setProperty("prototype", _numberPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_numberCtor->setReturnValue(numberValue());
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_dateCtor = new DateCtor(this);
|
|
|
|
_dateCtor->setPrototype(_functionPrototype);
|
|
|
|
_dateCtor->setProperty("prototype", _datePrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_dateCtor->setReturnValue(_datePrototype);
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
_regexpCtor = new RegExpCtor(this);
|
|
|
|
_regexpCtor->setPrototype(_functionPrototype);
|
|
|
|
_regexpCtor->setProperty("prototype", _regexpPrototype);
|
2010-06-28 09:49:45 +02:00
|
|
|
_regexpCtor->setReturnValue(_regexpPrototype);
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
addFunction(_objectCtor, "getPrototypeOf", 1);
|
|
|
|
addFunction(_objectCtor, "getOwnPropertyDescriptor", 2);
|
2010-01-24 11:10:01 +01:00
|
|
|
addFunction(_objectCtor, "getOwnPropertyNames", newArray(), 1);
|
2010-01-21 15:54:19 +01:00
|
|
|
addFunction(_objectCtor, "create", 1);
|
|
|
|
addFunction(_objectCtor, "defineProperty", 3);
|
|
|
|
addFunction(_objectCtor, "defineProperties", 2);
|
|
|
|
addFunction(_objectCtor, "seal", 1);
|
|
|
|
addFunction(_objectCtor, "freeze", 1);
|
|
|
|
addFunction(_objectCtor, "preventExtensions", 1);
|
|
|
|
addFunction(_objectCtor, "isSealed", booleanValue(), 1);
|
|
|
|
addFunction(_objectCtor, "isFrozen", booleanValue(), 1);
|
|
|
|
addFunction(_objectCtor, "isExtensible", booleanValue(), 1);
|
2010-01-24 11:10:01 +01:00
|
|
|
addFunction(_objectCtor, "keys", newArray(), 1);
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
addFunction(_objectPrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_objectPrototype, "toLocaleString", stringValue(), 0);
|
2010-01-24 11:10:01 +01:00
|
|
|
addFunction(_objectPrototype, "valueOf", 0); // ### FIXME it should return thisObject
|
2010-01-21 15:54:19 +01:00
|
|
|
addFunction(_objectPrototype, "hasOwnProperty", booleanValue(), 1);
|
|
|
|
addFunction(_objectPrototype, "isPrototypeOf", booleanValue(), 1);
|
|
|
|
addFunction(_objectPrototype, "propertyIsEnumerable", booleanValue(), 1);
|
|
|
|
|
|
|
|
// set up the default Function prototype
|
|
|
|
_functionPrototype->setProperty("constructor", _functionCtor);
|
|
|
|
addFunction(_functionPrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_functionPrototype, "apply", 2);
|
|
|
|
addFunction(_functionPrototype, "call", 1);
|
|
|
|
addFunction(_functionPrototype, "bind", 1);
|
|
|
|
|
|
|
|
// set up the default Array prototype
|
|
|
|
addFunction(_arrayCtor, "isArray", booleanValue(), 1);
|
|
|
|
|
|
|
|
_arrayPrototype->setProperty("constructor", _arrayCtor);
|
|
|
|
addFunction(_arrayPrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_arrayPrototype, "toLocalString", stringValue(), 0);
|
|
|
|
addFunction(_arrayPrototype, "concat", 0);
|
|
|
|
addFunction(_arrayPrototype, "join", 1);
|
|
|
|
addFunction(_arrayPrototype, "pop", 0);
|
|
|
|
addFunction(_arrayPrototype, "push", 0);
|
|
|
|
addFunction(_arrayPrototype, "reverse", 0);
|
|
|
|
addFunction(_arrayPrototype, "shift", 0);
|
|
|
|
addFunction(_arrayPrototype, "slice", 2);
|
|
|
|
addFunction(_arrayPrototype, "sort", 1);
|
|
|
|
addFunction(_arrayPrototype, "splice", 2);
|
|
|
|
addFunction(_arrayPrototype, "unshift", 0);
|
|
|
|
addFunction(_arrayPrototype, "indexOf", numberValue(), 1);
|
|
|
|
addFunction(_arrayPrototype, "lastIndexOf", numberValue(), 1);
|
|
|
|
addFunction(_arrayPrototype, "every", 1);
|
|
|
|
addFunction(_arrayPrototype, "some", 1);
|
|
|
|
addFunction(_arrayPrototype, "forEach", 1);
|
|
|
|
addFunction(_arrayPrototype, "map", 1);
|
|
|
|
addFunction(_arrayPrototype, "filter", 1);
|
|
|
|
addFunction(_arrayPrototype, "reduce", 1);
|
|
|
|
addFunction(_arrayPrototype, "reduceRight", 1);
|
|
|
|
|
|
|
|
// set up the default String prototype
|
|
|
|
addFunction(_stringCtor, "fromCharCode", stringValue(), 0);
|
|
|
|
|
|
|
|
_stringPrototype->setProperty("constructor", _stringCtor);
|
|
|
|
addFunction(_stringPrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "valueOf", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "charAt", stringValue(), 1);
|
|
|
|
addFunction(_stringPrototype, "charCodeAt", stringValue(), 1);
|
|
|
|
addFunction(_stringPrototype, "concat", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "indexOf", numberValue(), 2);
|
|
|
|
addFunction(_stringPrototype, "lastIndexOf", numberValue(), 2);
|
|
|
|
addFunction(_stringPrototype, "localeCompare", booleanValue(), 1);
|
2010-01-24 11:10:01 +01:00
|
|
|
addFunction(_stringPrototype, "match", newArray(), 1);
|
2010-01-21 15:54:19 +01:00
|
|
|
addFunction(_stringPrototype, "replace", stringValue(), 2);
|
|
|
|
addFunction(_stringPrototype, "search", numberValue(), 1);
|
|
|
|
addFunction(_stringPrototype, "slice", stringValue(), 2);
|
2010-01-26 12:38:52 +01:00
|
|
|
addFunction(_stringPrototype, "split", newArray(), 1);
|
2010-01-21 15:54:19 +01:00
|
|
|
addFunction(_stringPrototype, "substring", stringValue(), 2);
|
|
|
|
addFunction(_stringPrototype, "toLowerCase", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "toLocaleLowerCase", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "toUpperCase", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "toLocaleUpperCase", stringValue(), 0);
|
|
|
|
addFunction(_stringPrototype, "trim", stringValue(), 0);
|
|
|
|
|
|
|
|
// set up the default Boolean prototype
|
|
|
|
addFunction(_booleanCtor, "fromCharCode", 0);
|
|
|
|
|
|
|
|
_booleanPrototype->setProperty("constructor", _booleanCtor);
|
|
|
|
addFunction(_booleanPrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_booleanPrototype, "valueOf", booleanValue(), 0);
|
|
|
|
|
|
|
|
// set up the default Number prototype
|
|
|
|
_numberCtor->setProperty("MAX_VALUE", numberValue());
|
|
|
|
_numberCtor->setProperty("MIN_VALUE", numberValue());
|
|
|
|
_numberCtor->setProperty("NaN", numberValue());
|
|
|
|
_numberCtor->setProperty("NEGATIVE_INFINITY", numberValue());
|
|
|
|
_numberCtor->setProperty("POSITIVE_INFINITY", numberValue());
|
|
|
|
|
|
|
|
addFunction(_numberCtor, "fromCharCode", 0);
|
|
|
|
|
|
|
|
_numberPrototype->setProperty("constructor", _numberCtor);
|
|
|
|
addFunction(_numberPrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_numberPrototype, "toLocaleString", stringValue(), 0);
|
|
|
|
addFunction(_numberPrototype, "valueOf", numberValue(), 0);
|
|
|
|
addFunction(_numberPrototype, "toFixed", numberValue(), 1);
|
|
|
|
addFunction(_numberPrototype, "toExponential", numberValue(), 1);
|
|
|
|
addFunction(_numberPrototype, "toPrecision", numberValue(), 1);
|
|
|
|
|
|
|
|
// set up the Math object
|
|
|
|
_mathObject = newObject();
|
|
|
|
_mathObject->setProperty("E", numberValue());
|
|
|
|
_mathObject->setProperty("LN10", numberValue());
|
|
|
|
_mathObject->setProperty("LN2", numberValue());
|
|
|
|
_mathObject->setProperty("LOG2E", numberValue());
|
|
|
|
_mathObject->setProperty("LOG10E", numberValue());
|
|
|
|
_mathObject->setProperty("PI", numberValue());
|
|
|
|
_mathObject->setProperty("SQRT1_2", numberValue());
|
|
|
|
_mathObject->setProperty("SQRT2", numberValue());
|
|
|
|
|
|
|
|
addFunction(_mathObject, "abs", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "acos", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "asin", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "atan", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "atan2", numberValue(), 2);
|
|
|
|
addFunction(_mathObject, "ceil", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "cos", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "exp", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "floor", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "log", numberValue(), 1);
|
2010-01-26 10:50:30 +01:00
|
|
|
addFunction(_mathObject, "max", numberValue(), 0);
|
|
|
|
addFunction(_mathObject, "min", numberValue(), 0);
|
2010-01-21 15:54:19 +01:00
|
|
|
addFunction(_mathObject, "pow", numberValue(), 2);
|
|
|
|
addFunction(_mathObject, "random", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "round", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "sin", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "sqrt", numberValue(), 1);
|
|
|
|
addFunction(_mathObject, "tan", numberValue(), 1);
|
|
|
|
|
|
|
|
// set up the default Boolean prototype
|
|
|
|
addFunction(_dateCtor, "parse", numberValue(), 1);
|
|
|
|
addFunction(_dateCtor, "now", numberValue(), 0);
|
|
|
|
|
|
|
|
_datePrototype->setProperty("constructor", _dateCtor);
|
|
|
|
addFunction(_datePrototype, "toString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toDateString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toTimeString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toLocaleString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toLocaleDateString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toLocaleTimeString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "valueOf", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getTime", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getFullYear", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCFullYear", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getMonth", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCMonth", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getDate", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCDate", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getHours", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCHours", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getMinutes", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCMinutes", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getSeconds", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCSeconds", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getMilliseconds", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getUTCMilliseconds", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "getTimezoneOffset", numberValue(), 0);
|
|
|
|
addFunction(_datePrototype, "setTime", 1);
|
|
|
|
addFunction(_datePrototype, "setMilliseconds", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCMilliseconds", 1);
|
|
|
|
addFunction(_datePrototype, "setSeconds", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCSeconds", 1);
|
|
|
|
addFunction(_datePrototype, "setMinutes", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCMinutes", 1);
|
|
|
|
addFunction(_datePrototype, "setHours", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCHours", 1);
|
|
|
|
addFunction(_datePrototype, "setDate", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCDate", 1);
|
|
|
|
addFunction(_datePrototype, "setMonth", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCMonth", 1);
|
|
|
|
addFunction(_datePrototype, "setFullYear", 1);
|
|
|
|
addFunction(_datePrototype, "setUTCFullYear", 1);
|
|
|
|
addFunction(_datePrototype, "toUTCString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toISOString", stringValue(), 0);
|
|
|
|
addFunction(_datePrototype, "toJSON", stringValue(), 1);
|
|
|
|
|
|
|
|
// set up the default Boolean prototype
|
|
|
|
_regexpPrototype->setProperty("constructor", _regexpCtor);
|
2010-01-24 11:10:01 +01:00
|
|
|
addFunction(_regexpPrototype, "exec", newArray(), 1);
|
2010-01-21 15:54:19 +01:00
|
|
|
addFunction(_regexpPrototype, "test", booleanValue(), 1);
|
|
|
|
addFunction(_regexpPrototype, "toString", stringValue(), 0);
|
|
|
|
|
|
|
|
// fill the Global object
|
|
|
|
_globalObject->setProperty("Math", _mathObject);
|
|
|
|
_globalObject->setProperty("Object", objectCtor());
|
|
|
|
_globalObject->setProperty("Function", functionCtor());
|
|
|
|
_globalObject->setProperty("Array", arrayCtor());
|
|
|
|
_globalObject->setProperty("String", stringCtor());
|
|
|
|
_globalObject->setProperty("Boolean", booleanCtor());
|
|
|
|
_globalObject->setProperty("Number", numberCtor());
|
|
|
|
_globalObject->setProperty("Date", dateCtor());
|
|
|
|
_globalObject->setProperty("RegExp", regexpCtor());
|
2010-02-10 15:51:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
//types
|
|
|
|
_qtObject = newObject(/*prototype */ 0);
|
|
|
|
addFunction(_qtObject, QLatin1String("rgba"), 4);
|
|
|
|
addFunction(_qtObject, QLatin1String("hsla"), 4);
|
|
|
|
addFunction(_qtObject, QLatin1String("rect"), 4);
|
|
|
|
addFunction(_qtObject, QLatin1String("point"), 2);
|
|
|
|
addFunction(_qtObject, QLatin1String("size"), 2);
|
|
|
|
addFunction(_qtObject, QLatin1String("vector3d"), 3);
|
|
|
|
|
|
|
|
//color helpers
|
|
|
|
addFunction(_qtObject, QLatin1String("lighter"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("darker"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("tint"), 2);
|
|
|
|
|
|
|
|
//misc methods
|
|
|
|
addFunction(_qtObject, QLatin1String("closestAngle"), 2);
|
|
|
|
addFunction(_qtObject, QLatin1String("playSound"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("openUrlExternally"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("md5"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("btoa"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("atob"), 1);
|
|
|
|
addFunction(_qtObject, QLatin1String("quit"), 0);
|
|
|
|
addFunction(_qtObject, QLatin1String("resolvedUrl"), 1);
|
|
|
|
|
|
|
|
//firebug/webkit compat
|
|
|
|
ObjectValue *consoleObject = newObject(/*prototype */ 0);
|
|
|
|
addFunction(consoleObject, QLatin1String("log"), 1);
|
|
|
|
addFunction(consoleObject, QLatin1String("debug"), 1);
|
|
|
|
|
|
|
|
_globalObject->setProperty(QLatin1String("console"), consoleObject);
|
|
|
|
|
|
|
|
_globalObject->setProperty(QLatin1String("Qt"), _qtObject);
|
2010-09-24 14:01:10 +02:00
|
|
|
|
|
|
|
// QML objects
|
|
|
|
_qmlFontObject = newObject(/*prototype =*/ 0);
|
|
|
|
_qmlFontObject->setClassName(QLatin1String("Font"));
|
|
|
|
_qmlFontObject->setProperty("family", stringValue());
|
|
|
|
_qmlFontObject->setProperty("weight", undefinedValue()); // ### make me an object
|
|
|
|
_qmlFontObject->setProperty("capitalization", undefinedValue()); // ### make me an object
|
|
|
|
_qmlFontObject->setProperty("bold", booleanValue());
|
|
|
|
_qmlFontObject->setProperty("italic", booleanValue());
|
|
|
|
_qmlFontObject->setProperty("underline", booleanValue());
|
|
|
|
_qmlFontObject->setProperty("overline", booleanValue());
|
|
|
|
_qmlFontObject->setProperty("strikeout", booleanValue());
|
|
|
|
_qmlFontObject->setProperty("pointSize", numberValue());
|
|
|
|
_qmlFontObject->setProperty("pixelSize", numberValue());
|
|
|
|
_qmlFontObject->setProperty("letterSpacing", numberValue());
|
|
|
|
_qmlFontObject->setProperty("wordSpacing", numberValue());
|
|
|
|
|
|
|
|
_qmlPointObject = newObject(/*prototype =*/ 0);
|
|
|
|
_qmlPointObject->setClassName(QLatin1String("Point"));
|
|
|
|
_qmlPointObject->setProperty("x", numberValue());
|
|
|
|
_qmlPointObject->setProperty("y", numberValue());
|
|
|
|
|
|
|
|
_qmlSizeObject = newObject(/*prototype =*/ 0);
|
|
|
|
_qmlSizeObject->setClassName(QLatin1String("Size"));
|
|
|
|
_qmlSizeObject->setProperty("width", numberValue());
|
|
|
|
_qmlSizeObject->setProperty("height", numberValue());
|
|
|
|
|
|
|
|
_qmlRectObject = newObject(/*prototype =*/ 0);
|
|
|
|
_qmlRectObject->setClassName("Rect");
|
|
|
|
_qmlRectObject->setProperty("x", numberValue());
|
|
|
|
_qmlRectObject->setProperty("y", numberValue());
|
|
|
|
_qmlRectObject->setProperty("width", numberValue());
|
|
|
|
_qmlRectObject->setProperty("height", numberValue());
|
|
|
|
|
|
|
|
_qmlVector3DObject = newObject(/*prototype =*/ 0);
|
|
|
|
_qmlVector3DObject->setClassName(QLatin1String("Vector3D"));
|
|
|
|
_qmlVector3DObject->setProperty("x", numberValue());
|
|
|
|
_qmlVector3DObject->setProperty("y", numberValue());
|
|
|
|
_qmlVector3DObject->setProperty("z", numberValue());
|
2010-01-26 11:06:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *Engine::qmlKeysObject()
|
|
|
|
{
|
|
|
|
return _qmlKeysObject;
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 14:01:10 +02:00
|
|
|
const ObjectValue *Engine::qmlFontObject()
|
|
|
|
{
|
|
|
|
return _qmlFontObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *Engine::qmlPointObject()
|
|
|
|
{
|
|
|
|
return _qmlPointObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *Engine::qmlSizeObject()
|
|
|
|
{
|
|
|
|
return _qmlSizeObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *Engine::qmlRectObject()
|
|
|
|
{
|
|
|
|
return _qmlRectObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *Engine::qmlVector3DObject()
|
|
|
|
{
|
|
|
|
return _qmlVector3DObject;
|
|
|
|
}
|
|
|
|
|
2010-01-26 11:15:21 +01:00
|
|
|
const Value *Engine::defaultValueForBuiltinType(const QString &typeName) const
|
|
|
|
{
|
2010-11-11 16:04:55 +01:00
|
|
|
if (typeName == QLatin1String("string"))
|
2010-01-26 11:15:21 +01:00
|
|
|
return stringValue();
|
2010-11-11 16:04:55 +01:00
|
|
|
else if (typeName == QLatin1String("url"))
|
|
|
|
return urlValue();
|
2010-01-26 11:15:21 +01:00
|
|
|
else if (typeName == QLatin1String("bool"))
|
|
|
|
return booleanValue();
|
2010-11-11 16:04:55 +01:00
|
|
|
else if (typeName == QLatin1String("int"))
|
|
|
|
return intValue();
|
|
|
|
else if (typeName == QLatin1String("real"))
|
|
|
|
return realValue();
|
2010-07-27 13:41:30 +02:00
|
|
|
else if (typeName == QLatin1String("color"))
|
|
|
|
return colorValue();
|
2010-01-26 11:15:21 +01:00
|
|
|
// ### more types...
|
|
|
|
|
|
|
|
return undefinedValue();
|
|
|
|
}
|
|
|
|
|
2010-02-08 12:50:10 +01:00
|
|
|
ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
|
|
|
|
UiObjectInitializer *initializer,
|
2010-02-09 12:27:52 +01:00
|
|
|
const QmlJS::Document *doc,
|
2010-02-08 12:50:10 +01:00
|
|
|
Engine *engine)
|
2010-05-31 12:21:12 +02:00
|
|
|
: ObjectValue(engine), _typeName(typeName), _initializer(initializer), _doc(doc), _defaultPropertyRef(0)
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
if (_initializer) {
|
|
|
|
for (UiObjectMemberList *it = _initializer->members; it; it = it->next) {
|
|
|
|
UiObjectMember *member = it->member;
|
|
|
|
if (UiPublicMember *def = cast<UiPublicMember *>(member)) {
|
2010-02-17 08:44:17 +01:00
|
|
|
if (def->type == UiPublicMember::Property && def->name && def->memberType) {
|
2010-02-08 12:50:10 +01:00
|
|
|
ASTPropertyReference *ref = new ASTPropertyReference(def, _doc, engine);
|
|
|
|
_properties.append(ref);
|
2010-05-31 12:21:12 +02:00
|
|
|
if (def->defaultToken.isValid())
|
|
|
|
_defaultPropertyRef = ref;
|
2010-02-17 08:44:17 +01:00
|
|
|
} else if (def->type == UiPublicMember::Signal && def->name) {
|
|
|
|
ASTSignalReference *ref = new ASTSignalReference(def, _doc, engine);
|
|
|
|
_signals.append(ref);
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-08 12:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTObjectValue::~ASTObjectValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTObjectValue::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _typeName->identifierToken.startLine;
|
|
|
|
*column = _typeName->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTObjectValue::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
2010-02-17 09:16:28 +01:00
|
|
|
foreach (ASTPropertyReference *ref, _properties) {
|
2010-02-08 12:50:10 +01:00
|
|
|
processor->processProperty(ref->ast()->name->asString(), ref);
|
2010-02-17 09:16:28 +01:00
|
|
|
// ### Should get a different value?
|
|
|
|
processor->processGeneratedSlot(ref->onChangedSlotName(), ref);
|
|
|
|
}
|
2010-02-17 08:44:17 +01:00
|
|
|
foreach (ASTSignalReference *ref, _signals) {
|
|
|
|
processor->processSignal(ref->ast()->name->asString(), ref);
|
2010-02-17 09:16:28 +01:00
|
|
|
// ### Should get a different value?
|
2010-02-17 08:44:17 +01:00
|
|
|
processor->processGeneratedSlot(ref->slotName(), ref);
|
|
|
|
}
|
2010-02-08 12:50:10 +01:00
|
|
|
|
2010-02-03 14:31:03 +01:00
|
|
|
ObjectValue::processMembers(processor);
|
|
|
|
}
|
|
|
|
|
2010-05-31 12:21:12 +02:00
|
|
|
QString ASTObjectValue::defaultPropertyName() const
|
|
|
|
{
|
|
|
|
if (_defaultPropertyRef) {
|
|
|
|
UiPublicMember *prop = _defaultPropertyRef->ast();
|
|
|
|
if (prop && prop->name)
|
|
|
|
return prop->name->asString();
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-02-03 14:31:03 +01:00
|
|
|
ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, Engine *engine)
|
|
|
|
: Reference(engine), _ast(ast)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTVariableReference::~ASTVariableReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ASTVariableReference::value(const Context *context) const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
2010-02-15 11:52:39 +01:00
|
|
|
Evaluate check(context);
|
2010-02-03 14:31:03 +01:00
|
|
|
return check(_ast->expression);
|
|
|
|
}
|
|
|
|
|
2010-11-16 13:53:39 +01:00
|
|
|
ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const QmlJS::Document *doc, Engine *engine)
|
2010-07-22 14:18:40 +02:00
|
|
|
: FunctionValue(engine), _ast(ast), _doc(doc)
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
setPrototype(engine->functionPrototype());
|
|
|
|
|
|
|
|
for (FormalParameterList *it = ast->formals; it; it = it->next)
|
|
|
|
_argumentNames.append(it->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTFunctionValue::~ASTFunctionValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-11-16 13:53:39 +01:00
|
|
|
FunctionExpression *ASTFunctionValue::ast() const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
return _ast;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *ASTFunctionValue::returnValue() const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ASTFunctionValue::argumentCount() const
|
|
|
|
{
|
|
|
|
return _argumentNames.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *ASTFunctionValue::argument(int) const
|
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ASTFunctionValue::argumentName(int index) const
|
|
|
|
{
|
|
|
|
if (index < _argumentNames.size()) {
|
|
|
|
if (NameId *nameId = _argumentNames.at(index))
|
|
|
|
return nameId->asString();
|
|
|
|
}
|
|
|
|
|
|
|
|
return FunctionValue::argumentName(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTFunctionValue::isVariadic() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2010-02-03 15:39:57 +01:00
|
|
|
|
2010-07-16 10:50:28 +02:00
|
|
|
bool ASTFunctionValue::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _ast->identifierToken.startLine;
|
|
|
|
*column = _ast->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-02-04 11:08:57 +01:00
|
|
|
QmlPrototypeReference::QmlPrototypeReference(UiQualifiedId *qmlTypeName, const QmlJS::Document *doc,
|
2010-02-04 09:44:43 +01:00
|
|
|
Engine *engine)
|
2010-02-03 15:39:57 +01:00
|
|
|
: Reference(engine),
|
2010-02-04 09:44:43 +01:00
|
|
|
_qmlTypeName(qmlTypeName),
|
|
|
|
_doc(doc)
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlPrototypeReference::~QmlPrototypeReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
UiQualifiedId *QmlPrototypeReference::qmlTypeName() const
|
|
|
|
{
|
|
|
|
return _qmlTypeName;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *QmlPrototypeReference::value(const Context *context) const
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
2010-02-04 09:44:43 +01:00
|
|
|
return context->lookupType(_doc, _qmlTypeName);
|
2010-02-03 15:39:57 +01:00
|
|
|
}
|
|
|
|
|
2010-02-09 12:27:52 +01:00
|
|
|
ASTPropertyReference::ASTPropertyReference(UiPublicMember *ast, const QmlJS::Document *doc, Engine *engine)
|
2010-02-08 12:50:10 +01:00
|
|
|
: Reference(engine), _ast(ast), _doc(doc)
|
|
|
|
{
|
2010-02-17 09:16:28 +01:00
|
|
|
const QString propertyName = ast->name->asString();
|
|
|
|
_onChangedSlotName = QLatin1String("on");
|
|
|
|
_onChangedSlotName += propertyName.at(0).toUpper();
|
|
|
|
_onChangedSlotName += propertyName.midRef(1);
|
|
|
|
_onChangedSlotName += QLatin1String("Changed");
|
2010-02-08 12:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTPropertyReference::~ASTPropertyReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _ast->identifierToken.startLine;
|
|
|
|
*column = _ast->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ASTPropertyReference::value(const Context *context) const
|
2010-02-08 12:50:10 +01:00
|
|
|
{
|
2010-07-27 13:42:32 +02:00
|
|
|
if (_ast->expression
|
|
|
|
&& (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant"))) {
|
2010-02-15 11:52:39 +01:00
|
|
|
Evaluate check(context);
|
2010-02-08 12:50:10 +01:00
|
|
|
return check(_ast->expression);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_ast->memberType)
|
|
|
|
return engine()->defaultValueForBuiltinType(_ast->memberType->asString());
|
|
|
|
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
2010-02-17 08:44:17 +01:00
|
|
|
|
|
|
|
ASTSignalReference::ASTSignalReference(UiPublicMember *ast, const QmlJS::Document *doc, Engine *engine)
|
|
|
|
: Reference(engine), _ast(ast), _doc(doc)
|
|
|
|
{
|
|
|
|
const QString signalName = ast->name->asString();
|
|
|
|
_slotName = QLatin1String("on");
|
|
|
|
_slotName += signalName.at(0).toUpper();
|
|
|
|
_slotName += signalName.midRef(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTSignalReference::~ASTSignalReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTSignalReference::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _ast->identifierToken.startLine;
|
|
|
|
*column = _ast->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ASTSignalReference::value(const Context *) const
|
2010-02-17 08:44:17 +01:00
|
|
|
{
|
|
|
|
return engine()->undefinedValue();
|
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
|
|
|
|
ImportInfo::ImportInfo()
|
|
|
|
: _type(InvalidImport)
|
|
|
|
, _ast(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ImportInfo::ImportInfo(Type type, const QString &name,
|
|
|
|
QmlJS::ComponentVersion version, UiImport *ast)
|
|
|
|
: _type(type)
|
|
|
|
, _name(name)
|
|
|
|
, _version(version)
|
|
|
|
, _ast(ast)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImportInfo::isValid() const
|
|
|
|
{
|
|
|
|
return _type != InvalidImport;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImportInfo::Type ImportInfo::type() const
|
|
|
|
{
|
|
|
|
return _type;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ImportInfo::name() const
|
|
|
|
{
|
|
|
|
return _name;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ImportInfo::id() const
|
|
|
|
{
|
|
|
|
if (_ast && _ast->importId)
|
|
|
|
return _ast->importId->asString();
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlJS::ComponentVersion ImportInfo::version() const
|
|
|
|
{
|
|
|
|
return _version;
|
|
|
|
}
|
|
|
|
|
|
|
|
UiImport *ImportInfo::ast() const
|
|
|
|
{
|
|
|
|
return _ast;
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeEnvironment::TypeEnvironment(Engine *engine)
|
|
|
|
: ObjectValue(engine)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *TypeEnvironment::lookupMember(const QString &name, const Context *context, bool) const
|
|
|
|
{
|
|
|
|
QHashIterator<const ObjectValue *, ImportInfo> it(_imports);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
const ObjectValue *import = it.key();
|
|
|
|
const ImportInfo &info = it.value();
|
|
|
|
|
|
|
|
if (!info.id().isEmpty()) {
|
|
|
|
if (info.id() == name)
|
|
|
|
return import;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type() == ImportInfo::FileImport) {
|
|
|
|
if (import->className() == name)
|
|
|
|
return import;
|
|
|
|
} else {
|
|
|
|
if (const Value *v = import->property(name, context))
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TypeEnvironment::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
|
|
|
QHashIterator<const ObjectValue *, ImportInfo> it(_imports);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
const ObjectValue *import = it.key();
|
|
|
|
const ImportInfo &info = it.value();
|
|
|
|
|
|
|
|
if (!info.id().isEmpty()) {
|
|
|
|
processor->processProperty(info.id(), import);
|
|
|
|
} else {
|
|
|
|
if (info.type() == ImportInfo::FileImport)
|
|
|
|
processor->processProperty(import->className(), import);
|
|
|
|
else
|
|
|
|
import->processMembers(processor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TypeEnvironment::addImport(const ObjectValue *import, const ImportInfo &info)
|
|
|
|
{
|
|
|
|
_imports.insert(import, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImportInfo TypeEnvironment::importInfo(const QString &name, const Context *context) const
|
|
|
|
{
|
|
|
|
QString firstId = name;
|
|
|
|
int dotIdx = firstId.indexOf(QLatin1Char('.'));
|
|
|
|
if (dotIdx != -1)
|
|
|
|
firstId = firstId.left(dotIdx);
|
|
|
|
|
|
|
|
QHashIterator<const ObjectValue *, ImportInfo> it(_imports);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
const ObjectValue *import = it.key();
|
|
|
|
const ImportInfo &info = it.value();
|
|
|
|
|
|
|
|
if (!info.id().isEmpty()) {
|
|
|
|
if (info.id() == firstId)
|
|
|
|
return info;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type() == ImportInfo::FileImport) {
|
|
|
|
if (import->className() == firstId)
|
|
|
|
return info;
|
|
|
|
} else {
|
|
|
|
if (import->property(firstId, context))
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ImportInfo();
|
|
|
|
}
|