summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2010-03-22 05:34:41 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2010-03-22 05:36:35 (GMT)
commit888d29c9c138ca3d698985f090ceb3db912ade0f (patch)
treeaa991f683dd8e7ea4b05d029dd75b32321fde3c0 /src/declarative/qml
parent42de973ff156383beed62a6b1bce70b56b360078 (diff)
downloadQt-888d29c9c138ca3d698985f090ceb3db912ade0f.zip
Qt-888d29c9c138ca3d698985f090ceb3db912ade0f.tar.gz
Qt-888d29c9c138ca3d698985f090ceb3db912ade0f.tar.bz2
Deprecate inline Script {} blocks
Inline blocks/includes have been replaced with an import syntax: import "foo.js" as Foo this gives better separation between QML and code. Imported script blocks also have a mandatory qualifier, which leads to better optimization potential.
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp47
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp5
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h2
-rw-r--r--src/declarative/qml/qdeclarativecompositetypedata_p.h9
-rw-r--r--src/declarative/qml/qdeclarativecompositetypemanager.cpp29
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp69
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h2
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp16
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp6
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h8
-rw-r--r--src/declarative/qml/qdeclarativeinstruction.cpp3
-rw-r--r--src/declarative/qml/qdeclarativeinstruction_p.h1
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h9
-rw-r--r--src/declarative/qml/qdeclarativescriptparser.cpp130
-rw-r--r--src/declarative/qml/qdeclarativescriptparser_p.h4
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache.cpp15
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h4
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp13
18 files changed, 349 insertions, 23 deletions
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 103e918..28c2210 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -542,8 +542,8 @@ void QDeclarativeCompiler::reset(QDeclarativeCompiledData *data)
on a successful compiler.
*/
bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
- QDeclarativeCompositeTypeData *unit,
- QDeclarativeCompiledData *out)
+ QDeclarativeCompositeTypeData *unit,
+ QDeclarativeCompiledData *out)
{
exceptions.clear();
@@ -633,6 +633,37 @@ void QDeclarativeCompiler::compileTree(Object *tree)
init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
output->bytecode << init;
+ // Build global import scripts
+ QHash<QString, Object::ScriptBlock> importedScripts;
+ QStringList importedScriptIndexes;
+
+ for (int ii = 0; ii < unit->scripts.count(); ++ii) {
+ QString scriptCode = QString::fromUtf8(unit->scripts.at(ii).resource->data);
+ Object::ScriptBlock::Pragmas pragmas = QDeclarativeScriptParser::extractPragmas(scriptCode);
+
+ if (!scriptCode.isEmpty()) {
+ Object::ScriptBlock &scriptBlock = importedScripts[unit->scripts.at(ii).qualifier];
+
+ scriptBlock.codes.append(scriptCode);
+ scriptBlock.lineNumbers.append(1);
+ scriptBlock.files.append(unit->scripts.at(ii).resource->url);
+ scriptBlock.pragmas.append(pragmas);
+ }
+ }
+
+ for (QHash<QString, Object::ScriptBlock>::Iterator iter = importedScripts.begin();
+ iter != importedScripts.end(); ++iter) {
+
+ importedScriptIndexes.append(iter.key());
+
+ QDeclarativeInstruction import;
+ import.type = QDeclarativeInstruction::StoreImportedScript;
+ import.line = 0;
+ import.storeScript.value = output->scripts.count();
+ output->scripts << *iter;
+ output->bytecode << import;
+ }
+
genObject(tree);
QDeclarativeInstruction def;
@@ -641,7 +672,13 @@ void QDeclarativeCompiler::compileTree(Object *tree)
output->bytecode << def;
output->imports = unit->imports;
- output->importCache = output->imports.cache(engine);
+
+ output->importCache = new QDeclarativeTypeNameCache(engine);
+
+ for (int ii = 0; ii < importedScriptIndexes.count(); ++ii)
+ output->importCache->add(importedScriptIndexes.at(ii), ii);
+
+ output->imports.cache(output->importCache, engine);
Q_ASSERT(tree->metatype);
@@ -1153,6 +1190,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclarativeParser::Object *script)
{
+ qWarning().nospace() << qPrintable(output->url.toString()) << ":" << obj->location.start.line << ":" << obj->location.start.column << ": Script blocks have been deprecated. Support will be removed entirely shortly.";
+
Object::ScriptBlock scriptBlock;
if (script->properties.count() == 1 &&
@@ -1184,6 +1223,7 @@ bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclara
scriptBlock.codes.append(scriptCode);
scriptBlock.files.append(sourceUrl);
scriptBlock.lineNumbers.append(lineNumber);
+ scriptBlock.pragmas.append(Object::ScriptBlock::None);
}
}
@@ -1226,6 +1266,7 @@ bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclara
scriptBlock.codes.append(scriptCode);
scriptBlock.files.append(sourceUrl);
scriptBlock.lineNumbers.append(lineNumber);
+ scriptBlock.pragmas.append(Object::ScriptBlock::None);
}
}
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index ec595e3..ec23458 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -612,6 +612,11 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, cons
ctxt->isInternal = true;
ctxt->url = cc->url;
ctxt->imports = cc->importCache;
+
+ // Nested global imports
+ if (creationContext && start != -1)
+ ctxt->importedScripts = creationContext->importedScripts;
+
cc->importCache->addref();
ctxt->setParent(context);
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index 649fce5..b44aeef 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -116,7 +116,7 @@ public:
static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state);
QDeclarativeEngine *engine;
- QDeclarativeContextData *creationContext;
+ QDeclarativeGuardedContextData creationContext;
void clear();
diff --git a/src/declarative/qml/qdeclarativecompositetypedata_p.h b/src/declarative/qml/qdeclarativecompositetypedata_p.h
index fb26af9..04d0c63 100644
--- a/src/declarative/qml/qdeclarativecompositetypedata_p.h
+++ b/src/declarative/qml/qdeclarativecompositetypedata_p.h
@@ -103,7 +103,16 @@ public:
QDeclarativeCompositeTypeData *unit;
};
+ struct ScriptReference
+ {
+ ScriptReference();
+
+ QString qualifier;
+ QDeclarativeCompositeTypeResource *resource;
+ };
+
QList<TypeReference> types;
+ QList<ScriptReference> scripts;
QList<QDeclarativeCompositeTypeResource *> resources;
// Add or remove p as a waiter. When the QDeclarativeCompositeTypeData becomes
diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp
index ebf1f40..c883805 100644
--- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp
+++ b/src/declarative/qml/qdeclarativecompositetypemanager.cpp
@@ -126,6 +126,27 @@ QDeclarativeCompositeTypeData::toCompiledComponent(QDeclarativeEngine *engine)
{
if (status == Complete && !compiledComponent) {
+ // Build script imports
+ foreach (const QDeclarativeScriptParser::Import &import, data.imports()) {
+ if (import.type == QDeclarativeScriptParser::Import::Script) {
+ QString url = imports.baseUrl().resolved(QUrl(import.uri)).toString();
+
+ ScriptReference ref;
+ ref.qualifier = import.qualifier;
+
+ for (int ii = 0; ii < resources.count(); ++ii) {
+ if (resources.at(ii)->url == url) {
+ ref.resource = resources.at(ii);
+ break;
+ }
+ }
+
+ Q_ASSERT(ref.resource);
+
+ scripts << ref;
+ }
+ }
+
compiledComponent = new QDeclarativeCompiledData(engine);
compiledComponent->url = imports.baseUrl();
compiledComponent->name = compiledComponent->url.toString();
@@ -153,6 +174,11 @@ QDeclarativeCompositeTypeData::TypeReference::TypeReference()
{
}
+QDeclarativeCompositeTypeData::ScriptReference::ScriptReference()
+: resource(0)
+{
+}
+
QDeclarativeCompositeTypeManager::QDeclarativeCompositeTypeManager(QDeclarativeEngine *e)
: engine(e), redirectCount(0)
{
@@ -514,6 +540,9 @@ int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData
foreach (QDeclarativeScriptParser::Import imp, unit->data.imports()) {
QDeclarativeDirComponents qmldircomponentsnetwork;
+ if (imp.type == QDeclarativeScriptParser::Import::Script)
+ continue;
+
if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) {
QString importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))).toString();
for (int ii = 0; ii < unit->resources.count(); ++ii) {
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index 782c0d7..85896c4 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -606,6 +606,75 @@ void QDeclarativeContextData::addObject(QObject *o)
contextObjects = data;
}
+void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script)
+{
+ if (!engine)
+ return;
+
+ Q_ASSERT(script.codes.count() == 1);
+
+ QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+
+ const QString &code = script.codes.at(0);
+ const QString &url = script.files.at(0);
+ const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas.at(0);
+
+ Q_ASSERT(!url.isEmpty());
+
+ if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) {
+
+ QHash<QString, QScriptValue>::Iterator iter = enginePriv->m_sharedScriptImports.find(url);
+ if (iter == enginePriv->m_sharedScriptImports.end()) {
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+
+ scriptContext->pushScope(enginePriv->globalClass->globalObject());
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+ scriptContext->pushScope(scope);
+
+ scriptEngine->evaluate(code, url, 1);
+
+ if (scriptEngine->hasUncaughtException()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
+ qWarning().nospace() << qPrintable(error.toString());
+ }
+
+ scriptEngine->popContext();
+
+ iter = enginePriv->m_sharedScriptImports.insert(url, scope);
+ }
+
+ importedScripts.append(*iter);
+
+ } else {
+
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+
+ scriptContext->pushScope(enginePriv->contextClass->newContext(this, 0));
+ scriptContext->pushScope(enginePriv->globalClass->globalObject());
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+ scriptContext->pushScope(scope);
+
+ scriptEngine->evaluate(code, url, 1);
+
+ if (scriptEngine->hasUncaughtException()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
+ qWarning().nospace() << qPrintable(error.toString());
+ }
+
+ scriptEngine->popContext();
+
+ importedScripts.append(scope);
+
+ }
+}
+
void QDeclarativeContextData::addScript(const QDeclarativeParser::Object::ScriptBlock &script,
QObject *scopeObject)
{
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index d74aa33..ecf3ec8 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -141,6 +141,8 @@ public:
// Any script blocks that exist on this context
QList<QScriptValue> scripts;
+ QList<QScriptValue> importedScripts;
+ void addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script);
void addScript(const QDeclarativeParser::Object::ScriptBlock &script, QObject *scopeObject);
// Context base url
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
index 847d632..2559224 100644
--- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
@@ -240,10 +240,19 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
} else if (lastData) {
- if (lastData->type)
+ if (lastData->type) {
return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->type));
- else
- return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->typeNamespace));
+ } else if (lastData->typeNamespace) {
+ return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject,
+ lastData->typeNamespace));
+ } else {
+ int index = lastData->importedScriptIndex;
+ if (index < bindContext->importedScripts.count()) {
+ return Value(scriptEngine, bindContext->importedScripts.at(index));
+ } else {
+ return Value();
+ }
+ }
} else if (lastPropertyIndex != -1) {
@@ -266,7 +275,6 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext->asQDeclarativeContext(), -1, lastPropertyIndex + cp->notifyIndex);
}
-
return Value(scriptEngine, rv);
} else {
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 5820961..0bedbeb 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -1695,12 +1695,10 @@ static QDeclarativeTypeNameCache *cacheForNamespace(QDeclarativeEngine *engine,
return cache;
}
-QDeclarativeTypeNameCache *QDeclarativeEnginePrivate::Imports::cache(QDeclarativeEngine *engine) const
+void QDeclarativeEnginePrivate::Imports::cache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const
{
const QDeclarativeEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
- QDeclarativeTypeNameCache *cache = new QDeclarativeTypeNameCache(engine);
-
for (QHash<QString,QDeclarativeEnginePrivate::ImportedNamespace* >::ConstIterator iter = d->set.begin();
iter != d->set.end(); ++iter) {
@@ -1716,8 +1714,6 @@ QDeclarativeTypeNameCache *QDeclarativeEnginePrivate::Imports::cache(QDeclarativ
}
cacheForNamespace(engine, set, cache);
-
- return cache;
}
/*
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index 4ab619e..6532d30 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -264,7 +264,7 @@ public:
void setBaseUrl(const QUrl& url);
QUrl baseUrl() const;
- QDeclarativeTypeNameCache *cache(QDeclarativeEngine *) const;
+ void cache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *) const;
private:
friend class QDeclarativeEnginePrivate;
@@ -281,7 +281,9 @@ public:
QString resolvePlugin(const QDir &dir, const QString &baseName);
- bool addToImport(Imports*, const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const;
+ bool addToImport(Imports*, const QDeclarativeDirComponents &qmldircomponentsnetwork,
+ const QString& uri, const QString& prefix, int vmaj, int vmin,
+ QDeclarativeScriptParser::Import::Type importType) const;
bool resolveType(const Imports&, const QByteArray& type,
QDeclarativeType** type_return, QUrl* url_return,
int *version_major, int *version_minor,
@@ -303,6 +305,8 @@ public:
QHash<int, int> m_qmlLists;
QHash<int, QDeclarativeCompiledData *> m_compositeTypes;
+ QHash<QString, QScriptValue> m_sharedScriptImports;
+
QScriptValue scriptValueFromVariant(const QVariant &);
QVariant scriptValueToVariant(const QScriptValue &);
diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp
index a23ff75..9083ab3 100644
--- a/src/declarative/qml/qdeclarativeinstruction.cpp
+++ b/src/declarative/qml/qdeclarativeinstruction.cpp
@@ -144,6 +144,9 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx)
case QDeclarativeInstruction::StoreScript:
qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SCRIPT\t\t" << instr->storeScript.value;
break;
+ case QDeclarativeInstruction::StoreImportedScript:
+ qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value;
+ break;
case QDeclarativeInstruction::StoreScriptString:
qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope;
break;
diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h
index ec32b35..877179d 100644
--- a/src/declarative/qml/qdeclarativeinstruction_p.h
+++ b/src/declarative/qml/qdeclarativeinstruction_p.h
@@ -119,6 +119,7 @@ public:
StoreSignal, /* storeSignal */
StoreScript, /* storeScript */
+ StoreImportedScript, /* storeScript */
StoreScriptString, /* storeScriptString */
//
diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h
index 9dfb86b..476b027 100644
--- a/src/declarative/qml/qdeclarativeparser_p.h
+++ b/src/declarative/qml/qdeclarativeparser_p.h
@@ -179,9 +179,16 @@ namespace QDeclarativeParser
// Script blocks that were nested under this object
struct ScriptBlock {
+ enum Pragma {
+ None = 0x00000000,
+ Shared = 0x00000001
+ };
+ Q_DECLARE_FLAGS(Pragmas, Pragma)
+
QStringList codes;
QStringList files;
QList<int> lineNumbers;
+ QList<Pragmas> pragmas;
};
QList<ScriptBlock> scripts;
@@ -360,6 +367,8 @@ namespace QDeclarativeParser
};
}
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeParser::Object::ScriptBlock::Pragmas);
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QDeclarativeParser::Variant)
diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp
index 2578ff4..49bd3b7 100644
--- a/src/declarative/qml/qdeclarativescriptparser.cpp
+++ b/src/declarative/qml/qdeclarativescriptparser.cpp
@@ -441,8 +441,14 @@ bool ProcessAST::visit(AST::UiImport *node)
QDeclarativeScriptParser::Import import;
if (node->fileName) {
- import.type = QDeclarativeScriptParser::Import::File;
uri = node->fileName->asString();
+
+ if (uri.endsWith(QLatin1String(".js"))) {
+ import.type = QDeclarativeScriptParser::Import::Script;
+ _parser->_refUrls << QUrl(uri);
+ } else {
+ import.type = QDeclarativeScriptParser::Import::File;
+ }
} else {
import.type = QDeclarativeScriptParser::Import::Library;
uri = asString(node->importUri);
@@ -451,6 +457,7 @@ bool ProcessAST::visit(AST::UiImport *node)
AST::SourceLocation startLoc = node->importToken;
AST::SourceLocation endLoc = node->semicolonToken;
+ // Qualifier
if (node->importId) {
import.qualifier = node->importId->asString();
if (!import.qualifier.at(0).isUpper()) {
@@ -461,17 +468,43 @@ bool ProcessAST::visit(AST::UiImport *node)
_parser->_errors << error;
return false;
}
+
+ // Check for script qualifier clashes
+ bool isScript = import.type == QDeclarativeScriptParser::Import::Script;
+ for (int ii = 0; ii < _parser->_imports.count(); ++ii) {
+ const QDeclarativeScriptParser::Import &other = _parser->_imports.at(ii);
+ bool otherIsScript = other.type == QDeclarativeScriptParser::Import::Script;
+
+ if ((isScript || otherIsScript) && import.qualifier == other.qualifier) {
+ QDeclarativeError error;
+ error.setDescription(QCoreApplication::translate("QDeclarativeParser","Script import qualifiers must be unique."));
+ error.setLine(node->importIdToken.startLine);
+ error.setColumn(node->importIdToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+ }
+
+ } else if (import.type == QDeclarativeScriptParser::Import::Script) {
+ QDeclarativeError error;
+ error.setDescription(QCoreApplication::translate("QDeclarativeParser","Script import requires a qualifier"));
+ error.setLine(node->importIdToken.startLine);
+ error.setColumn(node->importIdToken.startColumn);
+ _parser->_errors << error;
+ return false;
}
- if (node->versionToken.isValid())
+
+ if (node->versionToken.isValid()) {
import.version = textAt(node->versionToken);
- else if (import.type == QDeclarativeScriptParser::Import::Library) {
+ } else if (import.type == QDeclarativeScriptParser::Import::Library) {
QDeclarativeError error;
error.setDescription(QCoreApplication::translate("QDeclarativeParser","Library import requires a version"));
error.setLine(node->importIdToken.startLine);
error.setColumn(node->importIdToken.startColumn);
_parser->_errors << error;
return false;
- }
+ }
+
import.location = location(startLoc, endLoc);
import.uri = uri;
@@ -934,6 +967,95 @@ QList<QDeclarativeError> QDeclarativeScriptParser::errors() const
return _errors;
}
+/*
+Searches for ".pragma <value>" declarations within \a script. Currently supported pragmas
+are:
+ library
+*/
+QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extractPragmas(QString &script)
+{
+ QDeclarativeParser::Object::ScriptBlock::Pragmas rv = QDeclarativeParser::Object::ScriptBlock::None;
+
+ const QChar forwardSlash(QLatin1Char('/'));
+ const QChar star(QLatin1Char('*'));
+ const QChar newline(QLatin1Char('\n'));
+ const QChar dot(QLatin1Char('.'));
+ const QChar semicolon(QLatin1Char(';'));
+ const QChar space(QLatin1Char(' '));
+ const QString pragma(QLatin1String(".pragma "));
+
+ const QChar *pragmaData = pragma.constData();
+
+ const QChar *data = script.constData();
+ const int length = script.count();
+ for (int ii = 0; ii < length; ++ii) {
+ const QChar &c = data[ii];
+
+ if (c.isSpace())
+ continue;
+
+ if (c == forwardSlash) {
+ ++ii;
+ if (ii >= length)
+ return rv;
+
+ const QChar &c = data[ii];
+ if (c == forwardSlash) {
+ // Find next newline
+ while (ii < length && data[++ii] != newline) {};
+ } else if (c == star) {
+ // Find next star
+ while (true) {
+ while (ii < length && data[++ii] != star) {};
+ if (ii + 1 >= length)
+ return rv;
+
+ if (data[ii + 1] == forwardSlash) {
+ ++ii;
+ break;
+ }
+ }
+ } else {
+ return rv;
+ }
+ } else if (c == dot) {
+ // Could be a pragma!
+ if (ii + pragma.length() >= length ||
+ 0 != ::memcmp(data + ii, pragmaData, sizeof(QChar) * pragma.length()))
+ return rv;
+
+ int pragmaStatementIdx = ii;
+
+ ii += pragma.length();
+
+ while (ii < length && data[ii].isSpace()) { ++ii; }
+
+ int startIdx = ii;
+
+ while (ii < length && data[ii].isLetter()) { ++ii; }
+
+ int endIdx = ii;
+
+ if (ii != length && data[ii] != forwardSlash && !data[ii].isSpace() && data[ii] != semicolon)
+ return rv;
+
+ QString p(data + startIdx, endIdx - startIdx);
+
+ if (p == QLatin1String("library"))
+ rv |= QDeclarativeParser::Object::ScriptBlock::Shared;
+ else
+ return rv;
+
+ for (int jj = pragmaStatementIdx; jj < endIdx; ++jj) script[jj] = space;
+
+ } else {
+ return rv;
+ }
+ }
+
+ return rv;
+}
+
void QDeclarativeScriptParser::clear()
{
if (root) {
diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h
index b8f77d1..68f1840 100644
--- a/src/declarative/qml/qdeclarativescriptparser_p.h
+++ b/src/declarative/qml/qdeclarativescriptparser_p.h
@@ -75,7 +75,7 @@ public:
public:
Import() : type(Library) {}
- enum Type { Library, File };
+ enum Type { Library, File, Script };
Type type;
QString uri;
@@ -112,6 +112,8 @@ public:
QList<QDeclarativeError> errors() const;
+ static QDeclarativeParser::Object::ScriptBlock::Pragmas extractPragmas(QString &);
+
// ### private:
TypeReference *findOrCreateType(const QString &name);
void setTree(QDeclarativeParser::Object *tree);
diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp
index f94f944..c4a8707 100644
--- a/src/declarative/qml/qdeclarativetypenamecache.cpp
+++ b/src/declarative/qml/qdeclarativetypenamecache.cpp
@@ -63,6 +63,21 @@ void QDeclarativeTypeNameCache::clear()
engine = 0;
}
+void QDeclarativeTypeNameCache::add(const QString &name, int importedScriptIndex)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->importedScriptIndex = importedScriptIndex;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+}
+
void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type)
{
if (stringCache.contains(name))
diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h
index eee5b77..3e24f5c 100644
--- a/src/declarative/qml/qdeclarativetypenamecache_p.h
+++ b/src/declarative/qml/qdeclarativetypenamecache_p.h
@@ -73,8 +73,10 @@ public:
inline ~Data();
QDeclarativeType *type;
QDeclarativeTypeNameCache *typeNamespace;
+ int importedScriptIndex;
};
+ void add(const QString &, int);
void add(const QString &, QDeclarativeType *);
void add(const QString &, QDeclarativeTypeNameCache *);
@@ -97,7 +99,7 @@ private:
};
QDeclarativeTypeNameCache::Data::Data()
-: type(0), typeNamespace(0)
+: type(0), typeNamespace(0), importedScriptIndex(-1)
{
}
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index b3144a8..2338bc3 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -259,8 +259,9 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
case QDeclarativeInstruction::CreateComponent:
{
- QObject *qcomp = new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count,
- stack.isEmpty() ? 0 : stack.top());
+ QDeclarativeComponent *qcomp =
+ new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count,
+ stack.isEmpty() ? 0 : stack.top());
QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(qcomp, true);
Q_ASSERT(ddata);
@@ -275,6 +276,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
ddata->lineNumber = instr.line;
ddata->columnNumber = instr.create.column;
+ QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
+
stack.push(qcomp);
ii += instr.createComponent.count;
}
@@ -581,6 +584,12 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
}
break;
+ case QDeclarativeInstruction::StoreImportedScript:
+ {
+ ctxt->addImportedScript(scripts.at(instr.storeScript.value));
+ }
+ break;
+
case QDeclarativeInstruction::StoreScriptString:
{
QObject *target = stack.top();