summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qml.pri1
-rw-r--r--src/declarative/qml/qmlcompiler.cpp78
-rw-r--r--src/declarative/qml/qmlcompiler_p.h1
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h22
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp152
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h6
-rw-r--r--src/declarative/qml/qmlcontext.cpp39
-rw-r--r--src/declarative/qml/qmlcontext_p.h1
-rw-r--r--src/declarative/qml/qmlinstruction_p.h4
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp2
-rw-r--r--src/declarative/qml/qmlparser.cpp2
-rw-r--r--src/declarative/qml/qmlparser_p.h5
-rw-r--r--src/declarative/qml/qmlscript.cpp (renamed from src/declarative/util/qmlscript.h)70
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp51
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h2
-rw-r--r--src/declarative/qml/qmlvme.cpp7
-rw-r--r--src/declarative/util/qmlscript.cpp209
-rw-r--r--src/declarative/util/util.pri2
18 files changed, 393 insertions, 261 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index e46dd3f..a2e2050 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -35,6 +35,7 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlsqldatabase.cpp \
qml/qmetaobjectbuilder.cpp \
qml/qmlwatcher.cpp \
+ qml/qmlscript.cpp \
qml/qmlpropertycache.cpp \
qml/qmlintegercache.cpp \
qml/qmltypenamecache.cpp \
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 4b5c5bf..12e8101 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -669,7 +669,11 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
if (obj->metatype == &QmlComponent::staticMetaObject) {
COMPILE_CHECK(buildComponent(obj, ctxt));
return true;
- }
+ }
+
+ // Build any script blocks for this type
+ for (int ii = 0; ii < obj->scriptBlockObjects.count(); ++ii)
+ COMPILE_CHECK(buildScript(obj, obj->scriptBlockObjects.at(ii)));
// Object instantiations reset the binding context
BindingContext objCtxt(obj);
@@ -824,6 +828,15 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
output->bytecode << id;
}
+ // Set any script blocks
+ for (int ii = 0; ii < obj->scriptBlocks.count(); ++ii) {
+ QmlInstruction script;
+ script.type = QmlInstruction::StoreScript;
+ script.line = -1; // ###
+ script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii));
+ output->bytecode << script;
+ }
+
// Begin the class
if (obj->parserStatusCast != -1) {
QmlInstruction begin;
@@ -1000,7 +1013,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
// Find, check and set the "id" property (if any)
Property *idProp = 0;
if (obj->properties.count() > 1 ||
- (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id") ||
+ !obj->scriptBlockObjects.isEmpty())
COMPILE_EXCEPTION(obj, "Invalid component specification");
if (obj->properties.count())
@@ -1037,6 +1051,66 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
return true;
}
+bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
+{
+ QString scriptCode;
+
+ if (script->properties.count() == 1 &&
+ script->properties.begin().key() == QByteArray("source")) {
+
+ Property *source = *script->properties.begin();
+ if (script->defaultProperty)
+ COMPILE_EXCEPTION(source, "Invalid Script block. Specify either the source property or inline script.");
+
+ if (source->value || source->values.count() != 1 ||
+ source->values.at(0)->object || !source->values.at(0)->value.isString())
+ COMPILE_EXCEPTION(source, "Invalid Script source value");
+
+ QString sourceUrl =
+ output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString();
+
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ if (unit->resources.at(ii)->url == sourceUrl) {
+ scriptCode = QString::fromUtf8(unit->resources.at(ii)->data);
+ break;
+ }
+ }
+
+ } else if (!script->properties.isEmpty()) {
+ COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block");
+ } else if (script->defaultProperty) {
+ QmlParser::Location currentLocation;
+
+ for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) {
+ Value *v = script->defaultProperty->values.at(ii);
+ if (v->object || !v->value.isString())
+ COMPILE_EXCEPTION(v, "Invalid Script block");
+
+ if (ii == 0) {
+ currentLocation = v->location.start;
+ scriptCode.append(QString(currentLocation.column, QLatin1Char(' ')));
+ }
+
+ while (currentLocation.line < v->location.start.line) {
+ scriptCode.append(QLatin1String("\n"));
+ currentLocation.line++;
+ currentLocation.column = 0;
+ }
+
+ scriptCode.append(QString(v->location.start.column - currentLocation.column, QLatin1Char(' ')));
+
+ scriptCode += v->value.asString();
+ currentLocation = v->location.end;
+ currentLocation.column++;
+ }
+ }
+
+ if (!scriptCode.isEmpty())
+ obj->scriptBlocks.append(scriptCode);
+
+ return true;
+}
+
bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj,
const BindingContext &ctxt)
{
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index fd361fd..1d27342 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -171,6 +171,7 @@ private:
bool buildObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildScript(QmlParser::Object *obj, QmlParser::Object *script);
bool buildComponent(QmlParser::Object *obj, const BindingContext &);
bool buildSubObject(QmlParser::Object *obj, const BindingContext &);
bool buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
index 48c6c2b..fa11137 100644
--- a/src/declarative/qml/qmlcompositetypedata_p.h
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -58,6 +58,7 @@
QT_BEGIN_NAMESPACE
+class QmlCompositeTypeResource;
class QmlCompositeTypeData : public QmlRefCount
{
public:
@@ -101,6 +102,7 @@ public:
};
QList<TypeReference> types;
+ QList<QmlCompositeTypeResource *> resources;
// Add or remove p as a waiter. When the QmlCompositeTypeData becomes
// ready, the QmlComponentPrivate::typeDataReady() method will be invoked on
@@ -122,5 +124,25 @@ private:
QmlCompiledData *compiledComponent;
};
+class QmlCompositeTypeResource : public QmlRefCount
+{
+public:
+ QmlCompositeTypeResource();
+ virtual ~QmlCompositeTypeResource();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+
+ QList<QmlCompositeTypeData *> dependants;
+
+ QString url;
+ QByteArray data;
+};
+
#endif // QMLCOMPOSITETYPEDATA_P_H
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index a99cff0..71b4ef0 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -63,6 +63,9 @@ QmlCompositeTypeData::~QmlCompositeTypeData()
for (int ii = 0; ii < dependants.count(); ++ii)
dependants.at(ii)->release();
+ for (int ii = 0; ii < resources.count(); ++ii)
+ resources.at(ii)->release();
+
if (compiledComponent)
compiledComponent->release();
@@ -70,6 +73,16 @@ QmlCompositeTypeData::~QmlCompositeTypeData()
delete component;
}
+QmlCompositeTypeResource::QmlCompositeTypeResource()
+{
+}
+
+QmlCompositeTypeResource::~QmlCompositeTypeResource()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+}
+
void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p)
{
waiters << p;
@@ -142,6 +155,10 @@ QmlCompositeTypeManager::~QmlCompositeTypeManager()
(*iter)->release();
iter = components.erase(iter);
}
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ }
}
QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
@@ -181,8 +198,16 @@ void QmlCompositeTypeManager::clearCache()
++iter;
}
}
-}
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ if ((*iter)->status != QmlCompositeTypeResource::Waiting) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
void QmlCompositeTypeManager::replyFinished()
{
@@ -215,6 +240,52 @@ void QmlCompositeTypeManager::replyFinished()
reply->deleteLater();
}
+void QmlCompositeTypeManager::resourceReplyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeResource *resource = resources.value(reply->url().toString());
+ Q_ASSERT(resource);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ resource->status = QmlCompositeTypeResource::Error;
+
+ } else {
+
+ resource->status = QmlCompositeTypeResource::Complete;
+ resource->data = reply->readAll();
+
+ }
+
+ doComplete(resource);
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource)
+{
+ QUrl url(resource->url);
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QFile file(url.toLocalFile());
+ if (file.open(QFile::ReadOnly)) {
+ resource->data = file.readAll();
+ resource->status = QmlCompositeTypeResource::Complete;
+ } else {
+ resource->status = QmlCompositeTypeResource::Error;
+ }
+
+ } else {
+
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(resourceReplyFinished()));
+
+ }
+}
+
void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
{
QUrl url(unit->imports.baseUrl());
@@ -308,6 +379,15 @@ void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
}
}
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeResource *resource)
+{
+ for (int ii = 0; ii < resource->dependants.count(); ++ii) {
+ checkComplete(resource->dependants.at(ii));
+ resource->dependants.at(ii)->release();
+ }
+ resource->dependants.clear();
+}
+
void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
{
if (unit->status != QmlCompositeTypeData::Waiting)
@@ -329,12 +409,33 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
waiting++;
}
}
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ QmlCompositeTypeResource *r = unit->resources.at(ii);
+
+ if (!r)
+ continue;
+
+ if (r->status == QmlCompositeTypeResource::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(QLatin1String("Resource ") + r->url +
+ QLatin1String(" unavailable"));
+ unit->errors << error;
+ doComplete(unit);
+ return;
+ } else if (r->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+
if (!waiting) {
unit->status = QmlCompositeTypeData::Complete;
doComplete(unit);
}
}
+// ### Check ref counting in here
void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
{
QList<QmlScriptParser::TypeReference*> types = unit->data.referencedTypes();
@@ -346,12 +447,6 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
QmlCompositeTypeData::TypeReference ref;
- if (typeName == QByteArray("Property") ||
- typeName == QByteArray("Signal")) {
- unit->types << ref;
- continue;
- }
-
QUrl url;
int majorVersion;
int minorVersion;
@@ -431,6 +526,49 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
unit->types << ref;
}
+ QList<QUrl> resourceList = unit->data.referencedResources();
+ for (int ii = 0; ii < resourceList.count(); ++ii) {
+ QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii));
+
+ QmlCompositeTypeResource *resource = resources.value(url.toString());
+
+ if (!resource) {
+ resource = new QmlCompositeTypeResource;
+ resource->status = QmlCompositeTypeResource::Waiting;
+ resource->url = url.toString();
+ resources.insert(resource->url, resource);
+
+ loadResource(resource);
+ }
+
+ switch(resource->status) {
+ case QmlCompositeTypeResource::Invalid:
+ case QmlCompositeTypeResource::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(QLatin1String("Resource ") + resource->url +
+ QLatin1String(" unavailable"));
+ unit->errors << error;
+ }
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ resource->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ resource->addref();
+ unit->resources << resource;
+ }
+
if (waiting) {
unit->status = QmlCompositeTypeData::Waiting;
} else {
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
index 8f16998..843a9cf 100644
--- a/src/declarative/qml/qmlcompositetypemanager_p.h
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -67,6 +67,7 @@ class QmlComponent;
class QmlDomDocument;
class QmlCompositeTypeData;
+class QmlCompositeTypeResource;
class QmlCompositeTypeManager : public QObject
{
@@ -88,19 +89,24 @@ public:
private Q_SLOTS:
void replyFinished();
+ void resourceReplyFinished();
void requestProgress(qint64 received, qint64 total);
private:
void loadSource(QmlCompositeTypeData *);
+ void loadResource(QmlCompositeTypeResource *);
void compile(QmlCompositeTypeData *);
void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &);
void doComplete(QmlCompositeTypeData *);
+ void doComplete(QmlCompositeTypeResource *);
void checkComplete(QmlCompositeTypeData *);
QmlEngine *engine;
typedef QHash<QString, QmlCompositeTypeData *> Components;
Components components;
+ typedef QHash<QString, QmlCompositeTypeResource *> Resources;
+ Resources resources;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index a1eb5de..549925f 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -48,6 +48,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
#include <private/qmlbindingoptimizations_p.h>
+#include <QtDeclarative/qmlinfo.h>
// 6-bits
#define MAXIMUM_DEFAULT_OBJECTS 63
@@ -60,6 +61,44 @@ QmlContextPrivate::QmlContextPrivate()
{
}
+void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject)
+{
+ if (!engine)
+ return;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(scriptValue);
+
+ if (scopeObject)
+ scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject));
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+
+ QScriptValue val = scriptEngine->evaluate(script);
+
+ if (scriptEngine->hasUncaughtException()) {
+ if (scriptEngine->uncaughtException().isError()){
+ QScriptValue exception = scriptEngine->uncaughtException();
+ if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
+ qWarning() << exception.property(QLatin1String("fileName")).toString()
+ << scriptEngine->uncaughtExceptionLineNumber()
+ << exception.toString();
+
+ } else {
+ qmlInfo(scopeObject) << exception.toString();
+ }
+ }
+ }
+
+ scriptEngine->popContext();
+
+ scripts.append(scope);
+}
+
void QmlContextPrivate::dump()
{
dump(0);
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index 22e5895..d18bfda 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -94,6 +94,7 @@ public:
QScriptValue scriptValue;
QList<QScriptValue> scripts;
+ void addScript(const QString &script, QObject *scope);
QUrl url;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 38b3191..1dcdace 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -118,6 +118,7 @@ public:
StoreInterface, /* storeObject */
StoreSignal, /* storeSignal */
+ StoreScript, /* storeScript */
//
// Unresolved single assignment
@@ -238,6 +239,9 @@ public:
int value;
} storeString;
struct {
+ int value;
+ } storeScript;
+ struct {
int propertyIndex;
int value;
} storeUrl;
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 155b34a..302ce8c 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -564,7 +564,7 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
if (!isProperty() || (type() & Attached) || !d->object)
return 0;
- d->setBinding(d->object, d->core, newBinding);
+ return d->setBinding(d->object, d->core, newBinding);
}
QmlAbstractBinding *
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 39fe1e2..8c46939 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -82,6 +82,8 @@ QmlParser::Object::~Object()
prop->release();
foreach(const DynamicProperty &prop, dynamicProperties)
if (prop.defaultValue) prop.defaultValue->release();
+ foreach(Object *obj, scriptBlockObjects)
+ obj->release();
}
void Object::setBindingBit(int b)
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index e0579b0..16862eb 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -151,6 +151,8 @@ namespace QmlParser
Property *defaultProperty;
QHash<QByteArray, Property *> properties;
+ QList<Object *> scriptBlockObjects;
+
// Output of the compilation phase (these properties continue to exist
// in either the defaultProperty or properties members too)
void addValueProperty(Property *);
@@ -164,6 +166,9 @@ namespace QmlParser
QList<Property *> groupedProperties;
QList<Property *> valueTypeProperties;
+ // Script blocks that were nested under this object
+ QStringList scriptBlocks;
+
// The bytes to cast instances by to get to the QmlParserStatus
// interface. -1 indicates the type doesn't support this interface.
// Set by the QmlCompiler.
diff --git a/src/declarative/util/qmlscript.h b/src/declarative/qml/qmlscript.cpp
index 4ba4f6b..307d72f 100644
--- a/src/declarative/util/qmlscript.h
+++ b/src/declarative/qml/qmlscript.cpp
@@ -39,46 +39,44 @@
**
****************************************************************************/
-#ifndef QMLSCRIPT_H
-#define QMLSCRIPT_H
+// This is just a dummy file to include the documentation
-#include <QtDeclarative/qfxglobal.h>
-#include <QtCore/qobject.h>
-#include <QtDeclarative/qml.h>
+/*!
+ \qmlclass Script QmlScript
+ \brief The Script element adds JavaScript snippets.
+ \ingroup group_utility
-QT_BEGIN_HEADER
+ QmlScript is used to add convenient JavaScript "glue" methods to
+ your Qt Declarative application or component. While you can have any JavaScript code
+ within a QmlScript, it is best to limit yourself to defining functions.
-QT_BEGIN_NAMESPACE
+ \qml
+ Script {
+ function debugMyComponent() {
+ print(text.text);
+ print(otherinterestingitem.property);
+ }
+ }
+ MouseRegion { onClicked: debugMyComponent() }
+ \endqml
-QT_MODULE(Declarative)
+ \note QmlScript executes JavaScript as soon as it is specified.
+ When defining a component, this may be before the execution context is
+ fully specified. As a result some properties or items may not be
+ accessible. By limiting your JavaScript to defining functions that are
+ only executed later once the context is fully defined, this problem is
+ avoided.
+*/
-class QmlScriptPrivate;
-class Q_DECLARATIVE_EXPORT QmlScript : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QmlScript)
+/*!
+ \qmlproperty string Script::script
+ \default
+ JavaScript code to execute.
+*/
- Q_PROPERTY(QString script READ script WRITE setScript)
- Q_PROPERTY(QUrl source READ source WRITE setSource)
- Q_CLASSINFO("DefaultProperty", "script")
+/*!
+ \qmlproperty url Script::source
-public:
- QmlScript(QObject *parent=0);
-
- QString script() const;
- void setScript(const QString &);
-
- QUrl source() const;
- void setSource(const QUrl &);
-
-private Q_SLOTS:
- void replyFinished();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QmlScript)
-
-QT_END_HEADER
-
-#endif
+ Setting this property causes the Script element to read JavaScript code from
+ the file specified.
+*/
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index c126830..1c7bf83 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -289,12 +289,26 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
if (lastTypeDot >= 0)
resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
- QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ bool isScript = resolvableObjectType == QLatin1String("Script");
+
+ if (isScript) {
+ if (_stateStack.isEmpty() || _stateStack.top().property) {
+ QmlError error;
+ error.setDescription(QLatin1String("Invalid use of Script block"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ }
+ }
Object *obj = new Object;
- obj->type = typeRef->id;
- typeRef->refObjects.append(obj);
+ if (!isScript) {
+ QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ obj->type = typeRef->id;
+
+ typeRef->refObjects.append(obj);
+ }
// XXX this doesn't do anything (_scope never builds up)
_scope.append(resolvableObjectType);
@@ -303,7 +317,11 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
obj->location = location;
- if (propertyCount) {
+ if (isScript) {
+
+ _stateStack.top().object->scriptBlockObjects.append(obj);
+
+ } else if (propertyCount) {
Property *prop = currentProperty();
Value *v = new Value;
@@ -385,6 +403,26 @@ Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
_stateStack.pop(); // object
return obj;
+ } else if (objectType == QLatin1String("Script")) {
+
+ AST::UiObjectMemberList *it = initializer->members;
+ for (; it; it = it->next) {
+ AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(it->member);
+ if (! scriptBinding)
+ continue;
+
+ QString propertyName = asString(scriptBinding->qualifiedId);
+ if (propertyName == QLatin1String("source")) {
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
+ AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(stmt->expression);
+ if (string) {
+ // We need to add this as a resource
+ _parser->_refUrls << QUrl(string->value->asString());
+ }
+ }
+ }
+ }
+
}
return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer);
@@ -867,6 +905,11 @@ QList<QmlScriptParser::TypeReference*> QmlScriptParser::referencedTypes() const
return _refTypes;
}
+QList<QUrl> QmlScriptParser::referencedResources() const
+{
+ return _refUrls;
+}
+
Object *QmlScriptParser::tree() const
{
return root;
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
index d489610..b25d6bf 100644
--- a/src/declarative/qml/qmlscriptparser_p.h
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -102,6 +102,7 @@ public:
bool parse(const QByteArray &data, const QUrl &url = QUrl());
QList<TypeReference*> referencedTypes() const;
+ QList<QUrl> referencedResources() const;
QmlParser::Object *tree() const;
QList<Import> imports() const;
@@ -123,6 +124,7 @@ public:
QmlParser::Object *root;
QList<Import> _imports;
QList<TypeReference*> _refTypes;
+ QList<QUrl> _refUrls;
QString _scriptFile;
QmlScriptParserJsASTData *data;
};
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 4ba412b..e4eef64 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -564,6 +564,13 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
}
break;
+ case QmlInstruction::StoreScript:
+ {
+ QObject *target = stack.top();
+ cp->addScript(primitives.at(instr.storeScript.value), target);
+ }
+ break;
+
case QmlInstruction::BeginObject:
{
QObject *target = stack.top();
diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp
deleted file mode 100644
index 5d58f64..0000000
--- a/src/declarative/util/qmlscript.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtDeclarative/qmlengine.h>
-#include <QtDeclarative/qmlcontext.h>
-#include <private/qobject_p.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qdebug.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
-#include <private/qmlnullablevalue_p.h>
-#include <private/qmlengine_p.h>
-#include <private/qmlcontext_p.h>
-#include "qmlscript.h"
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QtDeclarative/qmlinfo.h>
-#include <private/qfxperf_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QmlScriptPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QmlScript);
-
-public:
- QmlScriptPrivate() : reply(0) {}
-
- void addScriptToEngine(const QString &, const QString &source=QString());
-
- QString script;
- QNetworkReply *reply;
- QUrl url;
-};
-
-/*!
- \qmlclass Script QmlScript
- \brief The Script element adds JavaScript snippets.
- \ingroup group_utility
-
- QmlScript is used to add convenient JavaScript "glue" methods to
- your Qt Declarative application or component. While you can have any JavaScript code
- within a QmlScript, it is best to limit yourself to defining functions.
-
- \qml
- Script {
- function debugMyComponent() {
- print(text.text);
- print(otherinterestingitem.property);
- }
- }
- MouseRegion { onClicked: debugMyComponent() }
- \endqml
-
- \note QmlScript executes JavaScript as soon as it is specified.
- When defining a component, this may be before the execution context is
- fully specified. As a result some properties or items may not be
- accessible. By limiting your JavaScript to defining functions that are
- only executed later once the context is fully defined, this problem is
- avoided.
-*/
-
-QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Script,QmlScript)
-QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent)
-{
-}
-
-/*!
- \qmlproperty string Script::script
- \default
- JavaScript code to execute.
-*/
-QString QmlScript::script() const
-{
- Q_D(const QmlScript);
- return d->script;
-}
-
-void QmlScript::setScript(const QString &script)
-{
- Q_D(QmlScript);
- d->script = script;
- d->addScriptToEngine(d->script);
-}
-
-/*!
- \qmlproperty url Script::source
-
- Setting this property causes the Script element to read JavaScript code from
- the file specified.
-*/
-QUrl QmlScript::source() const
-{
- Q_D(const QmlScript);
- return d->url;
-}
-
-void QmlScript::setSource(const QUrl &source)
-{
- Q_D(QmlScript);
- if (d->url == source)
- return;
- d->url = qmlContext(this)->resolvedUrl(source);
-
-#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
- if (d->url.scheme() == QLatin1String("file")) {
- QFile file(d->url.toLocalFile());
- file.open(QIODevice::ReadOnly);
- QByteArray ba = file.readAll();
- d->addScriptToEngine(QString::fromUtf8(ba), file.fileName());
- } else
-#endif
- {
- QNetworkRequest req(d->url);
- d->reply = qmlEngine(this)->networkAccessManager()->get(req);
- QObject::connect(d->reply, SIGNAL(finished()),
- this, SLOT(replyFinished()));
- }
-}
-
-void QmlScript::replyFinished()
-{
- Q_D(QmlScript);
- if (!d->reply->error()) {
- QByteArray ba = d->reply->readAll();
- d->addScriptToEngine(QString::fromUtf8(ba), d->url.toString());
- }
- d->reply->deleteLater();
- d->reply = 0;
-}
-
-void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &source)
-{
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QFxPerfTimer<QFxPerf::AddScript> pt;
-#endif
- Q_Q(QmlScript);
- QmlEngine *engine = qmlEngine(q);
- QmlContext *context = qmlContext(q);
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
-
- QScriptContext *scriptContext = scriptEngine->pushCleanContext();
- scriptContext->pushScope(QmlContextPrivate::get(context)->scriptValue);
-
- QScriptValue scope = scriptEngine->newObject();
- scriptContext->pushScope(scope);
-
- scriptContext->setActivationObject(scope);
-
- QScriptValue val = scriptEngine->evaluate(script, source);
- if (scriptEngine->hasUncaughtException()) {
- if (scriptEngine->uncaughtException().isError()){
- QScriptValue exception = scriptEngine->uncaughtException();
- if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
- qWarning() << exception.property(QLatin1String("fileName")).toString()
- << scriptEngine->uncaughtExceptionLineNumber()
- << exception.toString();
-
- } else {
- qmlInfo(q) << exception.toString();
- }
- }
- }
-
- scriptEngine->popContext();
-
- context->d_func()->scripts.append(scope);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
index 41c9019..ec9967c 100644
--- a/src/declarative/util/util.pri
+++ b/src/declarative/util/util.pri
@@ -4,7 +4,6 @@ SOURCES += \
util/qperformancelog.cpp \
util/qmlconnection.cpp \
util/qmlpackage.cpp \
- util/qmlscript.cpp \
util/qmlanimation.cpp \
util/qmlsystempalette.cpp \
util/qmlspringfollow.cpp \
@@ -29,7 +28,6 @@ HEADERS += \
util/qperformancelog_p.h \
util/qmlconnection.h \
util/qmlpackage.h \
- util/qmlscript.h \
util/qmlanimation.h \
util/qmlanimation_p.h \
util/qmlsystempalette.h \