forked from qt-creator/qt-creator
		
	QmlJS: Speed up ValueOwner construction.
* Don't build all default values (including the global object) separately for each ValueOwner instance. * Instead, keep all global, immutable values in a single, shared instance. While refactoring, some cases where we *modified* the global object had to be removed: * C++ context properties no longer get injected into the global object, instead they now have their own scope just above the global one. * The Qt object's prototype no longer gets modified in Link. Instead, it's now a reference to the "Qt" object provided in a qmltypes file. * The whole concept of a function 'Activation' that could potentially affect the global object was removed. Change-Id: Id382faf965efa747fcc7a9b0bc2c90429d84d61b Reviewed-by: Leandro Melo <leandro.melo@nokia.com>
This commit is contained in:
		| @@ -273,13 +273,13 @@ bool Evaluate::visit(AST::NumericLiteral *) | ||||
|  | ||||
| bool Evaluate::visit(AST::RegExpLiteral *) | ||||
| { | ||||
|     _result = _valueOwner->regexpCtor()->construct(); | ||||
|     _result = _valueOwner->regexpCtor()->returnValue(); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool Evaluate::visit(AST::ArrayLiteral *) | ||||
| { | ||||
|     _result = _valueOwner->arrayCtor()->construct(); | ||||
|     _result = _valueOwner->arrayCtor()->returnValue(); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| @@ -347,7 +347,7 @@ bool Evaluate::visit(AST::FieldMemberExpression *ast) | ||||
| bool Evaluate::visit(AST::NewMemberExpression *ast) | ||||
| { | ||||
|     if (const FunctionValue *ctor = value_cast<FunctionValue>(value(ast->base))) { | ||||
|         _result = ctor->construct(); | ||||
|         _result = ctor->returnValue(); | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| @@ -355,7 +355,7 @@ bool Evaluate::visit(AST::NewMemberExpression *ast) | ||||
| bool Evaluate::visit(AST::NewExpression *ast) | ||||
| { | ||||
|     if (const FunctionValue *ctor = value_cast<FunctionValue>(value(ast->expression))) { | ||||
|         _result = ctor->construct(); | ||||
|         _result = ctor->returnValue(); | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|   | ||||
| @@ -169,11 +169,6 @@ public: | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *) const | ||||
|     { | ||||
|         return valueOwner()->unknownValue(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // end of anonymous namespace | ||||
| @@ -1115,105 +1110,18 @@ QList<const ObjectValue *> PrototypeIterator::all() | ||||
|     return m_prototypes; | ||||
| } | ||||
|  | ||||
| Activation::Activation(Context *parentContext) | ||||
|     : _thisObject(0), | ||||
|       _calledAsFunction(true), | ||||
|       _parentContext(parentContext) | ||||
| { | ||||
| } | ||||
|  | ||||
| Activation::~Activation() | ||||
| { | ||||
| } | ||||
|  | ||||
| Context *Activation::parentContext() const | ||||
| { | ||||
|     return _parentContext; | ||||
| } | ||||
|  | ||||
| Context *Activation::context() const | ||||
| { | ||||
|     // ### FIXME: Real context for activations. | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| bool Activation::calledAsConstructor() const | ||||
| { | ||||
|     return ! _calledAsFunction; | ||||
| } | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| FunctionValue::FunctionValue(ValueOwner *valueOwner) | ||||
|     : ObjectValue(valueOwner) | ||||
| { | ||||
|     setClassName("Function"); | ||||
|     setMember(QLatin1String("length"), valueOwner->numberValue()); | ||||
|     setPrototype(valueOwner->functionPrototype()); | ||||
| } | ||||
|  | ||||
| FunctionValue::~FunctionValue() | ||||
| { | ||||
| } | ||||
|  | ||||
| const Value *FunctionValue::construct(const ValueList &actuals) const | ||||
| { | ||||
|     Activation activation; | ||||
|     activation.setCalledAsConstructor(true); | ||||
|     activation.setThisObject(valueOwner()->newObject()); | ||||
|     activation.setArguments(actuals); | ||||
|     return invoke(&activation); | ||||
| } | ||||
|  | ||||
| const Value *FunctionValue::call(const ValueList &actuals) const | ||||
| { | ||||
|     Activation activation; | ||||
|     activation.setCalledAsFunction(true); | ||||
|     activation.setThisObject(valueOwner()->globalObject()); // ### FIXME: it should be `null' | ||||
|     activation.setArguments(actuals); | ||||
|     return invoke(&activation); | ||||
| } | ||||
|  | ||||
| const Value *FunctionValue::call(const ObjectValue *thisObject, const ValueList &actuals) const | ||||
| { | ||||
|     Activation activation; | ||||
|     activation.setCalledAsFunction(true); | ||||
|     activation.setThisObject(const_cast<ObjectValue *>(thisObject)); // ### FIXME: remove the const_cast | ||||
|     activation.setArguments(actuals); | ||||
|     return invoke(&activation); | ||||
| } | ||||
|  | ||||
| const Value *FunctionValue::returnValue() const | ||||
| { | ||||
|     return valueOwner()->unknownValue(); | ||||
| @@ -1244,11 +1152,6 @@ bool FunctionValue::isVariadic() const | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| const Value *FunctionValue::invoke(const Activation *activation) const | ||||
| { | ||||
|     return activation->thisObject(); // ### FIXME: it should return undefined | ||||
| } | ||||
|  | ||||
| const FunctionValue *FunctionValue::asFunctionValue() const | ||||
| { | ||||
|     return this; | ||||
| @@ -1265,7 +1168,6 @@ Function::Function(ValueOwner *valueOwner) | ||||
|     , _optionalNamedArgumentCount(0) | ||||
|     , _isVariadic(false) | ||||
| { | ||||
|     setClassName("Function"); | ||||
| } | ||||
|  | ||||
| Function::~Function() | ||||
| @@ -1327,11 +1229,6 @@ QString Function::argumentName(int index) const | ||||
|     return FunctionValue::argumentName(index); | ||||
| } | ||||
|  | ||||
| const Value *Function::invoke(const Activation *) const | ||||
| { | ||||
|     return _returnValue; | ||||
| } | ||||
|  | ||||
| bool Function::isVariadic() const | ||||
| { | ||||
|     return _isVariadic; | ||||
| @@ -1394,7 +1291,9 @@ void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml, | ||||
| } | ||||
|  | ||||
| CppQmlTypes::CppQmlTypes(ValueOwner *valueOwner) | ||||
|     : _valueOwner(valueOwner) | ||||
|     : _cppContextProperties(0) | ||||
|     , _valueOwner(valueOwner) | ||||
|  | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -1544,6 +1443,16 @@ const CppComponentValue *CppQmlTypes::objectByCppName(const QString &cppName) co | ||||
|     return objectByQualifiedName(qualifiedName(cppPackage, cppName, ComponentVersion())); | ||||
| } | ||||
|  | ||||
| void CppQmlTypes::setCppContextProperties(const ObjectValue *contextProperties) | ||||
| { | ||||
|     _cppContextProperties = contextProperties; | ||||
| } | ||||
|  | ||||
| const ObjectValue *CppQmlTypes::cppContextProperties() const | ||||
| { | ||||
|     return _cppContextProperties; | ||||
| } | ||||
|  | ||||
|  | ||||
| ConvertToNumber::ConvertToNumber(ValueOwner *valueOwner) | ||||
|     : _valueOwner(valueOwner), _result(0) | ||||
| @@ -1595,14 +1504,14 @@ void ConvertToNumber::visit(const StringValue *) | ||||
| void ConvertToNumber::visit(const ObjectValue *object) | ||||
| { | ||||
|     if (const FunctionValue *valueOfMember = value_cast<FunctionValue>(object->lookupMember("valueOf", ContextPtr()))) { | ||||
|         _result = value_cast<NumberValue>(valueOfMember->call(object)); // ### invoke convert-to-number? | ||||
|         _result = value_cast<NumberValue>(valueOfMember->returnValue()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ConvertToNumber::visit(const FunctionValue *object) | ||||
| { | ||||
|     if (const FunctionValue *valueOfMember = value_cast<FunctionValue>(object->lookupMember("valueOf", ContextPtr()))) { | ||||
|         _result = value_cast<NumberValue>(valueOfMember->call(object)); // ### invoke convert-to-number? | ||||
|         _result = value_cast<NumberValue>(valueOfMember->returnValue()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1656,14 +1565,14 @@ void ConvertToString::visit(const StringValue *value) | ||||
| void ConvertToString::visit(const ObjectValue *object) | ||||
| { | ||||
|     if (const FunctionValue *toStringMember = value_cast<FunctionValue>(object->lookupMember("toString", ContextPtr()))) { | ||||
|         _result = value_cast<StringValue>(toStringMember->call(object)); // ### invoke convert-to-string? | ||||
|         _result = value_cast<StringValue>(toStringMember->returnValue()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ConvertToString::visit(const FunctionValue *object) | ||||
| { | ||||
|     if (const FunctionValue *toStringMember = value_cast<FunctionValue>(object->lookupMember("toString", ContextPtr()))) { | ||||
|         _result = value_cast<StringValue>(toStringMember->call(object)); // ### invoke convert-to-string? | ||||
|         _result = value_cast<StringValue>(toStringMember->returnValue()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1699,25 +1608,19 @@ void ConvertToObject::visit(const UndefinedValue *) | ||||
|     _result = _valueOwner->nullValue(); | ||||
| } | ||||
|  | ||||
| void ConvertToObject::visit(const NumberValue *value) | ||||
| void ConvertToObject::visit(const NumberValue *) | ||||
| { | ||||
|     ValueList actuals; | ||||
|     actuals.append(value); | ||||
|     _result = _valueOwner->numberCtor()->construct(actuals); | ||||
|     _result = _valueOwner->numberCtor()->returnValue(); | ||||
| } | ||||
|  | ||||
| void ConvertToObject::visit(const BooleanValue *value) | ||||
| void ConvertToObject::visit(const BooleanValue *) | ||||
| { | ||||
|     ValueList actuals; | ||||
|     actuals.append(value); | ||||
|     _result = _valueOwner->booleanCtor()->construct(actuals); | ||||
|     _result = _valueOwner->booleanCtor()->returnValue(); | ||||
| } | ||||
|  | ||||
| void ConvertToObject::visit(const StringValue *value) | ||||
| void ConvertToObject::visit(const StringValue *) | ||||
| { | ||||
|     ValueList actuals; | ||||
|     actuals.append(value); | ||||
|     _result = _valueOwner->stringCtor()->construct(actuals); | ||||
|     _result = _valueOwner->stringCtor()->returnValue(); | ||||
| } | ||||
|  | ||||
| void ConvertToObject::visit(const ObjectValue *object) | ||||
|   | ||||
| @@ -536,51 +536,12 @@ private: | ||||
|     int _metaObjectRevision; | ||||
| }; | ||||
|  | ||||
| class QMLJS_EXPORT Activation | ||||
| { | ||||
| public: | ||||
|     explicit Activation(Context *parentContext = 0); | ||||
|     virtual ~Activation(); | ||||
|  | ||||
|     Context *context() const; | ||||
|     Context *parentContext() const; | ||||
|  | ||||
|     bool calledAsConstructor() const; | ||||
|     void setCalledAsConstructor(bool calledAsConstructor); | ||||
|  | ||||
|     bool calledAsFunction() const; | ||||
|     void setCalledAsFunction(bool calledAsFunction); | ||||
|  | ||||
|     ObjectValue *thisObject() const; | ||||
|     void setThisObject(ObjectValue *thisObject); | ||||
|  | ||||
|     ValueList arguments() const; | ||||
|     void setArguments(const ValueList &arguments); | ||||
|  | ||||
| private: | ||||
|     ObjectValue *_thisObject; | ||||
|     ValueList _arguments; | ||||
|     bool _calledAsFunction; | ||||
|     Context *_parentContext; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class QMLJS_EXPORT FunctionValue: public ObjectValue | ||||
| { | ||||
| public: | ||||
|     FunctionValue(ValueOwner *valueOwner); | ||||
|     virtual ~FunctionValue(); | ||||
|  | ||||
|     // [[construct]] | ||||
|     const Value *construct(const ValueList &actuals = ValueList()) const; | ||||
|  | ||||
|     // [[call]] | ||||
|     const Value *call(const ValueList &actuals = ValueList()) const; | ||||
|  | ||||
|     const Value *call(const ObjectValue *thisObject, | ||||
|                       const ValueList &actuals = ValueList()) const; | ||||
|  | ||||
|  | ||||
|     virtual const Value *returnValue() const; | ||||
|  | ||||
|     // Access to the names of arguments | ||||
| @@ -601,8 +562,6 @@ public: | ||||
|  | ||||
|     virtual const Value *argument(int index) const; | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
|  | ||||
|     // Value interface | ||||
|     virtual const FunctionValue *asFunctionValue() const; | ||||
|     virtual void accept(ValueVisitor *visitor) const; | ||||
| @@ -625,7 +584,6 @@ public: | ||||
|     virtual int optionalNamedArgumentCount() const; | ||||
|     virtual const Value *argument(int index) const; | ||||
|     virtual QString argumentName(int index) const; | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
|     virtual bool isVariadic() const; | ||||
|  | ||||
| private: | ||||
| @@ -686,10 +644,14 @@ public: | ||||
|             LanguageUtils::ComponentVersion version) const; | ||||
|     const CppComponentValue *objectByCppName(const QString &cppName) const; | ||||
|  | ||||
|     void setCppContextProperties(const ObjectValue *contextProperties); | ||||
|     const ObjectValue *cppContextProperties() const; | ||||
|  | ||||
| private: | ||||
|     // "Package.CppName ImportVersion" ->  CppComponentValue | ||||
|     QHash<QString, const CppComponentValue *> _objectsByQualifiedName; | ||||
|     QHash<QString, QSet<LanguageUtils::FakeMetaObject::ConstPtr> > _fakeMetaObjectsByPackage; | ||||
|     const ObjectValue *_cppContextProperties; | ||||
|     ValueOwner *_valueOwner; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -154,8 +154,8 @@ Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const Libra | ||||
|             d->valueOwner->cppQmlTypes().load(cppData.exportedTypes); | ||||
|         } | ||||
|  | ||||
|         // populate global object with context properties from C++ | ||||
|         ObjectValue *global = d->valueOwner->globalObject(); | ||||
|         // build an object with the context properties from C++ | ||||
|         ObjectValue *cppContextProperties = d->valueOwner->newObject(/* prototype = */ 0); | ||||
|         foreach (const ModelManagerInterface::CppData &cppData, cppDataHash) { | ||||
|             QHashIterator<QString, QString> it(cppData.contextProperties); | ||||
|             while (it.hasNext()) { | ||||
| @@ -166,9 +166,10 @@ Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const Libra | ||||
|                     value = d->valueOwner->cppQmlTypes().objectByCppName(cppTypeName); | ||||
|                 if (!value) | ||||
|                     value = d->valueOwner->unknownValue(); | ||||
|                 global->setMember(it.key(), value); | ||||
|                 cppContextProperties->setMember(it.key(), value); | ||||
|             } | ||||
|         } | ||||
|         d->valueOwner->cppQmlTypes().setCppContextProperties(cppContextProperties); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -205,11 +206,6 @@ Context::ImportsPerDocument LinkPrivate::linkImports() | ||||
|     // load library objects shipped with Creator | ||||
|     valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultLibraryObjects); | ||||
|  | ||||
|     // 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 | ||||
|     const_cast<ObjectValue *>(valueOwner->qtObject())->setPrototype(valueOwner->cppQmlTypes().objectByCppName(QLatin1String("Qt"))); | ||||
|  | ||||
|     if (document) { | ||||
|         // do it on document first, to make sure import errors are shown | ||||
|         Imports *imports = new Imports(valueOwner); | ||||
|   | ||||
| @@ -100,6 +100,7 @@ ScopeChain::ScopeChain(const Document::Ptr &document, const ContextPtr &context) | ||||
|     : m_document(document) | ||||
|     , m_context(context) | ||||
|     , m_globalScope(0) | ||||
|     , m_cppContextProperties(0) | ||||
|     , m_qmlTypes(0) | ||||
|     , m_jsImports(0) | ||||
|     , m_modified(false) | ||||
| @@ -154,6 +155,17 @@ void ScopeChain::setGlobalScope(const ObjectValue *globalScope) | ||||
|     m_globalScope = globalScope; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ScopeChain::cppContextProperties() const | ||||
| { | ||||
|     return m_cppContextProperties; | ||||
| } | ||||
|  | ||||
| void ScopeChain::setCppContextProperties(const ObjectValue *cppContextProperties) | ||||
| { | ||||
|     m_modified = true; | ||||
|     m_cppContextProperties = cppContextProperties; | ||||
| } | ||||
|  | ||||
| QSharedPointer<const QmlComponentChain> ScopeChain::qmlComponentChain() const | ||||
| { | ||||
|     return m_qmlComponentScope; | ||||
| @@ -243,6 +255,9 @@ void ScopeChain::update() const | ||||
|  | ||||
|     m_all += m_globalScope; | ||||
|  | ||||
|     if (m_cppContextProperties) | ||||
|         m_all += m_cppContextProperties; | ||||
|  | ||||
|     // the root scope in js files doesn't see instantiating components | ||||
|     if (m_jsScopes.count() != 1 || !m_qmlScopeObjects.isEmpty()) { | ||||
|         if (m_qmlComponentScope) { | ||||
| @@ -278,6 +293,7 @@ void ScopeChain::initializeRootScope() | ||||
|     Bind *bind = m_document->bind(); | ||||
|  | ||||
|     m_globalScope = valueOwner->globalObject(); | ||||
|     m_cppContextProperties = valueOwner->cppQmlTypes().cppContextProperties(); | ||||
|  | ||||
|     QHash<const Document *, QmlComponentChain *> componentScopes; | ||||
|     QmlComponentChain *chain = new QmlComponentChain(m_document); | ||||
|   | ||||
| @@ -86,6 +86,9 @@ public: | ||||
|     const ObjectValue *globalScope() const; | ||||
|     void setGlobalScope(const ObjectValue *globalScope); | ||||
|  | ||||
|     const ObjectValue *cppContextProperties() const; | ||||
|     void setCppContextProperties(const ObjectValue *cppContextProperties); | ||||
|  | ||||
|     QSharedPointer<const QmlComponentChain> qmlComponentChain() const; | ||||
|     void setQmlComponentChain(const QSharedPointer<const QmlComponentChain> &qmlComponentChain); | ||||
|  | ||||
| @@ -115,6 +118,7 @@ private: | ||||
|     ContextPtr m_context; | ||||
|  | ||||
|     const ObjectValue *m_globalScope; | ||||
|     const ObjectValue *m_cppContextProperties; | ||||
|     QSharedPointer<const QmlComponentChain> m_qmlComponentScope; | ||||
|     QList<const ObjectValue *> m_qmlScopeObjects; | ||||
|     const TypeScope *m_qmlTypes; | ||||
|   | ||||
| @@ -32,6 +32,8 @@ | ||||
|  | ||||
| #include "qmljsvalueowner.h" | ||||
|  | ||||
| #include "qmljscontext.h" | ||||
|  | ||||
| using namespace QmlJS; | ||||
|  | ||||
| /*! | ||||
| @@ -47,477 +49,73 @@ using namespace QmlJS; | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // constructors | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| class ObjectCtor: public Function | ||||
| class QtObjectPrototypeReference : public Reference | ||||
| { | ||||
| public: | ||||
|     ObjectCtor(ValueOwner *valueOwner); | ||||
|     QtObjectPrototypeReference(ValueOwner *owner) | ||||
|         : Reference(owner) | ||||
|     {} | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| private: | ||||
|     virtual const Value *value(ReferenceContext *referenceContext) const | ||||
|     { | ||||
|         return referenceContext->context()->valueOwner()->cppQmlTypes().objectByCppName(QLatin1String("Qt")); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class FunctionCtor: public Function | ||||
| { | ||||
| public: | ||||
|     FunctionCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| class ArrayCtor: public Function | ||||
| { | ||||
| public: | ||||
|     ArrayCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| class StringCtor: public Function | ||||
| { | ||||
| public: | ||||
|     StringCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| class BooleanCtor: public Function | ||||
| { | ||||
| public: | ||||
|     BooleanCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| class NumberCtor: public Function | ||||
| { | ||||
| public: | ||||
|     NumberCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| class DateCtor: public Function | ||||
| { | ||||
| public: | ||||
|     DateCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| class RegExpCtor: public Function | ||||
| { | ||||
| public: | ||||
|     RegExpCtor(ValueOwner *valueOwner); | ||||
|  | ||||
|     virtual const Value *invoke(const Activation *activation) const; | ||||
| }; | ||||
|  | ||||
| ObjectCtor::ObjectCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| FunctionCtor::FunctionCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| ArrayCtor::ArrayCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| StringCtor::StringCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| BooleanCtor::BooleanCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| NumberCtor::NumberCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| DateCtor::DateCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| RegExpCtor::RegExpCtor(ValueOwner *valueOwner) | ||||
|     : Function(valueOwner) | ||||
| { | ||||
| } | ||||
|  | ||||
| const Value *ObjectCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     if (activation->calledAsFunction()) | ||||
|         thisObject = valueOwner()->newObject(); | ||||
|  | ||||
|     thisObject->setClassName("Object"); | ||||
|     thisObject->setPrototype(valueOwner()->objectPrototype()); | ||||
|     thisObject->setMember("length", valueOwner()->numberValue()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *FunctionCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     if (activation->calledAsFunction()) | ||||
|         thisObject = valueOwner()->newObject(); | ||||
|  | ||||
|     thisObject->setClassName("Function"); | ||||
|     thisObject->setPrototype(valueOwner()->functionPrototype()); | ||||
|     thisObject->setMember("length", valueOwner()->numberValue()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *ArrayCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     if (activation->calledAsFunction()) | ||||
|         thisObject = valueOwner()->newObject(); | ||||
|  | ||||
|     thisObject->setClassName("Array"); | ||||
|     thisObject->setPrototype(valueOwner()->arrayPrototype()); | ||||
|     thisObject->setMember("length", valueOwner()->numberValue()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *StringCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     if (activation->calledAsFunction()) | ||||
|         return valueOwner()->convertToString(activation->thisObject()); | ||||
|  | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     thisObject->setClassName("String"); | ||||
|     thisObject->setPrototype(valueOwner()->stringPrototype()); | ||||
|     thisObject->setMember("length", valueOwner()->numberValue()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *BooleanCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     if (activation->calledAsFunction()) | ||||
|         return valueOwner()->convertToBoolean(activation->thisObject()); | ||||
|  | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     thisObject->setClassName("Boolean"); | ||||
|     thisObject->setPrototype(valueOwner()->booleanPrototype()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *NumberCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     if (activation->calledAsFunction()) | ||||
|         return valueOwner()->convertToNumber(activation->thisObject()); | ||||
|  | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     thisObject->setClassName("Number"); | ||||
|     thisObject->setPrototype(valueOwner()->numberPrototype()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *DateCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     if (activation->calledAsFunction()) | ||||
|         return valueOwner()->stringValue(); | ||||
|  | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     thisObject->setClassName("Date"); | ||||
|     thisObject->setPrototype(valueOwner()->datePrototype()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| const Value *RegExpCtor::invoke(const Activation *activation) const | ||||
| { | ||||
|     ObjectValue *thisObject = activation->thisObject(); | ||||
|     if (activation->calledAsFunction()) | ||||
|         thisObject = valueOwner()->newObject(); | ||||
|  | ||||
|     thisObject->setClassName("RegExp"); | ||||
|     thisObject->setPrototype(valueOwner()->regexpPrototype()); | ||||
|     thisObject->setMember("source", valueOwner()->stringValue()); | ||||
|     thisObject->setMember("global", valueOwner()->booleanValue()); | ||||
|     thisObject->setMember("ignoreCase", valueOwner()->booleanValue()); | ||||
|     thisObject->setMember("multiline", valueOwner()->booleanValue()); | ||||
|     thisObject->setMember("lastIndex", valueOwner()->numberValue()); | ||||
|     return thisObject; | ||||
| } | ||||
|  | ||||
| } // end of anonymous namespace | ||||
|  | ||||
|  | ||||
| ValueOwner::ValueOwner() | ||||
|     : _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), | ||||
|       _qtObject(0), | ||||
|       _qmlKeysObject(0), | ||||
|       _qmlFontObject(0), | ||||
|       _qmlPointObject(0), | ||||
|       _qmlSizeObject(0), | ||||
|       _qmlRectObject(0), | ||||
|       _qmlVector3DObject(0), | ||||
|       _convertToNumber(this), | ||||
|       _convertToString(this), | ||||
|       _convertToObject(this), | ||||
|       _cppQmlTypes(this) | ||||
| // globally shared data | ||||
| class QmlJS::SharedValueOwner : public ValueOwner | ||||
| { | ||||
|     initializePrototypes(); | ||||
| } | ||||
| public: | ||||
|     SharedValueOwner(); | ||||
|  | ||||
| ValueOwner::~ValueOwner() | ||||
| { | ||||
|     qDeleteAll(_registeredValues); | ||||
| } | ||||
|     ObjectValue *_objectPrototype; | ||||
|     ObjectValue *_functionPrototype; | ||||
|     ObjectValue *_numberPrototype; | ||||
|     ObjectValue *_booleanPrototype; | ||||
|     ObjectValue *_stringPrototype; | ||||
|     ObjectValue *_arrayPrototype; | ||||
|     ObjectValue *_datePrototype; | ||||
|     ObjectValue *_regexpPrototype; | ||||
|  | ||||
| const NullValue *ValueOwner::nullValue() const | ||||
| { | ||||
|     return &_nullValue; | ||||
| } | ||||
|     Function *_objectCtor; | ||||
|     Function *_functionCtor; | ||||
|     Function *_arrayCtor; | ||||
|     Function *_stringCtor; | ||||
|     Function *_booleanCtor; | ||||
|     Function *_numberCtor; | ||||
|     Function *_dateCtor; | ||||
|     Function *_regexpCtor; | ||||
|  | ||||
| const UndefinedValue *ValueOwner::undefinedValue() const | ||||
| { | ||||
|     return &_undefinedValue; | ||||
| } | ||||
|     ObjectValue *_globalObject; | ||||
|     ObjectValue *_mathObject; | ||||
|     ObjectValue *_qtObject; | ||||
|     ObjectValue *_qmlKeysObject; | ||||
|     ObjectValue *_qmlFontObject; | ||||
|     ObjectValue *_qmlPointObject; | ||||
|     ObjectValue *_qmlSizeObject; | ||||
|     ObjectValue *_qmlRectObject; | ||||
|     ObjectValue *_qmlVector3DObject; | ||||
|  | ||||
| const UnknownValue *ValueOwner::unknownValue() const | ||||
| { | ||||
|     return &_unknownValue; | ||||
| } | ||||
|     NullValue _nullValue; | ||||
|     UndefinedValue _undefinedValue; | ||||
|     UnknownValue _unknownValue; | ||||
|     NumberValue _numberValue; | ||||
|     RealValue _realValue; | ||||
|     IntValue _intValue; | ||||
|     BooleanValue _booleanValue; | ||||
|     StringValue _stringValue; | ||||
|     UrlValue _urlValue; | ||||
|     ColorValue _colorValue; | ||||
|     AnchorLineValue _anchorLineValue; | ||||
| }; | ||||
| Q_GLOBAL_STATIC(SharedValueOwner, sharedValueOwner) | ||||
|  | ||||
| const NumberValue *ValueOwner::numberValue() const | ||||
| { | ||||
|     return &_numberValue; | ||||
| } | ||||
|  | ||||
| const RealValue *ValueOwner::realValue() const | ||||
| { | ||||
|     return &_realValue; | ||||
| } | ||||
|  | ||||
| const IntValue *ValueOwner::intValue() const | ||||
| { | ||||
|     return &_intValue; | ||||
| } | ||||
|  | ||||
| const BooleanValue *ValueOwner::booleanValue() const | ||||
| { | ||||
|     return &_booleanValue; | ||||
| } | ||||
|  | ||||
| const StringValue *ValueOwner::stringValue() const | ||||
| { | ||||
|     return &_stringValue; | ||||
| } | ||||
|  | ||||
| const UrlValue *ValueOwner::urlValue() const | ||||
| { | ||||
|     return &_urlValue; | ||||
| } | ||||
|  | ||||
| const ColorValue *ValueOwner::colorValue() const | ||||
| { | ||||
|     return &_colorValue; | ||||
| } | ||||
|  | ||||
| const AnchorLineValue *ValueOwner::anchorLineValue() const | ||||
| { | ||||
|     return &_anchorLineValue; | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::newArray() | ||||
| { | ||||
|     return arrayCtor()->construct(); | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::newObject() | ||||
| { | ||||
|     return newObject(_objectPrototype); | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::newObject(const ObjectValue *prototype) | ||||
| { | ||||
|     ObjectValue *object = new ObjectValue(this); | ||||
|     object->setPrototype(prototype); | ||||
|     return object; | ||||
| } | ||||
|  | ||||
| Function *ValueOwner::newFunction() | ||||
| { | ||||
|     Function *function = new Function(this); | ||||
|     function->setPrototype(functionPrototype()); | ||||
|     return function; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::globalObject() const | ||||
| { | ||||
|     return _globalObject; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::objectPrototype() const | ||||
| { | ||||
|     return _objectPrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::functionPrototype() const | ||||
| { | ||||
|     return _functionPrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::numberPrototype() const | ||||
| { | ||||
|     return _numberPrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::booleanPrototype() const | ||||
| { | ||||
|     return _booleanPrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::stringPrototype() const | ||||
| { | ||||
|     return _stringPrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::arrayPrototype() const | ||||
| { | ||||
|     return _arrayPrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::datePrototype() const | ||||
| { | ||||
|     return _datePrototype; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::regexpPrototype() const | ||||
| { | ||||
|     return _regexpPrototype; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::objectCtor() const | ||||
| { | ||||
|     return _objectCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::functionCtor() const | ||||
| { | ||||
|     return _functionCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::arrayCtor() const | ||||
| { | ||||
|     return _arrayCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::stringCtor() const | ||||
| { | ||||
|     return _stringCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::booleanCtor() const | ||||
| { | ||||
|     return _booleanCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::numberCtor() const | ||||
| { | ||||
|     return _numberCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::dateCtor() const | ||||
| { | ||||
|     return _dateCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::regexpCtor() const | ||||
| { | ||||
|     return _regexpCtor; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::mathObject() const | ||||
| { | ||||
|     return _mathObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qtObject() const | ||||
| { | ||||
|     return _qtObject; | ||||
| } | ||||
|  | ||||
| void ValueOwner::registerValue(Value *value) | ||||
| { | ||||
|     // ### get rid of this lock | ||||
|     QMutexLocker locker(&_mutex); | ||||
|     _registeredValues.append(value); | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToBoolean(const Value *value) | ||||
| { | ||||
|     return _convertToNumber(value);  // ### implement convert to bool | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToNumber(const Value *value) | ||||
| { | ||||
|     return _convertToNumber(value); | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToString(const Value *value) | ||||
| { | ||||
|     return _convertToString(value); | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToObject(const Value *value) | ||||
| { | ||||
|     return _convertToObject(value); | ||||
| } | ||||
|  | ||||
| QString ValueOwner::typeId(const Value *value) | ||||
| { | ||||
|     return _typeId(value); | ||||
| } | ||||
|  | ||||
| Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount, int optionalCount, bool variadic) | ||||
| { | ||||
|     Function *function = addFunction(object, name, argumentCount, optionalCount, variadic); | ||||
|     function->setReturnValue(result); | ||||
|     return function; | ||||
| } | ||||
|  | ||||
| Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, int argumentCount, int optionalCount, bool variadic) | ||||
| { | ||||
|     Function *function = newFunction(); | ||||
|     for (int i = 0; i < argumentCount; ++i) | ||||
|         function->addArgument(unknownValue()); | ||||
|     function->setVariadic(variadic); | ||||
|     function->setOptionalNamedArgumentCount(optionalCount); | ||||
|     object->setMember(name, function); | ||||
|     return function; | ||||
| } | ||||
|  | ||||
| void ValueOwner::initializePrototypes() | ||||
| SharedValueOwner::SharedValueOwner() | ||||
|     : ValueOwner(this) // need to avoid recursing in ValueOwner ctor | ||||
| { | ||||
|     _objectPrototype   = newObject(/*prototype = */ 0); | ||||
|     _functionPrototype = newObject(_objectPrototype); | ||||
| @@ -532,62 +130,76 @@ void ValueOwner::initializePrototypes() | ||||
|     _globalObject = newObject(); | ||||
|     _globalObject->setClassName("Global"); | ||||
|  | ||||
|     // set up the default Object prototype | ||||
|     _objectCtor = new ObjectCtor(this); | ||||
|     _objectCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *objectInstance = newObject(); | ||||
|     objectInstance->setClassName("Object"); | ||||
|     objectInstance->setMember("length", numberValue()); | ||||
|     _objectCtor = new Function(this); | ||||
|     _objectCtor->setMember("prototype", _objectPrototype); | ||||
|     _objectCtor->setReturnValue(newObject()); | ||||
|     _objectCtor->setReturnValue(objectInstance); | ||||
|     _objectCtor->addArgument(unknownValue(), "value"); | ||||
|     _objectCtor->setOptionalNamedArgumentCount(1); | ||||
|  | ||||
|     _functionCtor = new FunctionCtor(this); | ||||
|     _functionCtor->setPrototype(_functionPrototype); | ||||
|     FunctionValue *functionInstance = new FunctionValue(this); | ||||
|     _functionCtor = new Function(this); | ||||
|     _functionCtor->setMember("prototype", _functionPrototype); | ||||
|     _functionCtor->setReturnValue(newFunction()); | ||||
|     _functionCtor->setReturnValue(functionInstance); | ||||
|     _functionCtor->setVariadic(true); | ||||
|  | ||||
|     _arrayCtor = new ArrayCtor(this); | ||||
|     _arrayCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *arrayInstance = newObject(_arrayPrototype); | ||||
|     arrayInstance->setClassName("Array"); | ||||
|     arrayInstance->setMember("length", numberValue()); | ||||
|     _arrayCtor = new Function(this); | ||||
|     _arrayCtor->setMember("prototype", _arrayPrototype); | ||||
|     _arrayCtor->setReturnValue(newArray()); | ||||
|     _arrayCtor->setReturnValue(arrayInstance); | ||||
|     _arrayCtor->setVariadic(true); | ||||
|  | ||||
|     _stringCtor = new StringCtor(this); | ||||
|     _stringCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *stringInstance = newObject(_stringPrototype); | ||||
|     stringInstance->setClassName("String"); | ||||
|     stringInstance->setMember("length", numberValue()); | ||||
|     _stringCtor = new Function(this); | ||||
|     _stringCtor->setMember("prototype", _stringPrototype); | ||||
|     _stringCtor->setReturnValue(stringValue()); | ||||
|     _stringCtor->setReturnValue(stringInstance); | ||||
|     _stringCtor->addArgument(unknownValue(), "value"); | ||||
|     _stringCtor->setOptionalNamedArgumentCount(1); | ||||
|  | ||||
|     _booleanCtor = new BooleanCtor(this); | ||||
|     _booleanCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *booleanInstance = newObject(_booleanPrototype); | ||||
|     booleanInstance->setClassName("Boolean"); | ||||
|     _booleanCtor = new Function(this); | ||||
|     _booleanCtor->setMember("prototype", _booleanPrototype); | ||||
|     _booleanCtor->setReturnValue(booleanValue()); | ||||
|     _booleanCtor->setReturnValue(booleanInstance); | ||||
|     _booleanCtor->addArgument(unknownValue(), "value"); | ||||
|  | ||||
|     _numberCtor = new NumberCtor(this); | ||||
|     _numberCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *numberInstance = newObject(_numberPrototype); | ||||
|     numberInstance->setClassName("Number"); | ||||
|     _numberCtor = new Function(this); | ||||
|     _numberCtor->setMember("prototype", _numberPrototype); | ||||
|     _numberCtor->setReturnValue(numberValue()); | ||||
|     _numberCtor->setReturnValue(numberInstance); | ||||
|     _numberCtor->addArgument(unknownValue(), "value"); | ||||
|     _numberCtor->setOptionalNamedArgumentCount(1); | ||||
|  | ||||
|     _dateCtor = new DateCtor(this); | ||||
|     _dateCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *dateInstance = newObject(_datePrototype); | ||||
|     dateInstance->setClassName("Date"); | ||||
|     _dateCtor = new Function(this); | ||||
|     _dateCtor->setMember("prototype", _datePrototype); | ||||
|     _dateCtor->setReturnValue(_datePrototype); | ||||
|     _dateCtor->setReturnValue(dateInstance); | ||||
|     _dateCtor->setVariadic(true); | ||||
|  | ||||
|     _regexpCtor = new RegExpCtor(this); | ||||
|     _regexpCtor->setPrototype(_functionPrototype); | ||||
|     ObjectValue *regexpInstance = newObject(_regexpPrototype); | ||||
|     regexpInstance->setClassName("RegExp"); | ||||
|     regexpInstance->setMember("source", stringValue()); | ||||
|     regexpInstance->setMember("global", booleanValue()); | ||||
|     regexpInstance->setMember("ignoreCase", booleanValue()); | ||||
|     regexpInstance->setMember("multiline", booleanValue()); | ||||
|     regexpInstance->setMember("lastIndex", numberValue()); | ||||
|     _regexpCtor = new Function(this); | ||||
|     _regexpCtor->setMember("prototype", _regexpPrototype); | ||||
|     _regexpCtor->setReturnValue(_regexpPrototype); | ||||
|     _regexpCtor->setReturnValue(regexpInstance); | ||||
|     _regexpCtor->addArgument(unknownValue(), "pattern"); | ||||
|     _regexpCtor->addArgument(unknownValue(), "flags"); | ||||
|  | ||||
|     addFunction(_objectCtor, "getPrototypeOf", 1); | ||||
|     addFunction(_objectCtor, "getOwnPropertyDescriptor", 2); | ||||
|     addFunction(_objectCtor, "getOwnPropertyNames", newArray(), 1); | ||||
|     addFunction(_objectCtor, "getOwnPropertyNames", arrayInstance, 1); | ||||
|     addFunction(_objectCtor, "create", 1, 1); | ||||
|     addFunction(_objectCtor, "defineProperty", 3); | ||||
|     addFunction(_objectCtor, "defineProperties", 2); | ||||
| @@ -597,7 +209,7 @@ void ValueOwner::initializePrototypes() | ||||
|     addFunction(_objectCtor, "isSealed", booleanValue(), 1); | ||||
|     addFunction(_objectCtor, "isFrozen", booleanValue(), 1); | ||||
|     addFunction(_objectCtor, "isExtensible", booleanValue(), 1); | ||||
|     addFunction(_objectCtor, "keys", newArray(), 1); | ||||
|     addFunction(_objectCtor, "keys", arrayInstance, 1); | ||||
|  | ||||
|     addFunction(_objectPrototype, "toString", stringValue(), 0); | ||||
|     addFunction(_objectPrototype, "toLocaleString", stringValue(), 0); | ||||
| @@ -651,11 +263,11 @@ void ValueOwner::initializePrototypes() | ||||
|     addFunction(_stringPrototype, "indexOf", numberValue(), 2); | ||||
|     addFunction(_stringPrototype, "lastIndexOf", numberValue(), 2); | ||||
|     addFunction(_stringPrototype, "localeCompare", booleanValue(), 1); | ||||
|     addFunction(_stringPrototype, "match", newArray(), 1); | ||||
|     addFunction(_stringPrototype, "match", arrayInstance, 1); | ||||
|     addFunction(_stringPrototype, "replace", stringValue(), 2); | ||||
|     addFunction(_stringPrototype, "search", numberValue(), 1); | ||||
|     addFunction(_stringPrototype, "slice", stringValue(), 2); | ||||
|     addFunction(_stringPrototype, "split", newArray(), 1); | ||||
|     addFunction(_stringPrototype, "split", arrayInstance, 1); | ||||
|     addFunction(_stringPrototype, "substring", stringValue(), 2); | ||||
|     addFunction(_stringPrototype, "toLowerCase", stringValue(), 0); | ||||
|     addFunction(_stringPrototype, "toLocaleLowerCase", stringValue(), 0); | ||||
| @@ -767,7 +379,7 @@ void ValueOwner::initializePrototypes() | ||||
|  | ||||
|     // set up the default Boolean prototype | ||||
|     _regexpPrototype->setMember("constructor", _regexpCtor); | ||||
|     addFunction(_regexpPrototype, "exec", newArray(), 1); | ||||
|     addFunction(_regexpPrototype, "exec", arrayInstance, 1); | ||||
|     addFunction(_regexpPrototype, "test", booleanValue(), 1); | ||||
|     addFunction(_regexpPrototype, "toString", stringValue(), 0); | ||||
|  | ||||
| @@ -889,7 +501,7 @@ void ValueOwner::initializePrototypes() | ||||
|     _qmlVector3DObject->setMember("z", realValue()); | ||||
|  | ||||
|     // global Qt object, in alphabetic order | ||||
|     _qtObject = newObject(/*prototype */ 0); | ||||
|     _qtObject = newObject(new QtObjectPrototypeReference(this)); | ||||
|     addFunction(_qtObject, QLatin1String("atob"), &_stringValue, 1); | ||||
|     addFunction(_qtObject, QLatin1String("btoa"), &_stringValue, 1); | ||||
|     addFunction(_qtObject, QLatin1String("createComponent"), 1); | ||||
| @@ -930,34 +542,264 @@ void ValueOwner::initializePrototypes() | ||||
|     addFunction(_globalObject, QLatin1String("QT_TRID_NOOP"), 1); | ||||
| } | ||||
|  | ||||
|  | ||||
| ValueOwner::ValueOwner(const SharedValueOwner *shared) | ||||
|     : _convertToNumber(this) | ||||
|     , _convertToString(this) | ||||
|     , _convertToObject(this) | ||||
|     , _cppQmlTypes(this) | ||||
| { | ||||
|     if (shared) | ||||
|         _shared = shared; | ||||
|     else | ||||
|         _shared = sharedValueOwner(); | ||||
| } | ||||
|  | ||||
| ValueOwner::~ValueOwner() | ||||
| { | ||||
|     qDeleteAll(_registeredValues); | ||||
| } | ||||
|  | ||||
| const NullValue *ValueOwner::nullValue() const | ||||
| { | ||||
|     return &_shared->_nullValue; | ||||
| } | ||||
|  | ||||
| const UndefinedValue *ValueOwner::undefinedValue() const | ||||
| { | ||||
|     return &_shared->_undefinedValue; | ||||
| } | ||||
|  | ||||
| const UnknownValue *ValueOwner::unknownValue() const | ||||
| { | ||||
|     return &_shared->_unknownValue; | ||||
| } | ||||
|  | ||||
| const NumberValue *ValueOwner::numberValue() const | ||||
| { | ||||
|     return &_shared->_numberValue; | ||||
| } | ||||
|  | ||||
| const RealValue *ValueOwner::realValue() const | ||||
| { | ||||
|     return &_shared->_realValue; | ||||
| } | ||||
|  | ||||
| const IntValue *ValueOwner::intValue() const | ||||
| { | ||||
|     return &_shared->_intValue; | ||||
| } | ||||
|  | ||||
| const BooleanValue *ValueOwner::booleanValue() const | ||||
| { | ||||
|     return &_shared->_booleanValue; | ||||
| } | ||||
|  | ||||
| const StringValue *ValueOwner::stringValue() const | ||||
| { | ||||
|     return &_shared->_stringValue; | ||||
| } | ||||
|  | ||||
| const UrlValue *ValueOwner::urlValue() const | ||||
| { | ||||
|     return &_shared->_urlValue; | ||||
| } | ||||
|  | ||||
| const ColorValue *ValueOwner::colorValue() const | ||||
| { | ||||
|     return &_shared->_colorValue; | ||||
| } | ||||
|  | ||||
| const AnchorLineValue *ValueOwner::anchorLineValue() const | ||||
| { | ||||
|     return &_shared->_anchorLineValue; | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::newObject() | ||||
| { | ||||
|     return newObject(_shared->_objectPrototype); | ||||
| } | ||||
|  | ||||
| ObjectValue *ValueOwner::newObject(const Value *prototype) | ||||
| { | ||||
|     ObjectValue *object = new ObjectValue(this); | ||||
|     object->setPrototype(prototype); | ||||
|     return object; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::globalObject() const | ||||
| { | ||||
|     return _shared->_globalObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::objectPrototype() const | ||||
| { | ||||
|     return _shared->_objectPrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::functionPrototype() const | ||||
| { | ||||
|     return _shared->_functionPrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::numberPrototype() const | ||||
| { | ||||
|     return _shared->_numberPrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::booleanPrototype() const | ||||
| { | ||||
|     return _shared->_booleanPrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::stringPrototype() const | ||||
| { | ||||
|     return _shared->_stringPrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::arrayPrototype() const | ||||
| { | ||||
|     return _shared->_arrayPrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::datePrototype() const | ||||
| { | ||||
|     return _shared->_datePrototype; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::regexpPrototype() const | ||||
| { | ||||
|     return _shared->_regexpPrototype; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::objectCtor() const | ||||
| { | ||||
|     return _shared->_objectCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::functionCtor() const | ||||
| { | ||||
|     return _shared->_functionCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::arrayCtor() const | ||||
| { | ||||
|     return _shared->_arrayCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::stringCtor() const | ||||
| { | ||||
|     return _shared->_stringCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::booleanCtor() const | ||||
| { | ||||
|     return _shared->_booleanCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::numberCtor() const | ||||
| { | ||||
|     return _shared->_numberCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::dateCtor() const | ||||
| { | ||||
|     return _shared->_dateCtor; | ||||
| } | ||||
|  | ||||
| const FunctionValue *ValueOwner::regexpCtor() const | ||||
| { | ||||
|     return _shared->_regexpCtor; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::mathObject() const | ||||
| { | ||||
|     return _shared->_mathObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qtObject() const | ||||
| { | ||||
|     return _shared->_qtObject; | ||||
| } | ||||
|  | ||||
| void ValueOwner::registerValue(Value *value) | ||||
| { | ||||
|     // ### get rid of this lock | ||||
|     QMutexLocker locker(&_mutex); | ||||
|     _registeredValues.append(value); | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToBoolean(const Value *value) | ||||
| { | ||||
|     return _convertToNumber(value);  // ### implement convert to bool | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToNumber(const Value *value) | ||||
| { | ||||
|     return _convertToNumber(value); | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToString(const Value *value) | ||||
| { | ||||
|     return _convertToString(value); | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::convertToObject(const Value *value) | ||||
| { | ||||
|     return _convertToObject(value); | ||||
| } | ||||
|  | ||||
| QString ValueOwner::typeId(const Value *value) | ||||
| { | ||||
|     return _typeId(value); | ||||
| } | ||||
|  | ||||
| Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount, int optionalCount, bool variadic) | ||||
| { | ||||
|     Function *function = addFunction(object, name, argumentCount, optionalCount, variadic); | ||||
|     function->setReturnValue(result); | ||||
|     return function; | ||||
| } | ||||
|  | ||||
| Function *ValueOwner::addFunction(ObjectValue *object, const QString &name, int argumentCount, int optionalCount, bool variadic) | ||||
| { | ||||
|     Function *function = new Function(this); | ||||
|     for (int i = 0; i < argumentCount; ++i) | ||||
|         function->addArgument(unknownValue()); | ||||
|     function->setVariadic(variadic); | ||||
|     function->setOptionalNamedArgumentCount(optionalCount); | ||||
|     object->setMember(name, function); | ||||
|     return function; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qmlKeysObject() | ||||
| { | ||||
|     return _qmlKeysObject; | ||||
|     return _shared->_qmlKeysObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qmlFontObject() | ||||
| { | ||||
|     return _qmlFontObject; | ||||
|     return _shared->_qmlFontObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qmlPointObject() | ||||
| { | ||||
|     return _qmlPointObject; | ||||
|     return _shared->_qmlPointObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qmlSizeObject() | ||||
| { | ||||
|     return _qmlSizeObject; | ||||
|     return _shared->_qmlSizeObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qmlRectObject() | ||||
| { | ||||
|     return _qmlRectObject; | ||||
|     return _shared->_qmlRectObject; | ||||
| } | ||||
|  | ||||
| const ObjectValue *ValueOwner::qmlVector3DObject() | ||||
| { | ||||
|     return _qmlVector3DObject; | ||||
|     return _shared->_qmlVector3DObject; | ||||
| } | ||||
|  | ||||
| const Value *ValueOwner::defaultValueForBuiltinType(const QString &name) const | ||||
|   | ||||
| @@ -62,13 +62,14 @@ class Imports; | ||||
| class TypeScope; | ||||
| class JSImportScope; | ||||
| class Function; | ||||
| class SharedValueOwner; | ||||
|  | ||||
| class QMLJS_EXPORT ValueOwner | ||||
| { | ||||
|     Q_DISABLE_COPY(ValueOwner) | ||||
|  | ||||
| public: | ||||
|     ValueOwner(); | ||||
|     ValueOwner(const SharedValueOwner *shared = 0); | ||||
|     ~ValueOwner(); | ||||
|  | ||||
|     const NullValue *nullValue() const; | ||||
| @@ -83,10 +84,8 @@ public: | ||||
|     const ColorValue *colorValue() const; | ||||
|     const AnchorLineValue *anchorLineValue() const; | ||||
|  | ||||
|     ObjectValue *newObject(const ObjectValue *prototype); | ||||
|     ObjectValue *newObject(const Value *prototype); | ||||
|     ObjectValue *newObject(); | ||||
|     Function *newFunction(); | ||||
|     const Value *newArray(); // ### remove me | ||||
|  | ||||
|     // QML objects | ||||
|     const ObjectValue *qmlKeysObject(); | ||||
| @@ -100,19 +99,19 @@ public: | ||||
|     const Value *defaultValueForBuiltinType(const QString &typeName) const; | ||||
|  | ||||
|     // global object | ||||
|     ObjectValue *globalObject() const; | ||||
|     const ObjectValue *globalObject() const; | ||||
|     const ObjectValue *mathObject() const; | ||||
|     const ObjectValue *qtObject() const; | ||||
|  | ||||
|     // prototypes | ||||
|     ObjectValue *objectPrototype() const; | ||||
|     ObjectValue *functionPrototype() const; | ||||
|     ObjectValue *numberPrototype() const; | ||||
|     ObjectValue *booleanPrototype() const; | ||||
|     ObjectValue *stringPrototype() const; | ||||
|     ObjectValue *arrayPrototype() const; | ||||
|     ObjectValue *datePrototype() const; | ||||
|     ObjectValue *regexpPrototype() const; | ||||
|     const ObjectValue *objectPrototype() const; | ||||
|     const ObjectValue *functionPrototype() const; | ||||
|     const ObjectValue *numberPrototype() const; | ||||
|     const ObjectValue *booleanPrototype() const; | ||||
|     const ObjectValue *stringPrototype() const; | ||||
|     const ObjectValue *arrayPrototype() const; | ||||
|     const ObjectValue *datePrototype() const; | ||||
|     const ObjectValue *regexpPrototype() const; | ||||
|  | ||||
|     // ctors | ||||
|     const FunctionValue *objectCtor() const; | ||||
| @@ -139,64 +138,22 @@ public: | ||||
|  | ||||
|     void registerValue(Value *value); // internal | ||||
|  | ||||
| private: | ||||
|     void initializePrototypes(); | ||||
|  | ||||
| protected: | ||||
|     Function *addFunction(ObjectValue *object, const QString &name, const Value *result, | ||||
|                           int argumentCount = 0, int optionalCount = 0, bool variadic = false); | ||||
|     Function *addFunction(ObjectValue *object, const QString &name, | ||||
|                           int argumentCount = 0, int optionalCount = 0, bool variadic = false); | ||||
|  | ||||
| private: | ||||
|     ObjectValue *_objectPrototype; | ||||
|     ObjectValue *_functionPrototype; | ||||
|     ObjectValue *_numberPrototype; | ||||
|     ObjectValue *_booleanPrototype; | ||||
|     ObjectValue *_stringPrototype; | ||||
|     ObjectValue *_arrayPrototype; | ||||
|     ObjectValue *_datePrototype; | ||||
|     ObjectValue *_regexpPrototype; | ||||
|  | ||||
|     Function *_objectCtor; | ||||
|     Function *_functionCtor; | ||||
|     Function *_arrayCtor; | ||||
|     Function *_stringCtor; | ||||
|     Function *_booleanCtor; | ||||
|     Function *_numberCtor; | ||||
|     Function *_dateCtor; | ||||
|     Function *_regexpCtor; | ||||
|  | ||||
|     ObjectValue *_globalObject; | ||||
|     ObjectValue *_mathObject; | ||||
|     ObjectValue *_qtObject; | ||||
|     ObjectValue *_qmlKeysObject; | ||||
|     ObjectValue *_qmlFontObject; | ||||
|     ObjectValue *_qmlPointObject; | ||||
|     ObjectValue *_qmlSizeObject; | ||||
|     ObjectValue *_qmlRectObject; | ||||
|     ObjectValue *_qmlVector3DObject; | ||||
|  | ||||
|     NullValue _nullValue; | ||||
|     UndefinedValue _undefinedValue; | ||||
|     UnknownValue _unknownValue; | ||||
|     NumberValue _numberValue; | ||||
|     RealValue _realValue; | ||||
|     IntValue _intValue; | ||||
|     BooleanValue _booleanValue; | ||||
|     StringValue _stringValue; | ||||
|     UrlValue _urlValue; | ||||
|     ColorValue _colorValue; | ||||
|     AnchorLineValue _anchorLineValue; | ||||
|     QList<Value *> _registeredValues; | ||||
|     QMutex _mutex; | ||||
|  | ||||
|     ConvertToNumber _convertToNumber; | ||||
|     ConvertToString _convertToString; | ||||
|     ConvertToObject _convertToObject; | ||||
|     TypeId _typeId; | ||||
|  | ||||
|     CppQmlTypes _cppQmlTypes; | ||||
|  | ||||
|     QMutex _mutex; | ||||
|     const SharedValueOwner *_shared; | ||||
| }; | ||||
|  | ||||
| } // namespace QmlJS | ||||
|   | ||||
		Reference in New Issue
	
	Block a user