summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qmlcompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qmlcompiler.cpp')
-rw-r--r--src/declarative/qml/qmlcompiler.cpp78
1 files changed, 76 insertions, 2 deletions
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)
{