From e839129b6020795483d1f9ba0b3bcfde9f881bab Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 8 Aug 2018 17:49:59 +0200 Subject: Fix support for default exports in modules Default export declarations require a binding setup step at run-time, so we hook it into the ESModule's statement list to make it visible to the code gen visitor. We also reserve local slot zero for the default export. Change-Id: Ie064caad0422b92cfdadbd7d94db72a05e95c0cc Reviewed-by: Lars Knoll --- src/qml/parser/qqmljs.g | 10 +++++++++- src/qml/parser/qqmljsast.cpp | 25 ++++++++++++++++++------- src/qml/parser/qqmljsast_p.h | 8 ++++---- 3 files changed, 31 insertions(+), 12 deletions(-) (limited to 'src/qml/parser') diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 4c5748f818..faf465e7b9 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -3991,7 +3991,7 @@ ScriptBody: StatementList; Module: ModuleBodyOpt; /. case $rule_number: { - sym(1).Node = new (pool) AST::ESModule(sym(1).ModuleItemList); + sym(1).Node = new (pool) AST::ESModule(sym(1).ModuleItemList, pool); } break; ./ @@ -4233,6 +4233,14 @@ ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead T_FORCE_DECLARA ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead AssignmentExpression_In; -- [lookahead ∉ { function, class }] /. case $rule_number: { + // if lhs is an identifier expression and rhs is an anonymous function expression, we need to assign the name of lhs to the function + if (auto *f = asAnonymousFunctionDefinition(sym(4).Node)) { + f->name = stringRef(2); + } + if (auto *c = asAnonymousClassDefinition(sym(4).Expression)) { + c->name = stringRef(2); + } + auto exportDeclaration = new (pool) AST::ExportDeclaration(/*exportDefault=*/true, sym(4).Node); exportDeclaration->exportToken = loc(1); sym(1).ExportDeclaration = exportDeclaration; diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 6b315c9140..0b1b97a41a 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -1166,10 +1166,17 @@ void ModuleItemList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (ModuleItemList *it = this; it; it = it->next) { - // The statement list is concatenated together between module list - // items and stored in the ESModule, thus not visited from there. - if (it->item && it->item->kind == Kind_StatementList) - continue; + if (it->item) { + // The statement list is concatenated together between module list + // items and stored in the ESModule, thus not visited from there. + if (it->item->kind == Kind_StatementList) + continue; + // Export declaration are also injected into the statement list for + // processing of declarations an variable statements, so don't visit + // it here to avoid double visits. + if (it->item->kind == Kind_ExportDeclaration) + continue; + } accept(it->item, visitor); } } @@ -1177,13 +1184,17 @@ void ModuleItemList::accept0(Visitor *visitor) visitor->endVisit(this); } -StatementList *ModuleItemList::buildStatementList() const +StatementList *ModuleItemList::buildStatementList(MemoryPool *pool) const { StatementList *statements = nullptr; for (const ModuleItemList *item = this; item; item = item->next) { AST::StatementList *listItem = AST::cast(item->item); - if (!listItem) - continue; + if (!listItem) { + if (AST::ExportDeclaration *exportDecl = AST::cast(item->item)) + listItem = new (pool) AST::StatementList(exportDecl); + else + continue; + } if (statements) statements = statements->append(listItem); else diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 0729c99931..9d82e9546b 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -2675,7 +2675,7 @@ public: ExportsList *exportsList = nullptr; }; -class QML_PARSER_EXPORT ExportDeclaration: public Node +class QML_PARSER_EXPORT ExportDeclaration: public Statement { public: QQMLJS_DECLARE_AST_NODE(ExportDeclaration) @@ -2753,7 +2753,7 @@ public: return head; } - StatementList *buildStatementList() const; + StatementList *buildStatementList(MemoryPool *pool) const; void accept0(Visitor *visitor) override; @@ -2773,12 +2773,12 @@ class QML_PARSER_EXPORT ESModule: public Node public: QQMLJS_DECLARE_AST_NODE(Module) - ESModule(ModuleItemList *body) + ESModule(ModuleItemList *body, MemoryPool *pool) : body(body) { kind = K; if (body) - statements = body->buildStatementList(); + statements = body->buildStatementList(pool); } void accept0(Visitor *visitor) override; -- cgit v1.2.3