diff options
Diffstat (limited to 'src/declarative/qml/qmlcompiler.cpp')
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 78 |
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) { |