Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
[Merge chakra-core/ChakraCore@f2ff94fb6e] [1.6>1.7] [MERGE #3523 @suwc]…
Browse files Browse the repository at this point in the history
… Fix issue#3245: Semicolon should not be required after certain module export forms

Merge pull request #3523 from suwc:build/suwc/Issue3245

Following export declaration forms do not require termination with semicolon (15.2.3):

exportVariableStatement[~Yield, ~Await]
exportDeclaration[~Yield, ~Await]
exportdefaultHoistableDeclaration[~Yield, ~Await, +Default]
exportdefaultClassDeclaration[~Yield, ~Await, +Default]
  • Loading branch information
chakrabot authored and MSLaguana committed Sep 25, 2017
1 parent 245fad4 commit b076970
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
32 changes: 29 additions & 3 deletions deps/chakrashim/core/lib/Parser/Parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2709,7 +2709,7 @@ ParseNodePtr Parser::ParseDefaultExportClause()
}

template<bool buildAST>
ParseNodePtr Parser::ParseExportDeclaration()
ParseNodePtr Parser::ParseExportDeclaration(bool *needTerminator)
{
Assert(m_scriptContext->GetConfig()->IsES6ModuleEnabled());
Assert(m_token.tk == tkEXPORT);
Expand All @@ -2723,6 +2723,11 @@ ParseNodePtr Parser::ParseExportDeclaration()
IdentPtr moduleIdentifier = nullptr;
tokens declarationType;

if (needTerminator != nullptr)
{
*needTerminator = false;
}

// We just parsed an export token. Next valid tokens are *, {, var, let, const, async, function, class, default.
m_pscan->Scan();

Expand All @@ -2744,6 +2749,11 @@ ParseNodePtr Parser::ParseExportDeclaration()
AddModuleImportOrExportEntry(EnsureModuleStarExportEntryList(), importName, nullptr, nullptr, moduleIdentifier);
}

if (needTerminator != nullptr)
{
*needTerminator = true;
}

break;

case tkLCurly:
Expand Down Expand Up @@ -2784,6 +2794,12 @@ ParseNodePtr Parser::ParseExportDeclaration()
exportEntryList.Clear();
}
}

if (needTerminator != nullptr)
{
*needTerminator = true;
}

break;

case tkID:
Expand Down Expand Up @@ -10222,14 +10238,24 @@ ParseNodePtr Parser::ParseStatement()
goto LNeedTerminator;

case tkEXPORT:
{
if (!(m_grfscr & fscrIsModuleCode))
{
goto LDefaultToken;
}

pnode = ParseExportDeclaration<buildAST>();
bool needTerminator = false;
pnode = ParseExportDeclaration<buildAST>(&needTerminator);

goto LNeedTerminator;
if (needTerminator)
{
goto LNeedTerminator;
}
else
{
break;
}
}

LDefaultToken:
default:
Expand Down
2 changes: 1 addition & 1 deletion deps/chakrashim/core/lib/Parser/Parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ class Parser
template<bool buildAST> void ParseImportClause(ModuleImportOrExportEntryList* importEntryList, bool parsingAfterComma = false);
template<bool buildAST> ParseNodePtr ParseImportCall();

template<bool buildAST> ParseNodePtr ParseExportDeclaration();
template<bool buildAST> ParseNodePtr ParseExportDeclaration(bool *needTerminator = nullptr);
template<bool buildAST> ParseNodePtr ParseDefaultExportClause();

template<bool buildAST> void ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* importOrExportEntryList, bool isExportClause);
Expand Down
25 changes: 25 additions & 0 deletions deps/chakrashim/core/test/es6/module-syntax.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,31 @@ var tests = [
testModuleScript("var _ = { method: function() { return 'method_result'; }, method2: function() { return 'method2_result'; } }; export default _", 'Export object with methods - framework model');
}
},
{
name: "Valid export statements without semicolon",
body: function () {
testModuleScript('export var v0 if (true) { }', 'var declaration export');
testModuleScript('export let l0 if (true) { }', 'let declaration export');
testModuleScript('export const const0 = 0 if (true) { }', 'const declaration export');
testModuleScript('export function f() { } if (true) { }', 'function declaration export');
testModuleScript('export function *g() { } if (true) { }', 'function generator declaration export');
testModuleScript('export var c0 = class { } if (true) { }', 'var with unnamed class expression export');
testModuleScript('export class c1 { } if (true) { }', 'Named class expression export');
testModuleScript('export default function () { } if (true) { }', 'Unnamed function expression default export');
testModuleScript('export default function _fn2 () { } if (true) { }', 'Named function expression default export');
testModuleScript('export default function* () { } if (true) { }', 'Unnamed generator function expression default export');
testModuleScript('export default function* _gn2 () { } if (true) { }', 'Named generator function expression default export');
testModuleScript('export default class { } if (true) { }', 'Unnamed class expression default export');
testModuleScript('export default class _cl2 { } if (true) { }', 'Named class default expression export');
testModuleScript('export default 1 if (true) { }', 'Primitive type default export');
testModuleScript('var a; export default a = 10 if (true) { }', 'Variable in assignment expression default export');
testModuleScript('export default () => 3 if (true) { }', 'Simple default lambda expression export statement');
testModuleScript('function _default() { }; export default _default if (true) { }', 'Named function statement default export');
testModuleScript('function* g() { }; export default g if (true) { }', 'Named generator function statement default export');
testModuleScript('class c { }; export default c if (true) { }', 'Named class statement default export');
testModuleScript("var _ = { method: function() { return 'method_result'; }, method2: function() { return 'method2_result'; } }; export default _ if (true) { }", 'Export object with methods - framework model');
}
},
{
name: "Syntax error export statements",
body: function () {
Expand Down

0 comments on commit b076970

Please sign in to comment.