aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-18 18:21:18 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-19 08:32:33 +0100
commit89218c6d0eeec66025c62bb2e063ea067426445a (patch)
tree1a56c5da6120b9b9176e4d519440604c5336cbdb /src
parentc33a79f0a0de8f01b3a43335778e246e1f02598e (diff)
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 <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp263
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h5
-rw-r--r--src/qml/jsruntime/qv4script.cpp11
-rw-r--r--src/qml/jsruntime/qv4script_p.h2
-rw-r--r--src/qml/qml/qqmlscript.cpp294
-rw-r--r--src/qml/qml/qqmlscript_p.h10
-rw-r--r--src/qml/qml/qqmltypeloader.cpp62
-rw-r--r--src/qml/qml/qqmltypeloader_p.h6
8 files changed, 318 insertions, 335 deletions
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 <URI> <Version> as <Identifier>
+ // .import <file.js> as <Identifier>
+
+ token = l.lex();
+
+ CHECK_LINE;
+ QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>();
+
+ 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<QString> &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<QV4::CompiledData::QmlUnit *>(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<Object*> 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<QQmlError> *reportedErrors)
+QV4::CompiledData::CompilationUnit *Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *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<EvalInstructionSelection> isel(engine->iselFactory->create(QQmlEnginePrivate::get(engine), engine->executableAllocator, &module, &jsGenerator));
+ QScopedPointer<EvalInstructionSelection> 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<QQmlError> *reportedErrors = 0);
+ static QV4::CompiledData::CompilationUnit *precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *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 <value>" 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 <URI> <Version> as <Identifier>
- // .import <file.js> as <Identifier>
-
- 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<Import> 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<QQmlError> 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<QQmlError> 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<QQmlError> 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<QQmlScriptBlob *> 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<ScriptReference> m_scripts;
QQmlScriptData *m_scriptData;
+ QList<QQmlScript::Import> m_imports; // ### temporary until addImport is changed
+ QmlIR::Document m_irUnit;
};
class Q_AUTOTEST_EXPORT QQmlQmldirData : public QQmlTypeLoader::Blob