aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-08-15 14:53:28 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-08-15 18:56:05 +0000
commitd4ca7f779d85b01a7e650abefeb8cd6502eff8e2 (patch)
treecb9e961e795cbafb6bbfeb1d17e4be604cd7411d /src
parent263b1f5f2acdc7e652e7c3aa332e2a53bd136295 (diff)
Fix initialization of default exported functions and generators
When registering a default export, make sure that the local name points either to an entry that we've entered into the environment or the synthetic entry we create. Change-Id: I37e160dc1e3231214bb68f72d6bb0746d7aee3b3 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4codegen.cpp5
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp9
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h2
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp28
4 files changed, 31 insertions, 13 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 185f1812f7..0d004bfe80 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -816,7 +816,10 @@ bool Codegen::visit(ExportDeclaration *ast)
}
exportedValue.loadInAccumulator();
- Reference defaultExportSlot = Reference::fromScopedLocal(this, 0, /*scope*/0);
+
+ const int defaultExportIndex = _context->locals.indexOf(_context->localNameForDefaultExport);
+ Q_ASSERT(defaultExportIndex != -1);
+ Reference defaultExportSlot = Reference::fromScopedLocal(this, defaultExportIndex, /*scope*/0);
defaultExportSlot.storeConsumeAccumulator();
return false;
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index c0fbb72c59..09be19e427 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -295,9 +295,12 @@ void Context::setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
Q_ASSERT(nRegisters == 0);
registerOffset = bytecodeGenerator->currentRegister();
- if (contextType == ContextType::ESModule && hasDefaultExport) {
- // allocate a local slot for the default export
- locals.append(QStringLiteral("*default*"));
+ if (contextType == ContextType::ESModule && !localNameForDefaultExport.isEmpty()) {
+ if (!members.contains(localNameForDefaultExport)) {
+ // allocate a local slot for the default export, to be used in
+ // CodeGen::visit(ExportDeclaration*).
+ locals.append(localNameForDefaultExport);
+ }
}
switch (contextType) {
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 0f7f4c835d..bd0bd90a59 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -180,7 +180,7 @@ struct Context {
QStringList moduleRequests;
QVector<ImportEntry> importEntries;
QVector<ExportEntry> exportEntries;
- bool hasDefaultExport = false;
+ QString localNameForDefaultExport;
QVector<Context *> nestedContexts;
ControlFlow *controlFlow = nullptr;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index a3bdce05d4..7a8622dc02 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -170,6 +170,8 @@ bool ScanFunctions::visit(ExportDeclaration *declaration)
_context->moduleRequests << module;
}
+ QString localNameForDefaultExport = QStringLiteral("*default*");
+
if (declaration->exportAll) {
Compiler::ExportEntry entry;
entry.moduleRequest = declaration->fromClause->moduleSpecifier.toString();
@@ -209,25 +211,35 @@ bool ScanFunctions::visit(ExportDeclaration *declaration)
entry.localName = name;
entry.exportName = name;
_context->exportEntries << entry;
+ if (declaration->exportDefault)
+ localNameForDefaultExport = entry.localName;
}
} else if (auto *fdef = declaration->variableStatementOrDeclaration->asFunctionDefinition()) {
- QString name = fdef->name.toString();
- // Our parser gives `export default (function() {}` the name "default", which
- // we don't want to export here.
- if (!name.isEmpty() && name != QStringLiteral("default")) {
+ QString functionName;
+
+ // Only function definitions for which we enter their name into the local environment
+ // can result in exports. Nested expressions such as (function foo() {}) are not accessible
+ // as locals and can only be exported as default exports (further down).
+ auto ast = declaration->variableStatementOrDeclaration;
+ if (AST::cast<AST::ExpressionStatement*>(ast) || AST::cast<AST::FunctionDeclaration*>(ast))
+ functionName = fdef->name.toString();
+
+ if (!functionName.isEmpty()) {
Compiler::ExportEntry entry;
- entry.localName = name;
- entry.exportName = name;
+ entry.localName = functionName;
+ entry.exportName = functionName;
_context->exportEntries << entry;
+ if (declaration->exportDefault)
+ localNameForDefaultExport = entry.localName;
}
}
if (declaration->exportDefault) {
Compiler::ExportEntry entry;
- entry.localName = QStringLiteral("*default*");
+ entry.localName = localNameForDefaultExport;
+ _context->localNameForDefaultExport = localNameForDefaultExport;
entry.exportName = QStringLiteral("default");
_context->exportEntries << entry;
- _context->hasDefaultExport = true;
}
return true; // scan through potential assignment expression code, etc.