From 89218c6d0eeec66025c62bb2e063ea067426445a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 18 Mar 2014 18:21:18 +0100 Subject: Clean up script imports Move the .pragma and .import script extraction out of qqmlscript and into qqmlirbuilder, where it can populate a QQmlIR::Document. Changed the script part of the type loader to use that, which also allowed eliminating the m_source member and m_metaData. Change-Id: Icc64d219fff5666679a02e6afda73f7edfca132b Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 263 +++++++++++++++++++++++++++++++++ src/qml/compiler/qqmlirbuilder_p.h | 5 + src/qml/jsruntime/qv4script.cpp | 11 +- src/qml/jsruntime/qv4script_p.h | 2 +- src/qml/qml/qqmlscript.cpp | 294 ------------------------------------- src/qml/qml/qqmlscript_p.h | 10 -- src/qml/qml/qqmltypeloader.cpp | 62 +++++--- src/qml/qml/qqmltypeloader_p.h | 6 +- 8 files changed, 318 insertions(+), 335 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index a6276096b2..85159c7f75 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -197,6 +197,268 @@ QStringList Signal::parameterStringList(const QStringList &stringPool) const return result; } +static void replaceWithSpace(QString &str, int idx, int n) +{ + QChar *data = str.data() + idx; + const QChar space(QLatin1Char(' ')); + for (int ii = 0; ii < n; ++ii) + *data++ = space; +} + +#define CHECK_LINE if (l.tokenStartLine() != startLine) return; +#define CHECK_TOKEN(t) if (token != QQmlJSGrammar:: t) return; + +static const int uriTokens[] = { + QQmlJSGrammar::T_IDENTIFIER, + QQmlJSGrammar::T_PROPERTY, + QQmlJSGrammar::T_SIGNAL, + QQmlJSGrammar::T_READONLY, + QQmlJSGrammar::T_ON, + QQmlJSGrammar::T_BREAK, + QQmlJSGrammar::T_CASE, + QQmlJSGrammar::T_CATCH, + QQmlJSGrammar::T_CONTINUE, + QQmlJSGrammar::T_DEFAULT, + QQmlJSGrammar::T_DELETE, + QQmlJSGrammar::T_DO, + QQmlJSGrammar::T_ELSE, + QQmlJSGrammar::T_FALSE, + QQmlJSGrammar::T_FINALLY, + QQmlJSGrammar::T_FOR, + QQmlJSGrammar::T_FUNCTION, + QQmlJSGrammar::T_IF, + QQmlJSGrammar::T_IN, + QQmlJSGrammar::T_INSTANCEOF, + QQmlJSGrammar::T_NEW, + QQmlJSGrammar::T_NULL, + QQmlJSGrammar::T_RETURN, + QQmlJSGrammar::T_SWITCH, + QQmlJSGrammar::T_THIS, + QQmlJSGrammar::T_THROW, + QQmlJSGrammar::T_TRUE, + QQmlJSGrammar::T_TRY, + QQmlJSGrammar::T_TYPEOF, + QQmlJSGrammar::T_VAR, + QQmlJSGrammar::T_VOID, + QQmlJSGrammar::T_WHILE, + QQmlJSGrammar::T_CONST, + QQmlJSGrammar::T_DEBUGGER, + QQmlJSGrammar::T_RESERVED_WORD, + QQmlJSGrammar::T_WITH, + + QQmlJSGrammar::EOF_SYMBOL +}; +static inline bool isUriToken(int token) +{ + const int *current = uriTokens; + while (*current != QQmlJSGrammar::EOF_SYMBOL) { + if (*current == token) + return true; + ++current; + } + return false; +} + +void Document::extractScriptMetaData(QString &script, QQmlError *error) +{ + Q_ASSERT(error); + + const QString js(QLatin1String(".js")); + const QString library(QLatin1String("library")); + + QQmlJS::MemoryPool *pool = jsParserEngine.pool(); + + QQmlJS::Lexer l(0); + l.setCode(script, 0); + + int token = l.lex(); + + while (true) { + if (token != QQmlJSGrammar::T_DOT) + return; + + int startOffset = l.tokenOffset(); + int startLine = l.tokenStartLine(); + int startColumn = l.tokenStartColumn(); + + QQmlError importError; + importError.setLine(startLine + 1); // 0-based, adjust to be 1-based + + token = l.lex(); + + CHECK_LINE; + + if (token == QQmlJSGrammar::T_IMPORT) { + + // .import as + // .import as + + token = l.lex(); + + CHECK_LINE; + QV4::CompiledData::Import *import = pool->New(); + + if (token == QQmlJSGrammar::T_STRING_LITERAL) { + + QString file = l.tokenText(); + + if (!file.endsWith(js)) { + importError.setDescription(QCoreApplication::translate("QQmlParser","Imported file must be a script")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + bool invalidImport = false; + + token = l.lex(); + + if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) { + invalidImport = true; + } else { + token = l.lex(); + + if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine)) + invalidImport = true; + } + + + if (invalidImport) { + importError.setDescription(QCoreApplication::translate("QQmlParser","File import requires a qualifier")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + int endOffset = l.tokenLength() + l.tokenOffset(); + + QString importId = script.mid(l.tokenOffset(), l.tokenLength()); + + token = l.lex(); + + if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { + importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + replaceWithSpace(script, startOffset, endOffset - startOffset); + + import->type = QV4::CompiledData::Import::ImportScript; + import->uriIndex = registerString(file); + import->qualifierIndex = registerString(importId); + import->location.line = startLine; + import->location.column = startColumn; + imports << import; + } else { + // URI + QString uri; + + while (true) { + if (!isUriToken(token)) { + importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid module URI")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + uri.append(l.tokenText()); + + token = l.lex(); + CHECK_LINE; + if (token != QQmlJSGrammar::T_DOT) + break; + + uri.append(QLatin1Char('.')); + + token = l.lex(); + CHECK_LINE; + } + + if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) { + importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a version")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + int vmaj, vmin; + IRBuilder::extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()), + &vmaj, &vmin); + + bool invalidImport = false; + + token = l.lex(); + + if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) { + invalidImport = true; + } else { + token = l.lex(); + + if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine)) + invalidImport = true; + } + + + if (invalidImport) { + importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a qualifier")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + int endOffset = l.tokenLength() + l.tokenOffset(); + + QString importId = script.mid(l.tokenOffset(), l.tokenLength()); + + token = l.lex(); + + if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { + importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); + importError.setColumn(l.tokenStartColumn()); + *error = importError; + return; + } + + replaceWithSpace(script, startOffset, endOffset - startOffset); + + import->type = QV4::CompiledData::Import::ImportLibrary; + import->uriIndex = registerString(uri); + import->majorVersion = vmaj; + import->minorVersion = vmin; + import->qualifierIndex = registerString(importId); + import->location.line = startLine; + import->location.column = startColumn; + imports << import; + } + } else if (token == QQmlJSGrammar::T_PRAGMA) { + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); + int endOffset = l.tokenLength() + l.tokenOffset(); + + if (pragmaValue == library) { + unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; + replaceWithSpace(script, startOffset, endOffset - startOffset); + } else { + return; + } + + token = l.lex(); + if (l.tokenStartLine() == startLine) + return; + + } else { + return; + } + } + return; +} + IRBuilder::IRBuilder(const QSet &illegalNames) : illegalNames(illegalNames) , _object(0) @@ -1239,6 +1501,7 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(Document &output, int *to jsUnit = 0; QV4::CompiledData::QmlUnit *qmlUnit = reinterpret_cast(data); + qmlUnit->header.flags |= output.unitFlags; qmlUnit->header.flags |= QV4::CompiledData::Unit::IsQml; qmlUnit->offsetToImports = unitSize; qmlUnit->nImports = output.imports.count(); diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index f40799436e..2f398eb008 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -305,6 +305,7 @@ struct Q_QML_EXPORT Document Document(bool debugMode) : jsModule(debugMode) , jsGenerator(&jsModule, sizeof(QV4::CompiledData::QmlUnit)) + , unitFlags(0) {} QString code; QQmlJS::Engine jsParserEngine; @@ -315,10 +316,14 @@ struct Q_QML_EXPORT Document int indexOfRootObject; QList objects; QV4::Compiler::JSUnitGenerator jsGenerator; + quint32 unitFlags; QV4::CompiledData::TypeReferenceMap typeReferences; + int registerString(const QString &str) { return jsGenerator.registerString(str); } QString stringAt(int index) const { return jsGenerator.strings.value(index); } + + void extractScriptMetaData(QString &script, QQmlError *error); }; struct Q_QML_EXPORT IRBuilder : public QQmlJS::AST::Visitor diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index ebcc8bbefa..fc02e04e79 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -307,13 +307,11 @@ Function *Script::function() return vmFunction; } -CompiledData::CompilationUnit *Script::precompile(ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors) +QV4::CompiledData::CompilationUnit *Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors) { using namespace QQmlJS; using namespace QQmlJS::AST; - IR::Module module(engine->debugger != 0); - QQmlJS::Engine ee; QQmlJS::Lexer lexer(&ee); lexer.setCode(source, /*line*/1, /*qml mode*/true); @@ -351,7 +349,7 @@ CompiledData::CompilationUnit *Script::precompile(ExecutionEngine *engine, const } QQmlJS::Codegen cg(/*strict mode*/false); - cg.generateFromProgram(url.toString(), source, program, &module, QQmlJS::Codegen::EvalCode); + cg.generateFromProgram(url.toString(), source, program, module, QQmlJS::Codegen::EvalCode); errors = cg.errors(); if (!errors.isEmpty()) { if (reportedErrors) @@ -359,10 +357,9 @@ CompiledData::CompilationUnit *Script::precompile(ExecutionEngine *engine, const return 0; } - Compiler::JSUnitGenerator jsGenerator(&module); - QScopedPointer isel(engine->iselFactory->create(QQmlEnginePrivate::get(engine), engine->executableAllocator, &module, &jsGenerator)); + QScopedPointer isel(engine->iselFactory->create(QQmlEnginePrivate::get(engine), engine->executableAllocator, module, unitGenerator)); isel->setUseFastLookups(false); - return isel->compile(); + return isel->compile(/*generate unit data*/false); } ReturnedValue Script::qmlBinding() diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 8afdb6126f..ec06565ddc 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -100,7 +100,7 @@ struct Q_QML_EXPORT Script { Function *function(); - static CompiledData::CompilationUnit *precompile(ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors = 0); + static QV4::CompiledData::CompilationUnit *precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors = 0); static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject); }; diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp index cf56d5701d..90d19f2035 100644 --- a/src/qml/qml/qqmlscript.cpp +++ b/src/qml/qml/qqmlscript.cpp @@ -66,19 +66,6 @@ static void replaceWithSpace(QString &str, int idx, int n) *data++ = space; } -static QQmlScript::LocationSpan -locationFromLexer(const QQmlJS::Lexer &lex, int startLine, int startColumn, int startOffset) -{ - QQmlScript::LocationSpan l; - - l.start.line = startLine; l.start.column = startColumn; - l.end.line = lex.tokenEndLine(); l.end.column = lex.tokenEndColumn(); - l.range.offset = startOffset; - l.range.length = lex.tokenOffset() + lex.tokenLength() - startOffset; - - return l; -} - /* Searches for ".pragma " declarations within \a script. Currently supported pragmas are: @@ -133,285 +120,4 @@ QQmlScript::Object::ScriptBlock::Pragmas QQmlScript::Parser::extractPragmas(QStr return rv; } -#define CHECK_LINE if (l.tokenStartLine() != startLine) return rv; -#define CHECK_TOKEN(t) if (token != QQmlJSGrammar:: t) return rv; - -static const int uriTokens[] = { - QQmlJSGrammar::T_IDENTIFIER, - QQmlJSGrammar::T_PROPERTY, - QQmlJSGrammar::T_SIGNAL, - QQmlJSGrammar::T_READONLY, - QQmlJSGrammar::T_ON, - QQmlJSGrammar::T_BREAK, - QQmlJSGrammar::T_CASE, - QQmlJSGrammar::T_CATCH, - QQmlJSGrammar::T_CONTINUE, - QQmlJSGrammar::T_DEFAULT, - QQmlJSGrammar::T_DELETE, - QQmlJSGrammar::T_DO, - QQmlJSGrammar::T_ELSE, - QQmlJSGrammar::T_FALSE, - QQmlJSGrammar::T_FINALLY, - QQmlJSGrammar::T_FOR, - QQmlJSGrammar::T_FUNCTION, - QQmlJSGrammar::T_IF, - QQmlJSGrammar::T_IN, - QQmlJSGrammar::T_INSTANCEOF, - QQmlJSGrammar::T_NEW, - QQmlJSGrammar::T_NULL, - QQmlJSGrammar::T_RETURN, - QQmlJSGrammar::T_SWITCH, - QQmlJSGrammar::T_THIS, - QQmlJSGrammar::T_THROW, - QQmlJSGrammar::T_TRUE, - QQmlJSGrammar::T_TRY, - QQmlJSGrammar::T_TYPEOF, - QQmlJSGrammar::T_VAR, - QQmlJSGrammar::T_VOID, - QQmlJSGrammar::T_WHILE, - QQmlJSGrammar::T_CONST, - QQmlJSGrammar::T_DEBUGGER, - QQmlJSGrammar::T_RESERVED_WORD, - QQmlJSGrammar::T_WITH, - - QQmlJSGrammar::EOF_SYMBOL -}; -static inline bool isUriToken(int token) -{ - const int *current = uriTokens; - while (*current != QQmlJSGrammar::EOF_SYMBOL) { - if (*current == token) - return true; - ++current; - } - return false; -} - -static void extractVersion(QStringRef string, int *maj, int *min) -{ - *maj = -1; *min = -1; - - if (!string.isEmpty()) { - - int dot = string.indexOf(QLatin1Char('.')); - - if (dot < 0) { - *maj = string.toInt(); - *min = 0; - } else { - *maj = string.left(dot).toInt(); - *min = string.mid(dot + 1).toInt(); - } - } -} - -QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QString &script, QQmlError *error) -{ - Q_ASSERT(error); - - JavaScriptMetaData rv; - - QQmlScript::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas; - - const QString js(QLatin1String(".js")); - const QString library(QLatin1String("library")); - - QQmlJS::Lexer l(0); - l.setCode(script, 0); - - int token = l.lex(); - - while (true) { - if (token != QQmlJSGrammar::T_DOT) - return rv; - - int startOffset = l.tokenOffset(); - int startLine = l.tokenStartLine(); - int startColumn = l.tokenStartColumn(); - - QQmlError importError; - importError.setLine(startLine + 1); // 0-based, adjust to be 1-based - - token = l.lex(); - - CHECK_LINE; - - if (token == QQmlJSGrammar::T_IMPORT) { - - // .import as - // .import as - - token = l.lex(); - - CHECK_LINE; - - if (token == QQmlJSGrammar::T_STRING_LITERAL) { - - QString file = l.tokenText(); - - if (!file.endsWith(js)) { - importError.setDescription(QCoreApplication::translate("QQmlParser","Imported file must be a script")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - bool invalidImport = false; - - token = l.lex(); - - if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) { - invalidImport = true; - } else { - token = l.lex(); - - if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine)) - invalidImport = true; - } - - - if (invalidImport) { - importError.setDescription(QCoreApplication::translate("QQmlParser","File import requires a qualifier")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - int endOffset = l.tokenLength() + l.tokenOffset(); - - QString importId = script.mid(l.tokenOffset(), l.tokenLength()); - - QQmlScript::LocationSpan location = - locationFromLexer(l, startLine, startColumn, startOffset); - - token = l.lex(); - - if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { - importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - replaceWithSpace(script, startOffset, endOffset - startOffset); - - Import import; - import.type = Import::Script; - import.uri = file; - import.qualifier = importId; - import.location = location; - - rv.imports << import; - } else { - // URI - QString uri; - - while (true) { - if (!isUriToken(token)) { - importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid module URI")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - uri.append(l.tokenText()); - - token = l.lex(); - CHECK_LINE; - if (token != QQmlJSGrammar::T_DOT) - break; - - uri.append(QLatin1Char('.')); - - token = l.lex(); - CHECK_LINE; - } - - if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) { - importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a version")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - int vmaj, vmin; - extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()), - &vmaj, &vmin); - - bool invalidImport = false; - - token = l.lex(); - - if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) { - invalidImport = true; - } else { - token = l.lex(); - - if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine)) - invalidImport = true; - } - - - if (invalidImport) { - importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a qualifier")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - int endOffset = l.tokenLength() + l.tokenOffset(); - - QString importId = script.mid(l.tokenOffset(), l.tokenLength()); - - QQmlScript::LocationSpan location = - locationFromLexer(l, startLine, startColumn, startOffset); - - token = l.lex(); - - if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { - importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); - importError.setColumn(l.tokenStartColumn()); - *error = importError; - return rv; - } - - replaceWithSpace(script, startOffset, endOffset - startOffset); - - Import import; - import.type = Import::Library; - import.uri = uri; - import.majorVersion = vmaj; - import.minorVersion = vmin; - import.qualifier = importId; - import.location = location; - - rv.imports << import; - } - } else if (token == QQmlJSGrammar::T_PRAGMA) { - token = l.lex(); - - CHECK_TOKEN(T_IDENTIFIER); - CHECK_LINE; - - QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); - int endOffset = l.tokenLength() + l.tokenOffset(); - - if (pragmaValue == library) { - pragmas |= QQmlScript::Object::ScriptBlock::Shared; - replaceWithSpace(script, startOffset, endOffset - startOffset); - } else { - return rv; - } - - token = l.lex(); - if (l.tokenStartLine() == startLine) - return rv; - - } else { - return rv; - } - } - return rv; -} - QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h index e46cef9206..1d59d6117e 100644 --- a/src/qml/qml/qqmlscript_p.h +++ b/src/qml/qml/qqmlscript_p.h @@ -147,17 +147,7 @@ public: class Q_QML_PRIVATE_EXPORT Parser { public: - class JavaScriptMetaData { - public: - JavaScriptMetaData() - : pragmas(QQmlScript::Object::ScriptBlock::None) {} - - QQmlScript::Object::ScriptBlock::Pragmas pragmas; - QList imports; - }; - static QQmlScript::Object::ScriptBlock::Pragmas extractPragmas(QString &); - static JavaScriptMetaData extractMetaData(QString &, QQmlError *error); }; } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index e43b8177f8..efa47db951 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2451,7 +2451,6 @@ void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Locati QQmlScriptData::QQmlScriptData() : importCache(0) - , pragmas(QQmlScript::Object::ScriptBlock::None) , m_loaded(false) , m_precompiledScript(0) , m_program(0) @@ -2497,7 +2496,7 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare QV4::ExecutionEngine *v4 = QV8Engine::getV4(parentCtxt->engine); QV4::Scope scope(v4); - bool shared = pragmas & QQmlScript::Object::ScriptBlock::Shared; + bool shared = m_precompiledScript->data->flags & QV4::CompiledData::Unit::IsSharedLibrary; QQmlContextData *effectiveCtxt = parentCtxt; if (shared) @@ -2590,6 +2589,7 @@ void QQmlScriptData::clear() QQmlScriptBlob::QQmlScriptBlob(const QUrl &url, QQmlTypeLoader *loader) : QQmlTypeLoader::Blob(url, JavaScriptFile, loader), m_scriptData(0) +, m_irUnit(QV8Engine::getV4(loader->engine())->debugger != 0) { } @@ -2608,25 +2608,62 @@ QQmlScriptData *QQmlScriptBlob::scriptData() const void QQmlScriptBlob::dataReceived(const Data &data) { - m_source = QString::fromUtf8(data.data(), data.size()); + QString source = QString::fromUtf8(data.data(), data.size()); m_scriptData = new QQmlScriptData(); m_scriptData->url = finalUrl(); m_scriptData->urlString = finalUrlString(); QQmlError metaDataError; - m_metadata = QQmlScript::Parser::extractMetaData(m_source, &metaDataError); + m_irUnit.extractScriptMetaData(source, &metaDataError); if (metaDataError.isValid()) { metaDataError.setUrl(finalUrl()); setError(metaDataError); return; } + QList errors; + QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); + m_scriptData->m_precompiledScript = QV4::Script::precompile(&m_irUnit.jsModule, &m_irUnit.jsGenerator, v4, m_scriptData->url, source, &errors); + if (m_scriptData->m_precompiledScript) + m_scriptData->m_precompiledScript->ref(); + source.clear(); + if (!errors.isEmpty()) { + setError(errors); + return; + } + + QmlIR::QmlUnitGenerator qmlGenerator; + QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(m_irUnit); + if (m_scriptData->m_precompiledScript) { + Q_ASSERT(!m_scriptData->m_precompiledScript->data); + Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header); + // The js unit owns the data and will free the qml unit. + m_scriptData->m_precompiledScript->data = &qmlUnit->header; + } + m_importCache.setBaseUrl(finalUrl(), finalUrlString()); - QList errors; + for (quint32 i = 0; i < qmlUnit->nImports; ++i) { + const QV4::CompiledData::Import *imp = qmlUnit->importAt(i); + QQmlScript::Import import; + import.uri = qmlUnit->header.stringAt(imp->uriIndex); + import.qualifier = qmlUnit->header.stringAt(imp->qualifierIndex); + import.majorVersion = imp->majorVersion; + import.minorVersion = imp->minorVersion; + import.location.start.line = imp->location.line; + import.location.start.column = imp->location.column; + + switch (imp->type) { + case QV4::CompiledData::Import::ImportFile: import.type = QQmlScript::Import::File; break; + case QV4::CompiledData::Import::ImportLibrary: import.type = QQmlScript::Import::Library; break; + case QV4::CompiledData::Import::ImportScript: import.type = QQmlScript::Import::Script; break; + default: break; + } + m_imports << import; + } - foreach (const QQmlScript::Import &import, m_metadata.imports) { + foreach (const QQmlScript::Import &import, m_imports) { if (!addImport(import, &errors)) { Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); @@ -2680,19 +2717,6 @@ void QQmlScriptBlob::done() } m_importCache.populateCache(m_scriptData->importCache); - - m_scriptData->pragmas = m_metadata.pragmas; - - QList errors; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); - m_scriptData->m_precompiledScript = QV4::Script::precompile(v4, m_scriptData->url, m_source, &errors); - if (m_scriptData->m_precompiledScript) - m_scriptData->m_precompiledScript->ref(); - m_source.clear(); - if (!errors.isEmpty()) { - setError(errors); - return; - } } void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &nameSpace) diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index fa606bf1a9..24daa35a6f 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -498,7 +498,6 @@ public: QString urlString; QQmlTypeNameCache *importCache; QList scripts; - QQmlScript::Object::ScriptBlock::Pragmas pragmas; QV4::PersistentValue scriptValueForContext(QQmlContextData *parentCtxt); @@ -546,11 +545,10 @@ protected: private: virtual void scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &nameSpace); - QString m_source; - QQmlScript::Parser::JavaScriptMetaData m_metadata; - QList m_scripts; QQmlScriptData *m_scriptData; + QList m_imports; // ### temporary until addImport is changed + QmlIR::Document m_irUnit; }; class Q_AUTOTEST_EXPORT QQmlQmldirData : public QQmlTypeLoader::Blob -- cgit v1.2.3