Changeset 187890 in webkit


Ignore:
Timestamp:
Aug 4, 2015, 2:26:49 PM (9 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Support Module Syntax
https://bugs.webkit.org/show_bug.cgi?id=147422

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch introduces ES6 Modules syntax parsing part.
In this patch, ASTBuilder just produces the corresponding nodes to the ES6 Modules syntax,
and this patch does not include the code generator part.

Modules require 2 phase parsing. In the first pass, we just analyze the dependent modules
and do not execute the body or construct the AST. And after analyzing all the dependent
modules, we will parse the dependent modules next.
After all analyzing part is done, we will start the second pass. In the second pass, we
will parse the module, produce the AST, and execute the body.
If we don't do so, we need to create all the ASTs in the module's dependent graph at first
because the given module can be executed after the all dependent modules are executed. It
means that we need to hold so many parser arenas. To avoid this, the first pass only extracts
the dependent modules' information.

In this patch, we don't add this analyzing part yet. This patch only implements the second pass.
This patch aims at just implementing the syntax parsing functionality correctly.
After this patch is landed, we will create the ModuleDependencyAnalyzer that inherits SyntaxChecker
to collect the dependent modules fast[1].

To test the parsing, we added the "checkModuleSyntax" function into jsc shell.
By using this, we can parse the given string as the module.

[1]: https://bugs.webkit.org/show_bug.cgi?id=147353

  • bytecompiler/NodesCodegen.cpp:

(JSC::ModuleProgramNode::emitBytecode):
(JSC::ImportDeclarationNode::emitBytecode):
(JSC::ExportAllDeclarationNode::emitBytecode):
(JSC::ExportDefaultDeclarationNode::emitBytecode):
(JSC::ExportLocalDeclarationNode::emitBytecode):
(JSC::ExportNamedDeclarationNode::emitBytecode):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionCheckModuleSyntax):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createModuleSpecifier):
(JSC::ASTBuilder::createImportSpecifier):
(JSC::ASTBuilder::createImportSpecifierList):
(JSC::ASTBuilder::appendImportSpecifier):
(JSC::ASTBuilder::createImportDeclaration):
(JSC::ASTBuilder::createExportAllDeclaration):
(JSC::ASTBuilder::createExportDefaultDeclaration):
(JSC::ASTBuilder::createExportLocalDeclaration):
(JSC::ASTBuilder::createExportNamedDeclaration):
(JSC::ASTBuilder::createExportSpecifier):
(JSC::ASTBuilder::createExportSpecifierList):
(JSC::ASTBuilder::appendExportSpecifier):

  • parser/Keywords.table:
  • parser/NodeConstructors.h:

(JSC::ModuleSpecifierNode::ModuleSpecifierNode):
(JSC::ImportSpecifierNode::ImportSpecifierNode):
(JSC::ImportDeclarationNode::ImportDeclarationNode):
(JSC::ExportAllDeclarationNode::ExportAllDeclarationNode):
(JSC::ExportDefaultDeclarationNode::ExportDefaultDeclarationNode):
(JSC::ExportLocalDeclarationNode::ExportLocalDeclarationNode):
(JSC::ExportNamedDeclarationNode::ExportNamedDeclarationNode):
(JSC::ExportSpecifierNode::ExportSpecifierNode):

  • parser/Nodes.cpp:

(JSC::ModuleProgramNode::ModuleProgramNode):

  • parser/Nodes.h:

(JSC::ModuleProgramNode::startColumn):
(JSC::ModuleProgramNode::endColumn):
(JSC::ModuleSpecifierNode::moduleName):
(JSC::ImportSpecifierNode::importedName):
(JSC::ImportSpecifierNode::localName):
(JSC::ImportSpecifierListNode::specifiers):
(JSC::ImportSpecifierListNode::append):
(JSC::ImportDeclarationNode::specifierList):
(JSC::ImportDeclarationNode::moduleSpecifier):
(JSC::ExportAllDeclarationNode::moduleSpecifier):
(JSC::ExportDefaultDeclarationNode::declaration):
(JSC::ExportLocalDeclarationNode::declaration):
(JSC::ExportSpecifierNode::exportedName):
(JSC::ExportSpecifierNode::localName):
(JSC::ExportSpecifierListNode::specifiers):
(JSC::ExportSpecifierListNode::append):
(JSC::ExportNamedDeclarationNode::specifierList):
(JSC::ExportNamedDeclarationNode::moduleSpecifier):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseModuleSourceElements):
(JSC::Parser<LexerType>::parseVariableDeclaration):
(JSC::Parser<LexerType>::parseVariableDeclarationList):
(JSC::Parser<LexerType>::createBindingPattern):
(JSC::Parser<LexerType>::tryParseDestructuringPatternExpression):
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseForStatement):
(JSC::Parser<LexerType>::parseFormalParameters):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClassDeclaration):
(JSC::Parser<LexerType>::parseModuleSpecifier):
(JSC::Parser<LexerType>::parseImportClauseItem):
(JSC::Parser<LexerType>::parseImportDeclaration):
(JSC::Parser<LexerType>::parseExportSpecifier):
(JSC::Parser<LexerType>::parseExportDeclaration):
(JSC::Parser<LexerType>::parseMemberExpression):

  • parser/Parser.h:

(JSC::isIdentifierOrKeyword):
(JSC::ModuleScopeData::create):
(JSC::ModuleScopeData::exportedBindings):
(JSC::ModuleScopeData::exportName):
(JSC::ModuleScopeData::exportBinding):
(JSC::Scope::Scope):
(JSC::Scope::setIsModule):
(JSC::Scope::moduleScopeData):
(JSC::Parser::matchContextualKeyword):
(JSC::Parser::matchIdentifierOrKeyword):
(JSC::Parser::isofToken): Deleted.

  • parser/ParserModes.h:
  • parser/ParserTokens.h:
  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createModuleSpecifier):
(JSC::SyntaxChecker::createImportSpecifier):
(JSC::SyntaxChecker::createImportSpecifierList):
(JSC::SyntaxChecker::appendImportSpecifier):
(JSC::SyntaxChecker::createImportDeclaration):
(JSC::SyntaxChecker::createExportAllDeclaration):
(JSC::SyntaxChecker::createExportDefaultDeclaration):
(JSC::SyntaxChecker::createExportLocalDeclaration):
(JSC::SyntaxChecker::createExportNamedDeclaration):
(JSC::SyntaxChecker::createExportSpecifier):
(JSC::SyntaxChecker::createExportSpecifierList):
(JSC::SyntaxChecker::appendExportSpecifier):

  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):

  • runtime/CommonIdentifiers.h:
  • runtime/Completion.cpp:

(JSC::checkModuleSyntax):

  • runtime/Completion.h:
  • tests/stress/modules-syntax-error-with-names.js: Added.

(shouldThrow):

  • tests/stress/modules-syntax-error.js: Added.

(shouldThrow):
(checkModuleSyntaxError.checkModuleSyntaxError.checkModuleSyntaxError):

  • tests/stress/modules-syntax.js: Added.

(prototype.checkModuleSyntax):
(checkModuleSyntax):

  • tests/stress/tagged-templates-syntax.js:

LayoutTests:

'export' and 'import' are changed from FutureReservedWord to Keyword in ES6.
http://www.ecma-international.org/ecma-262/6.0/#sec-keywords
And restrict 'super' use under the Script / Module contexts.

  • js/dom/reserved-words-as-property-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.10-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.27-expected.txt:
Location:
trunk
Files:
3 added
23 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/LayoutTests/ChangeLog

    r187886 r187890  
     12015-08-04  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Support Module Syntax
     4        https://bugs.webkit.org/show_bug.cgi?id=147422
     5
     6        Reviewed by Saam Barati.
     7
     8        'export' and 'import' are changed from FutureReservedWord to Keyword in ES6.
     9        http://www.ecma-international.org/ecma-262/6.0/#sec-keywords
     10        And restrict 'super' use under the Script / Module contexts.
     11
     12        * js/dom/reserved-words-as-property-expected.txt:
     13        * sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.10-expected.txt:
     14        * sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt:
     15        * sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.27-expected.txt:
     16
    1172015-08-04  Alexey Proskuryakov  <ap@apple.com>
    218
  • TabularUnified trunk/LayoutTests/js/dom/reserved-words-as-property-expected.txt

    r186860 r187890  
    11561156PASS "use strict";({ get enum(){}, set enum(x){}, parsedOkay: 42 }.parsedOkay === 42) is true
    11571157PASS (function(){"use strict";({ get enum(){}, set enum(x){}, parsedOkay: 42 }.parsedOkay === 42)}); true is true
    1158 PASS var export; true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1159 PASS (function(){var export; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1160 PASS var export = 42; export === 42 threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1161 PASS (function(){var export = 42; export === 42}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1162 PASS function g(export){  }; true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1163 PASS (function(){function g(export){  }; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1164 PASS /export/.test(function g(export){  }) threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1165 PASS (function(){/export/.test(function g(export){  })}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1166 PASS try{}catch(export){}; true threw exception SyntaxError: Cannot use the reserved word 'export' as a catch variable name..
    1167 PASS (function(){try{}catch(export){}; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a catch variable name..
    1168 PASS function export(){  }; true threw exception SyntaxError: Cannot use the reserved word 'export' as a function name..
    1169 PASS (function(){function export(){  }; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a function name..
     1158PASS var export; true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1159PASS (function(){var export; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1160PASS var export = 42; export === 42 threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1161PASS (function(){var export = 42; export === 42}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1162PASS function g(export){  }; true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1163PASS (function(){function g(export){  }; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1164PASS /export/.test(function g(export){  }) threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1165PASS (function(){/export/.test(function g(export){  })}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1166PASS try{}catch(export){}; true threw exception SyntaxError: Cannot use the keyword 'export' as a catch variable name..
     1167PASS (function(){try{}catch(export){}; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a catch variable name..
     1168PASS function export(){  }; true threw exception SyntaxError: Cannot use the keyword 'export' as a function name..
     1169PASS (function(){function export(){  }; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a function name..
    11701170PASS ({ "export": 42 }.export === 42) is true
    11711171PASS (function(){({ "export": 42 }.export === 42)}); true is true
     
    11741174PASS ({ get export(){}, set export(x){}, parsedOkay: 42 }.parsedOkay === 42) is true
    11751175PASS (function(){({ get export(){}, set export(x){}, parsedOkay: 42 }.parsedOkay === 42)}); true is true
    1176 PASS "use strict";var export; true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1177 PASS (function(){"use strict";var export; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1178 PASS "use strict";var export = 42; export === 42 threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1179 PASS (function(){"use strict";var export = 42; export === 42}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1180 PASS "use strict";function g(export){ "use strict"; }; true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1181 PASS (function(){"use strict";function g(export){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1182 PASS "use strict";/export/.test(function g(export){ "use strict"; }) threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1183 PASS (function(){"use strict";/export/.test(function g(export){ "use strict"; })}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a variable name..
    1184 PASS "use strict";try{}catch(export){}; true threw exception SyntaxError: Cannot use the reserved word 'export' as a catch variable name..
    1185 PASS (function(){"use strict";try{}catch(export){}; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a catch variable name..
    1186 PASS "use strict";function export(){ "use strict"; }; true threw exception SyntaxError: Cannot use the reserved word 'export' as a function name..
    1187 PASS (function(){"use strict";function export(){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the reserved word 'export' as a function name..
     1176PASS "use strict";var export; true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1177PASS (function(){"use strict";var export; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1178PASS "use strict";var export = 42; export === 42 threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1179PASS (function(){"use strict";var export = 42; export === 42}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1180PASS "use strict";function g(export){ "use strict"; }; true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1181PASS (function(){"use strict";function g(export){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1182PASS "use strict";/export/.test(function g(export){ "use strict"; }) threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1183PASS (function(){"use strict";/export/.test(function g(export){ "use strict"; })}); true threw exception SyntaxError: Cannot use the keyword 'export' as a variable name..
     1184PASS "use strict";try{}catch(export){}; true threw exception SyntaxError: Cannot use the keyword 'export' as a catch variable name..
     1185PASS (function(){"use strict";try{}catch(export){}; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a catch variable name..
     1186PASS "use strict";function export(){ "use strict"; }; true threw exception SyntaxError: Cannot use the keyword 'export' as a function name..
     1187PASS (function(){"use strict";function export(){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the keyword 'export' as a function name..
    11881188PASS "use strict";({ "export": 42 }.export === 42) is true
    11891189PASS (function(){"use strict";({ "export": 42 }.export === 42)}); true is true
     
    12281228PASS "use strict";({ get extends(){}, set extends(x){}, parsedOkay: 42 }.parsedOkay === 42) is true
    12291229PASS (function(){"use strict";({ get extends(){}, set extends(x){}, parsedOkay: 42 }.parsedOkay === 42)}); true is true
    1230 PASS var import; true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1231 PASS (function(){var import; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1232 PASS var import = 42; import === 42 threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1233 PASS (function(){var import = 42; import === 42}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1234 PASS function g(import){  }; true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1235 PASS (function(){function g(import){  }; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1236 PASS /import/.test(function g(import){  }) threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1237 PASS (function(){/import/.test(function g(import){  })}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1238 PASS try{}catch(import){}; true threw exception SyntaxError: Cannot use the reserved word 'import' as a catch variable name..
    1239 PASS (function(){try{}catch(import){}; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a catch variable name..
    1240 PASS function import(){  }; true threw exception SyntaxError: Cannot use the reserved word 'import' as a function name..
    1241 PASS (function(){function import(){  }; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a function name..
     1230PASS var import; true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1231PASS (function(){var import; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1232PASS var import = 42; import === 42 threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1233PASS (function(){var import = 42; import === 42}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1234PASS function g(import){  }; true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1235PASS (function(){function g(import){  }; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1236PASS /import/.test(function g(import){  }) threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1237PASS (function(){/import/.test(function g(import){  })}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1238PASS try{}catch(import){}; true threw exception SyntaxError: Cannot use the keyword 'import' as a catch variable name..
     1239PASS (function(){try{}catch(import){}; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a catch variable name..
     1240PASS function import(){  }; true threw exception SyntaxError: Cannot use the keyword 'import' as a function name..
     1241PASS (function(){function import(){  }; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a function name..
    12421242PASS ({ "import": 42 }.import === 42) is true
    12431243PASS (function(){({ "import": 42 }.import === 42)}); true is true
     
    12461246PASS ({ get import(){}, set import(x){}, parsedOkay: 42 }.parsedOkay === 42) is true
    12471247PASS (function(){({ get import(){}, set import(x){}, parsedOkay: 42 }.parsedOkay === 42)}); true is true
    1248 PASS "use strict";var import; true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1249 PASS (function(){"use strict";var import; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1250 PASS "use strict";var import = 42; import === 42 threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1251 PASS (function(){"use strict";var import = 42; import === 42}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1252 PASS "use strict";function g(import){ "use strict"; }; true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1253 PASS (function(){"use strict";function g(import){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1254 PASS "use strict";/import/.test(function g(import){ "use strict"; }) threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1255 PASS (function(){"use strict";/import/.test(function g(import){ "use strict"; })}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a variable name..
    1256 PASS "use strict";try{}catch(import){}; true threw exception SyntaxError: Cannot use the reserved word 'import' as a catch variable name..
    1257 PASS (function(){"use strict";try{}catch(import){}; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a catch variable name..
    1258 PASS "use strict";function import(){ "use strict"; }; true threw exception SyntaxError: Cannot use the reserved word 'import' as a function name..
    1259 PASS (function(){"use strict";function import(){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the reserved word 'import' as a function name..
     1248PASS "use strict";var import; true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1249PASS (function(){"use strict";var import; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1250PASS "use strict";var import = 42; import === 42 threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1251PASS (function(){"use strict";var import = 42; import === 42}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1252PASS "use strict";function g(import){ "use strict"; }; true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1253PASS (function(){"use strict";function g(import){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1254PASS "use strict";/import/.test(function g(import){ "use strict"; }) threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1255PASS (function(){"use strict";/import/.test(function g(import){ "use strict"; })}); true threw exception SyntaxError: Cannot use the keyword 'import' as a variable name..
     1256PASS "use strict";try{}catch(import){}; true threw exception SyntaxError: Cannot use the keyword 'import' as a catch variable name..
     1257PASS (function(){"use strict";try{}catch(import){}; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a catch variable name..
     1258PASS "use strict";function import(){ "use strict"; }; true threw exception SyntaxError: Cannot use the keyword 'import' as a function name..
     1259PASS (function(){"use strict";function import(){ "use strict"; }; true}); true threw exception SyntaxError: Cannot use the keyword 'import' as a function name..
    12601260PASS "use strict";({ "import": 42 }.import === 42) is true
    12611261PASS (function(){"use strict";({ "import": 42 }.import === 42)}); true is true
  • TabularUnified trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.10-expected.txt

    r158014 r187890  
    1 CONSOLE MESSAGE: line 76: SyntaxError: Unexpected use of reserved word 'export'
     1CONSOLE MESSAGE: line 76: SyntaxError: Unexpected keyword 'export'
    22S7.5.3_A1.10
    33
  • TabularUnified trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt

    r158014 r187890  
    1 CONSOLE MESSAGE: line 76: SyntaxError: Unexpected use of reserved word 'import'
     1CONSOLE MESSAGE: line 76: SyntaxError: Unexpected keyword 'import'
    22S7.5.3_A1.16
    33
  • TabularUnified trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.27-expected.txt

    r181618 r187890  
    1 CONSOLE MESSAGE: line 76: SyntaxError: Cannot reference super.
     1CONSOLE MESSAGE: line 76: SyntaxError: super is only valid inside functions.
    22S7.5.3_A1.27
    33
  • TabularUnified trunk/Source/JavaScriptCore/ChangeLog

    r187819 r187890  
     12015-08-04  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Support Module Syntax
     4        https://bugs.webkit.org/show_bug.cgi?id=147422
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch introduces ES6 Modules syntax parsing part.
     9        In this patch, ASTBuilder just produces the corresponding nodes to the ES6 Modules syntax,
     10        and this patch does not include the code generator part.
     11
     12        Modules require 2 phase parsing. In the first pass, we just analyze the dependent modules
     13        and do not execute the body or construct the AST. And after analyzing all the dependent
     14        modules, we will parse the dependent modules next.
     15        After all analyzing part is done, we will start the second pass. In the second pass, we
     16        will parse the module, produce the AST, and execute the body.
     17        If we don't do so, we need to create all the ASTs in the module's dependent graph at first
     18        because the given module can be executed after the all dependent modules are executed. It
     19        means that we need to hold so many parser arenas. To avoid this, the first pass only extracts
     20        the dependent modules' information.
     21
     22        In this patch, we don't add this analyzing part yet. This patch only implements the second pass.
     23        This patch aims at just implementing the syntax parsing functionality correctly.
     24        After this patch is landed, we will create the ModuleDependencyAnalyzer that inherits SyntaxChecker
     25        to collect the dependent modules fast[1].
     26
     27        To test the parsing, we added the "checkModuleSyntax" function into jsc shell.
     28        By using this, we can parse the given string as the module.
     29
     30        [1]: https://bugs.webkit.org/show_bug.cgi?id=147353
     31
     32        * bytecompiler/NodesCodegen.cpp:
     33        (JSC::ModuleProgramNode::emitBytecode):
     34        (JSC::ImportDeclarationNode::emitBytecode):
     35        (JSC::ExportAllDeclarationNode::emitBytecode):
     36        (JSC::ExportDefaultDeclarationNode::emitBytecode):
     37        (JSC::ExportLocalDeclarationNode::emitBytecode):
     38        (JSC::ExportNamedDeclarationNode::emitBytecode):
     39        * jsc.cpp:
     40        (GlobalObject::finishCreation):
     41        (functionCheckModuleSyntax):
     42        * parser/ASTBuilder.h:
     43        (JSC::ASTBuilder::createModuleSpecifier):
     44        (JSC::ASTBuilder::createImportSpecifier):
     45        (JSC::ASTBuilder::createImportSpecifierList):
     46        (JSC::ASTBuilder::appendImportSpecifier):
     47        (JSC::ASTBuilder::createImportDeclaration):
     48        (JSC::ASTBuilder::createExportAllDeclaration):
     49        (JSC::ASTBuilder::createExportDefaultDeclaration):
     50        (JSC::ASTBuilder::createExportLocalDeclaration):
     51        (JSC::ASTBuilder::createExportNamedDeclaration):
     52        (JSC::ASTBuilder::createExportSpecifier):
     53        (JSC::ASTBuilder::createExportSpecifierList):
     54        (JSC::ASTBuilder::appendExportSpecifier):
     55        * parser/Keywords.table:
     56        * parser/NodeConstructors.h:
     57        (JSC::ModuleSpecifierNode::ModuleSpecifierNode):
     58        (JSC::ImportSpecifierNode::ImportSpecifierNode):
     59        (JSC::ImportDeclarationNode::ImportDeclarationNode):
     60        (JSC::ExportAllDeclarationNode::ExportAllDeclarationNode):
     61        (JSC::ExportDefaultDeclarationNode::ExportDefaultDeclarationNode):
     62        (JSC::ExportLocalDeclarationNode::ExportLocalDeclarationNode):
     63        (JSC::ExportNamedDeclarationNode::ExportNamedDeclarationNode):
     64        (JSC::ExportSpecifierNode::ExportSpecifierNode):
     65        * parser/Nodes.cpp:
     66        (JSC::ModuleProgramNode::ModuleProgramNode):
     67        * parser/Nodes.h:
     68        (JSC::ModuleProgramNode::startColumn):
     69        (JSC::ModuleProgramNode::endColumn):
     70        (JSC::ModuleSpecifierNode::moduleName):
     71        (JSC::ImportSpecifierNode::importedName):
     72        (JSC::ImportSpecifierNode::localName):
     73        (JSC::ImportSpecifierListNode::specifiers):
     74        (JSC::ImportSpecifierListNode::append):
     75        (JSC::ImportDeclarationNode::specifierList):
     76        (JSC::ImportDeclarationNode::moduleSpecifier):
     77        (JSC::ExportAllDeclarationNode::moduleSpecifier):
     78        (JSC::ExportDefaultDeclarationNode::declaration):
     79        (JSC::ExportLocalDeclarationNode::declaration):
     80        (JSC::ExportSpecifierNode::exportedName):
     81        (JSC::ExportSpecifierNode::localName):
     82        (JSC::ExportSpecifierListNode::specifiers):
     83        (JSC::ExportSpecifierListNode::append):
     84        (JSC::ExportNamedDeclarationNode::specifierList):
     85        (JSC::ExportNamedDeclarationNode::moduleSpecifier):
     86        * parser/Parser.cpp:
     87        (JSC::Parser<LexerType>::Parser):
     88        (JSC::Parser<LexerType>::parseInner):
     89        (JSC::Parser<LexerType>::parseModuleSourceElements):
     90        (JSC::Parser<LexerType>::parseVariableDeclaration):
     91        (JSC::Parser<LexerType>::parseVariableDeclarationList):
     92        (JSC::Parser<LexerType>::createBindingPattern):
     93        (JSC::Parser<LexerType>::tryParseDestructuringPatternExpression):
     94        (JSC::Parser<LexerType>::parseDestructuringPattern):
     95        (JSC::Parser<LexerType>::parseForStatement):
     96        (JSC::Parser<LexerType>::parseFormalParameters):
     97        (JSC::Parser<LexerType>::parseFunctionParameters):
     98        (JSC::Parser<LexerType>::parseFunctionDeclaration):
     99        (JSC::Parser<LexerType>::parseClassDeclaration):
     100        (JSC::Parser<LexerType>::parseModuleSpecifier):
     101        (JSC::Parser<LexerType>::parseImportClauseItem):
     102        (JSC::Parser<LexerType>::parseImportDeclaration):
     103        (JSC::Parser<LexerType>::parseExportSpecifier):
     104        (JSC::Parser<LexerType>::parseExportDeclaration):
     105        (JSC::Parser<LexerType>::parseMemberExpression):
     106        * parser/Parser.h:
     107        (JSC::isIdentifierOrKeyword):
     108        (JSC::ModuleScopeData::create):
     109        (JSC::ModuleScopeData::exportedBindings):
     110        (JSC::ModuleScopeData::exportName):
     111        (JSC::ModuleScopeData::exportBinding):
     112        (JSC::Scope::Scope):
     113        (JSC::Scope::setIsModule):
     114        (JSC::Scope::moduleScopeData):
     115        (JSC::Parser::matchContextualKeyword):
     116        (JSC::Parser::matchIdentifierOrKeyword):
     117        (JSC::Parser::isofToken): Deleted.
     118        * parser/ParserModes.h:
     119        * parser/ParserTokens.h:
     120        * parser/SyntaxChecker.h:
     121        (JSC::SyntaxChecker::createModuleSpecifier):
     122        (JSC::SyntaxChecker::createImportSpecifier):
     123        (JSC::SyntaxChecker::createImportSpecifierList):
     124        (JSC::SyntaxChecker::appendImportSpecifier):
     125        (JSC::SyntaxChecker::createImportDeclaration):
     126        (JSC::SyntaxChecker::createExportAllDeclaration):
     127        (JSC::SyntaxChecker::createExportDefaultDeclaration):
     128        (JSC::SyntaxChecker::createExportLocalDeclaration):
     129        (JSC::SyntaxChecker::createExportNamedDeclaration):
     130        (JSC::SyntaxChecker::createExportSpecifier):
     131        (JSC::SyntaxChecker::createExportSpecifierList):
     132        (JSC::SyntaxChecker::appendExportSpecifier):
     133        * runtime/CommonIdentifiers.cpp:
     134        (JSC::CommonIdentifiers::CommonIdentifiers):
     135        * runtime/CommonIdentifiers.h:
     136        * runtime/Completion.cpp:
     137        (JSC::checkModuleSyntax):
     138        * runtime/Completion.h:
     139        * tests/stress/modules-syntax-error-with-names.js: Added.
     140        (shouldThrow):
     141        * tests/stress/modules-syntax-error.js: Added.
     142        (shouldThrow):
     143        (checkModuleSyntaxError.checkModuleSyntaxError.checkModuleSyntaxError):
     144        * tests/stress/modules-syntax.js: Added.
     145        (prototype.checkModuleSyntax):
     146        (checkModuleSyntax):
     147        * tests/stress/tagged-templates-syntax.js:
     148
    11492015-08-03  Csaba Osztrogonác  <ossy@webkit.org>
    2150
  • TabularUnified trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r187524 r187890  
    28892889}
    28902890
     2891// ------------------------------ ModuleProgramNode --------------------
     2892
     2893void ModuleProgramNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     2894{
     2895}
     2896
    28912897// ------------------------------ EvalNode -----------------------------
    28922898
     
    30393045}
    30403046#endif
    3041    
     3047
     3048// ------------------------------ ImportDeclarationNode -----------------------
     3049
     3050void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     3051{
     3052}
     3053
     3054// ------------------------------ ExportAllDeclarationNode --------------------
     3055
     3056void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     3057{
     3058}
     3059
     3060// ------------------------------ ExportDefaultDeclarationNode ----------------
     3061
     3062void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     3063{
     3064}
     3065
     3066// ------------------------------ ExportLocalDeclarationNode ------------------
     3067
     3068void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     3069{
     3070}
     3071
     3072// ------------------------------ ExportNamedDeclarationNode ------------------
     3073
     3074void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
     3075{
     3076}
     3077
    30423078// ------------------------------ DestructuringAssignmentNode -----------------
    30433079RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
  • TabularUnified trunk/Source/JavaScriptCore/jsc.cpp

    r187677 r187890  
    498498static EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState*);
    499499#endif
     500#if ENABLE(ES6_MODULES)
     501static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
     502#endif
    500503
    501504#if ENABLE(SAMPLING_FLAGS)
     
    664667        addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 1);
    665668#endif
     669#if ENABLE(ES6_MODULES)
     670        addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
     671#endif
    666672
    667673        JSArray* array = constructEmptyArray(globalExec(), 0);
     
    12071213        return JSValue::encode(exec->vm().throwException(exec, createSyntaxError(exec, errorMessage)));
    12081214    return JSValue::encode(module);
     1215}
     1216#endif
     1217
     1218#if ENABLE(ES6_MODULES)
     1219EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
     1220{
     1221    String source = exec->argument(0).toString(exec)->value(exec);
     1222
     1223    StopWatch stopWatch;
     1224    stopWatch.start();
     1225
     1226    ParserError error;
     1227    bool validSyntax = checkModuleSyntax(exec->vm(), makeSource(source), error);
     1228    stopWatch.stop();
     1229
     1230    if (!validSyntax)
     1231        exec->vm().throwException(exec, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
     1232    return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
    12091233}
    12101234#endif
  • TabularUnified trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r187760 r187890  
    114114    typedef ClassExprNode* ClassExpression;
    115115#endif
     116    typedef ModuleSpecifierNode* ModuleSpecifier;
     117    typedef ImportSpecifierNode* ImportSpecifier;
     118    typedef ImportSpecifierListNode* ImportSpecifierList;
     119    typedef ExportSpecifierNode* ExportSpecifier;
     120    typedef ExportSpecifierListNode* ExportSpecifierList;
    116121    typedef StatementNode* Statement;
    117122    typedef ClauseListNode* ClauseList;
     
    615620        return result;
    616621    }
    617    
     622
     623    ModuleSpecifierNode* createModuleSpecifier(const JSTokenLocation& location, const Identifier& moduleName)
     624    {
     625        return new (m_parserArena) ModuleSpecifierNode(location, moduleName);
     626    }
     627
     628    ImportSpecifierNode* createImportSpecifier(const JSTokenLocation& location, const Identifier& importedName, const Identifier& localName)
     629    {
     630        return new (m_parserArena) ImportSpecifierNode(location, importedName, localName);
     631    }
     632
     633    ImportSpecifierListNode* createImportSpecifierList()
     634    {
     635        return new (m_parserArena) ImportSpecifierListNode();
     636    }
     637
     638    void appendImportSpecifier(ImportSpecifierListNode* specifierList, ImportSpecifierNode* specifier)
     639    {
     640        specifierList->append(specifier);
     641    }
     642
     643    StatementNode* createImportDeclaration(const JSTokenLocation& location, ImportSpecifierListNode* importSpecifierList, ModuleSpecifierNode* moduleSpecifier)
     644    {
     645        return new (m_parserArena) ImportDeclarationNode(location, importSpecifierList, moduleSpecifier);
     646    }
     647
     648    StatementNode* createExportAllDeclaration(const JSTokenLocation& location, ModuleSpecifierNode* moduleSpecifier)
     649    {
     650        return new (m_parserArena) ExportAllDeclarationNode(location, moduleSpecifier);
     651    }
     652
     653    StatementNode* createExportDefaultDeclaration(const JSTokenLocation& location, StatementNode* declaration)
     654    {
     655        return new (m_parserArena) ExportDefaultDeclarationNode(location, declaration);
     656    }
     657
     658    StatementNode* createExportLocalDeclaration(const JSTokenLocation& location, StatementNode* declaration)
     659    {
     660        return new (m_parserArena) ExportLocalDeclarationNode(location, declaration);
     661    }
     662
     663    StatementNode* createExportNamedDeclaration(const JSTokenLocation& location, ExportSpecifierListNode* exportSpecifierList, ModuleSpecifierNode* moduleSpecifier)
     664    {
     665        return new (m_parserArena) ExportNamedDeclarationNode(location, exportSpecifierList, moduleSpecifier);
     666    }
     667
     668    ExportSpecifierNode* createExportSpecifier(const JSTokenLocation& location, const Identifier& localName, const Identifier& exportedName)
     669    {
     670        return new (m_parserArena) ExportSpecifierNode(location, localName, exportedName);
     671    }
     672
     673    ExportSpecifierListNode* createExportSpecifierList()
     674    {
     675        return new (m_parserArena) ExportSpecifierListNode();
     676    }
     677
     678    void appendExportSpecifier(ExportSpecifierListNode* specifierList, ExportSpecifierNode* specifier)
     679    {
     680        specifierList->append(specifier);
     681    }
     682
    618683    void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement)
    619684    {
  • TabularUnified trunk/Source/JavaScriptCore/parser/Keywords.table

    r186860 r187890  
    4242# Reserved for future use.
    4343enum            RESERVED
    44 export          RESERVED
    45 import          RESERVED
     44export          EXPORT
     45import          IMPORT
    4646
    4747# Reserved for future use in strict code.
  • TabularUnified trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r187515 r187890  
    734734    }
    735735
     736    inline ModuleSpecifierNode::ModuleSpecifierNode(const JSTokenLocation& location, const Identifier& moduleName)
     737        : Node(location)
     738        , m_moduleName(moduleName)
     739    {
     740    }
     741
     742    inline ImportSpecifierNode::ImportSpecifierNode(const JSTokenLocation& location, const Identifier& importedName, const Identifier& localName)
     743        : Node(location)
     744        , m_importedName(importedName)
     745        , m_localName(localName)
     746    {
     747    }
     748
     749    inline ImportDeclarationNode::ImportDeclarationNode(const JSTokenLocation& location, ImportSpecifierListNode* importSpecifierList, ModuleSpecifierNode* moduleSpecifier)
     750        : StatementNode(location)
     751        , m_specifierList(importSpecifierList)
     752        , m_moduleSpecifier(moduleSpecifier)
     753    {
     754    }
     755
     756    inline ExportAllDeclarationNode::ExportAllDeclarationNode(const JSTokenLocation& location, ModuleSpecifierNode* moduleSpecifier)
     757        : StatementNode(location)
     758        , m_moduleSpecifier(moduleSpecifier)
     759    {
     760    }
     761
     762    inline ExportDefaultDeclarationNode::ExportDefaultDeclarationNode(const JSTokenLocation& location, StatementNode* declaration)
     763        : StatementNode(location)
     764        , m_declaration(declaration)
     765    {
     766    }
     767
     768    inline ExportLocalDeclarationNode::ExportLocalDeclarationNode(const JSTokenLocation& location, StatementNode* declaration)
     769        : StatementNode(location)
     770        , m_declaration(declaration)
     771    {
     772    }
     773
     774    inline ExportNamedDeclarationNode::ExportNamedDeclarationNode(const JSTokenLocation& location, ExportSpecifierListNode* exportSpecifierList, ModuleSpecifierNode* moduleSpecifier)
     775        : StatementNode(location)
     776        , m_specifierList(exportSpecifierList)
     777        , m_moduleSpecifier(moduleSpecifier)
     778    {
     779    }
     780
     781    inline ExportSpecifierNode::ExportSpecifierNode(const JSTokenLocation& location, const Identifier& localName, const Identifier& exportedName)
     782        : Node(location)
     783        , m_localName(localName)
     784        , m_exportedName(exportedName)
     785    {
     786    }
     787
    736788    inline EmptyVarExpression::EmptyVarExpression(const JSTokenLocation& location, const Identifier& ident)
    737789        : ExpressionNode(location)
  • TabularUnified trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r186959 r187890  
    130130}
    131131
     132// ------------------------------ ModuleProgramNode -----------------------------
     133
     134ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, int numConstants)
     135    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, numConstants)
     136    , m_startColumn(startColumn)
     137    , m_endColumn(endColumn)
     138{
     139}
     140
    132141// ------------------------------ EvalNode -----------------------------
    133142
  • TabularUnified trunk/Source/JavaScriptCore/parser/Nodes.h

    r187515 r187890  
    16231623    };
    16241624
     1625    class ModuleProgramNode : public ScopeNode {
     1626    public:
     1627        ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, int numConstants);
     1628
     1629        unsigned startColumn() const { return m_startColumn; }
     1630        unsigned endColumn() const { return m_endColumn; }
     1631
     1632        static const bool scopeIsFunction = false;
     1633
     1634    private:
     1635        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     1636        unsigned m_startColumn;
     1637        unsigned m_endColumn;
     1638    };
     1639
     1640    class ModuleSpecifierNode : public Node {
     1641    public:
     1642        ModuleSpecifierNode(const JSTokenLocation&, const Identifier& moduleName);
     1643
     1644        const Identifier& moduleName() { return m_moduleName; }
     1645
     1646    private:
     1647        const Identifier& m_moduleName;
     1648    };
     1649
     1650    class ImportSpecifierNode : public Node {
     1651    public:
     1652        ImportSpecifierNode(const JSTokenLocation&, const Identifier& importedName, const Identifier& localName);
     1653
     1654        const Identifier& importedName() { return m_importedName; }
     1655        const Identifier& localName() { return m_localName; }
     1656
     1657    private:
     1658        const Identifier& m_importedName;
     1659        const Identifier& m_localName;
     1660    };
     1661
     1662    class ImportSpecifierListNode : public ParserArenaDeletable {
     1663    public:
     1664        typedef Vector<ImportSpecifierNode*, 3> Specifiers;
     1665
     1666        const Specifiers& specifiers() const { return m_specifiers; }
     1667        void append(ImportSpecifierNode* specifier)
     1668        {
     1669            m_specifiers.append(specifier);
     1670        }
     1671
     1672    private:
     1673        Specifiers m_specifiers;
     1674    };
     1675
     1676    class ImportDeclarationNode : public StatementNode {
     1677    public:
     1678        ImportDeclarationNode(const JSTokenLocation&, ImportSpecifierListNode*, ModuleSpecifierNode*);
     1679
     1680        ImportSpecifierListNode* specifierList() const { return m_specifierList; }
     1681        ModuleSpecifierNode* moduleSpecifier() const { return m_moduleSpecifier; }
     1682
     1683    private:
     1684        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     1685
     1686        ImportSpecifierListNode* m_specifierList;
     1687        ModuleSpecifierNode* m_moduleSpecifier;
     1688    };
     1689
     1690    class ExportAllDeclarationNode : public StatementNode {
     1691    public:
     1692        ExportAllDeclarationNode(const JSTokenLocation&, ModuleSpecifierNode*);
     1693
     1694        ModuleSpecifierNode* moduleSpecifier() const { return m_moduleSpecifier; }
     1695
     1696    private:
     1697        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     1698        ModuleSpecifierNode* m_moduleSpecifier;
     1699    };
     1700
     1701    class ExportDefaultDeclarationNode : public StatementNode {
     1702    public:
     1703        ExportDefaultDeclarationNode(const JSTokenLocation&, StatementNode*);
     1704
     1705        const StatementNode& declaration() const { return *m_declaration; }
     1706
     1707    private:
     1708        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     1709        StatementNode* m_declaration;
     1710    };
     1711
     1712    class ExportLocalDeclarationNode : public StatementNode {
     1713    public:
     1714        ExportLocalDeclarationNode(const JSTokenLocation&, StatementNode*);
     1715
     1716        const StatementNode& declaration() const { return *m_declaration; }
     1717
     1718    private:
     1719        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     1720        StatementNode* m_declaration;
     1721    };
     1722
     1723    class ExportSpecifierNode : public Node {
     1724    public:
     1725        ExportSpecifierNode(const JSTokenLocation&, const Identifier& localName, const Identifier& exportedName);
     1726
     1727        const Identifier& exportedName() { return m_exportedName; }
     1728        const Identifier& localName() { return m_localName; }
     1729
     1730    private:
     1731        const Identifier& m_localName;
     1732        const Identifier& m_exportedName;
     1733    };
     1734
     1735    class ExportSpecifierListNode : public ParserArenaDeletable {
     1736    public:
     1737        typedef Vector<ExportSpecifierNode*, 3> Specifiers;
     1738
     1739        const Specifiers& specifiers() const { return m_specifiers; }
     1740        void append(ExportSpecifierNode* specifier)
     1741        {
     1742            m_specifiers.append(specifier);
     1743        }
     1744
     1745    private:
     1746        Specifiers m_specifiers;
     1747    };
     1748
     1749    class ExportNamedDeclarationNode : public StatementNode {
     1750    public:
     1751        ExportNamedDeclarationNode(const JSTokenLocation&, ExportSpecifierListNode*, ModuleSpecifierNode*);
     1752
     1753        ExportSpecifierListNode* specifierList() const { return m_specifierList; }
     1754        ModuleSpecifierNode* moduleSpecifier() const { return m_moduleSpecifier; }
     1755
     1756    private:
     1757        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     1758        ExportSpecifierListNode* m_specifierList;
     1759        ModuleSpecifierNode* m_moduleSpecifier { nullptr };
     1760    };
     1761
    16251762    class FunctionParameters : public ParserArenaDeletable {
    16261763    public:
  • TabularUnified trunk/Source/JavaScriptCore/parser/Parser.cpp

    r187760 r187890  
    210210    , m_defaultConstructorKind(defaultConstructorKind)
    211211    , m_thisTDZMode(thisTDZMode)
     212    , m_codeType(codeType)
    212213{
    213214    m_lexer = std::make_unique<LexerType>(vm, builtinMode);
     
    221222    if (codeType == JSParserCodeType::Function)
    222223        scope->setIsFunction();
     224    if (codeType == JSParserCodeType::Module)
     225        scope->setIsModule();
    223226    if (strictMode == JSParserStrictMode::Strict)
    224227        scope->setStrictMode();
     
    268271        if (isArrowFunctionBodyExpression)
    269272            sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
     273#if ENABLE(ES6_MODULES)
     274        else if (m_codeType == JSParserCodeType::Module)
     275            sourceElements = parseModuleSourceElements(context);
     276#endif
    270277        else
    271278            sourceElements = parseSourceElements(context, CheckForStrictMode);
     
    404411    return sourceElements;
    405412}
     413
     414template <typename LexerType>
     415template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context)
     416{
     417    TreeSourceElements sourceElements = context.createSourceElements();
     418
     419    // FIXME: When some sort of ModuleAnalyzer TreeBuilder is landed,
     420    // this SyntaxChecker will be replaced with typedef under the TreeBuilder,
     421    // like TreeBuilder::ModuleStatementItemBuilder.
     422    // https://bugs.webkit.org/show_bug.cgi?id=147353
     423    SyntaxChecker moduleStatementItemBuilder(const_cast<VM*>(m_vm), m_lexer.get());
     424
     425    while (true) {
     426        if (match(IMPORT) || match(EXPORT)) {
     427            TreeStatement statement = 0;
     428            if (match(IMPORT))
     429                statement = parseImportDeclaration(context);
     430            else
     431                statement = parseExportDeclaration(context);
     432
     433            if (!statement)
     434                break;
     435            context.appendStatement(sourceElements, statement);
     436        } else {
     437            const Identifier* directive = 0;
     438            unsigned directiveLiteralLength = 0;
     439            if (!parseStatementListItem(moduleStatementItemBuilder, directive, &directiveLiteralLength))
     440                break;
     441        }
     442    }
     443
     444    propagateError();
     445
     446    for (const auto& uid : currentScope()->moduleScopeData().exportedBindings())
     447        semanticFailIfFalse(currentScope()->hasDeclaredVariable(uid) || currentScope()->hasLexicallyDeclaredVariable(uid), "Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
     448
     449    return sourceElements;
     450}
     451
    406452template <typename LexerType>
    407453template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
     
    452498
    453499template <typename LexerType>
    454 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType)
     500template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
    455501{
    456502    ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
     
    463509    JSTextPosition scratch3;
    464510    bool scratchBool;
    465     TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, scratchBool);
     511    TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
    466512    propagateError();
    467513    failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
     
    518564
    519565template <typename LexerType>
    520 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType, bool& forLoopConstDoesNotHaveInitializer)
     566template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType, ExportType exportType, bool& forLoopConstDoesNotHaveInitializer)
    521567{
    522568    ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
     
    556602                }
    557603            }
     604            semanticFailIfTrue(exportType == ExportType::Exported && !currentScope()->moduleScopeData().exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
     605
    558606            if (hasInitializer) {
    559607                JSTextPosition varDivot = tokenStartPosition() + 1;
     
    577625        } else {
    578626            lastIdent = 0;
    579             auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), nullptr, nullptr, assignmentContext);
     627            auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
    580628            failIfFalse(pattern, "Cannot parse this destructuring pattern");
    581629            hasInitializer = match(EQUAL);
     
    605653
    606654template <typename LexerType>
    607 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, const Identifier& name, int depth, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
     655template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, int depth, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
    608656{
    609657    ASSERT(!name.isNull());
     
    657705        }
    658706    }
     707
     708    semanticFailIfTrue(exportType == ExportType::Exported && !currentScope()->moduleScopeData().exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
    659709    return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
    660710}
     
    692742template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
    693743{
    694     return parseDestructuringPattern(context, DestructureToExpressions, nullptr, nullptr, bindingContext);
    695 }
    696 
    697 template <typename LexerType>
    698 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
     744    return parseDestructuringPattern(context, DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
     745}
     746
     747template <typename LexerType>
     748template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
    699749{
    700750    failIfStackOverflow();
     
    725775                JSTokenLocation location = m_token.m_location;
    726776                next();
    727                 auto innerPattern = parseDestructuringPattern(context, kind, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     777                auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    728778                if (kind == DestructureToExpressions && !innerPattern)
    729779                    return 0;
     
    738788
    739789            JSTokenLocation location = m_token.m_location;
    740             auto innerPattern = parseDestructuringPattern(context, kind, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     790            auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    741791            if (kind == DestructureToExpressions && !innerPattern)
    742792                return 0;
     
    775825                next();
    776826                if (consume(COLON))
    777                     innerPattern = parseDestructuringPattern(context, kind, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     827                    innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    778828                else
    779                     innerPattern = createBindingPattern(context, kind, *propertyName, depth + 1, identifierToken, bindingContext, duplicateIdentifier);
     829                    innerPattern = createBindingPattern(context, kind, exportType, *propertyName, depth + 1, identifierToken, bindingContext, duplicateIdentifier);
    780830            } else {
    781831                JSTokenType tokenType = m_token.m_type;
     
    808858                    failWithMessage("Expected a ':' prior to a named destructuring property");
    809859                }
    810                 innerPattern = parseDestructuringPattern(context, kind, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     860                innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    811861            }
    812862            if (kind == DestructureToExpressions && !innerPattern)
     
    833883        }
    834884        failIfTrue(match(LET) && (kind == DestructureToLet || kind == DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
    835         pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token, bindingContext, duplicateIdentifier);
     885        pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, depth, m_token, bindingContext, duplicateIdentifier);
    836886        next();
    837887        break;
     
    914964        else
    915965            RELEASE_ASSERT_NOT_REACHED();
    916         decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, forLoopConstDoesNotHaveInitializer);
     966        decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
    917967        m_allowsIn = true;
    918968        propagateError();
     
    14581508    const Identifier* duplicateParameter = nullptr;
    14591509    bool hasDestructuringPattern = false;
    1460     auto parameter = parseDestructuringPattern(context, DestructureToParameters, &duplicateParameter, &hasDestructuringPattern);
     1510    auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
    14611511    failIfFalse(parameter, "Cannot parse parameter pattern");
    14621512    auto defaultValue = parseDefaultValueForDestructuringPattern(context);
     
    14661516    parameterCount++;
    14671517    while (consume(COMMA)) {
    1468         parameter = parseDestructuringPattern(context, DestructureToParameters, &duplicateParameter, &hasDestructuringPattern);
     1518        parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
    14691519        failIfFalse(parameter, "Cannot parse parameter pattern");
    14701520        defaultValue = parseDefaultValueForDestructuringPattern(context);
     
    15471597            } else {
    15481598                functionInfo.parameterCount = 1;
    1549                 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
     1599                auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported);
    15501600                failIfFalse(parameter, "Cannot parse parameter pattern");
    15511601                context.appendParameter(parameterList, parameter, 0);
     
    15671617        failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
    15681618        const Identifier* duplicateParameter = nullptr;
    1569         auto parameter = parseDestructuringPattern(context, DestructureToParameters, &duplicateParameter);
     1619        auto parameter = parseDestructuringPattern(context, DestructureToParameters, ExportType::NotExported, &duplicateParameter);
    15701620        failIfFalse(parameter, "setter functions must have one parameter");
    15711621        auto defaultValue = parseDefaultValueForDestructuringPattern(context);
     
    17961846
    17971847template <typename LexerType>
    1798 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
     1848template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType)
    17991849{
    18001850    ASSERT(match(FUNCTION));
     
    18071857    failIfFalse(functionInfo.name, "Function statements must have a name");
    18081858    failIfTrueIfStrict(declareVariable(functionInfo.name) & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
     1859    semanticFailIfTrue(exportType == ExportType::Exported && !currentScope()->moduleScopeData().exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
    18091860    return context.createFuncDeclStatement(location, functionInfo);
    18101861}
     
    18121863#if ENABLE(ES6_CLASS_SYNTAX)
    18131864template <typename LexerType>
    1814 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context)
     1865template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType)
    18151866{
    18161867    ASSERT(match(CLASSTOKEN));
     
    18261877    if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
    18271878        internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
     1879    semanticFailIfTrue(exportType == ExportType::Exported && !currentScope()->moduleScopeData().exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
    18281880
    18291881    JSTextPosition classEnd = lastTokenEndPosition();
     
    21472199
    21482200    return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
     2201}
     2202
     2203template <typename LexerType>
     2204template <class TreeBuilder> typename TreeBuilder::ModuleSpecifier Parser<LexerType>::parseModuleSpecifier(TreeBuilder& context)
     2205{
     2206    // ModuleSpecifier represents the module name imported by the script.
     2207    // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
     2208    // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
     2209    JSTokenLocation specifierLocation(tokenLocation());
     2210    failIfFalse(match(STRING), "Imported modules names must be string literals");
     2211    const Identifier* moduleName = m_token.m_data.ident;
     2212    next();
     2213    return context.createModuleSpecifier(specifierLocation, *moduleName);
     2214}
     2215
     2216template <typename LexerType>
     2217template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
     2218{
     2219    // Produced node is the item of the ImportClause.
     2220    // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
     2221    // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
     2222    JSTokenLocation specifierLocation(tokenLocation());
     2223    JSToken localNameToken;
     2224    const Identifier* importedName = nullptr;
     2225    const Identifier* localName = nullptr;
     2226
     2227    switch (specifierType) {
     2228    case ImportSpecifierType::NamespaceImport: {
     2229        // NameSpaceImport :
     2230        // * as ImportedBinding
     2231        // e.g.
     2232        //     * as namespace
     2233        ASSERT(match(TIMES));
     2234        importedName = &m_vm->propertyNames->timesIdentifier;
     2235        next();
     2236
     2237        failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
     2238        next();
     2239
     2240        matchOrFail(IDENT, "Expected a variable name for the import declaration");
     2241        localNameToken = m_token;
     2242        localName = m_token.m_data.ident;
     2243        next();
     2244        break;
     2245    }
     2246
     2247    case ImportSpecifierType::NamedImport: {
     2248        // ImportSpecifier :
     2249        // ImportedBinding
     2250        // IdentifierName as ImportedBinding
     2251        // e.g.
     2252        //     A
     2253        //     A as B
     2254        ASSERT(matchIdentifierOrKeyword());
     2255        localNameToken = m_token;
     2256        localName = m_token.m_data.ident;
     2257        importedName = localName;
     2258        next();
     2259
     2260        if (matchContextualKeyword(m_vm->propertyNames->as)) {
     2261            next();
     2262            matchOrFail(IDENT, "Expected a variable name for the import declaration");
     2263            localNameToken = m_token;
     2264            localName = m_token.m_data.ident;
     2265            next();
     2266        }
     2267        break;
     2268    }
     2269
     2270    case ImportSpecifierType::DefaultImport: {
     2271        // ImportedDefaultBinding :
     2272        // ImportedBinding
     2273        ASSERT(match(IDENT));
     2274        localNameToken = m_token;
     2275        localName = m_token.m_data.ident;
     2276        importedName = &m_vm->propertyNames->defaultKeyword;
     2277        next();
     2278        break;
     2279    }
     2280    }
     2281
     2282    semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
     2283    DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration);
     2284    if (declarationResult != DeclarationResult::Valid) {
     2285        failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
     2286        if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
     2287            internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
     2288    }
     2289
     2290    return context.createImportSpecifier(specifierLocation, *importedName, *localName);
     2291}
     2292
     2293template <typename LexerType>
     2294template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
     2295{
     2296    // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
     2297    ASSERT(match(IMPORT));
     2298    JSTokenLocation importLocation(tokenLocation());
     2299    next();
     2300
     2301    auto specifierList = context.createImportSpecifierList();
     2302
     2303    if (match(STRING)) {
     2304        // import ModuleSpecifier ;
     2305        auto moduleSpecifier = parseModuleSpecifier(context);
     2306        failIfFalse(moduleSpecifier, "Cannot parse the module name");
     2307        failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
     2308        return context.createImportDeclaration(importLocation, specifierList, moduleSpecifier);
     2309    }
     2310
     2311    bool isFinishedParsingImport = false;
     2312    if (match(IDENT)) {
     2313        // ImportedDefaultBinding :
     2314        // ImportedBinding
     2315        auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
     2316        failIfFalse(specifier, "Cannot parse the default import");
     2317        context.appendImportSpecifier(specifierList, specifier);
     2318        if (match(COMMA))
     2319            next();
     2320        else
     2321            isFinishedParsingImport = true;
     2322    }
     2323
     2324    if (!isFinishedParsingImport) {
     2325        if (match(TIMES)) {
     2326            // import NameSpaceImport FromClause ;
     2327            auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
     2328            failIfFalse(specifier, "Cannot parse the namespace import");
     2329            context.appendImportSpecifier(specifierList, specifier);
     2330        } else if (match(OPENBRACE)) {
     2331            // NamedImports :
     2332            // { }
     2333            // { ImportsList }
     2334            // { ImportsList , }
     2335            next();
     2336
     2337            while (!match(CLOSEBRACE)) {
     2338                failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
     2339                auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
     2340                failIfFalse(specifier, "Cannot parse the named import");
     2341                context.appendImportSpecifier(specifierList, specifier);
     2342                if (!consume(COMMA))
     2343                    break;
     2344            }
     2345            handleProductionOrFail(CLOSEBRACE, "}", "end", "import list");
     2346        } else
     2347            failWithMessage("Expected namespace import or import list");
     2348    }
     2349
     2350    // FromClause :
     2351    // from ModuleSpecifier
     2352
     2353    failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
     2354    next();
     2355
     2356    auto moduleSpecifier = parseModuleSpecifier(context);
     2357    failIfFalse(moduleSpecifier, "Cannot parse the module name");
     2358    failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
     2359
     2360    return context.createImportDeclaration(importLocation, specifierList, moduleSpecifier);
     2361}
     2362
     2363template <typename LexerType>
     2364template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings)
     2365{
     2366    // ExportSpecifier :
     2367    // IdentifierName
     2368    // IdentifierName as IdentifierName
     2369    // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
     2370    ASSERT(matchIdentifierOrKeyword());
     2371    JSTokenLocation specifierLocation(tokenLocation());
     2372    if (m_token.m_type & KeywordTokenFlag)
     2373        hasKeywordForLocalBindings = true;
     2374    const Identifier* localName = m_token.m_data.ident;
     2375    const Identifier* exportedName = localName;
     2376    next();
     2377
     2378    if (matchContextualKeyword(m_vm->propertyNames->as)) {
     2379        next();
     2380        failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
     2381        exportedName = m_token.m_data.ident;
     2382        next();
     2383    }
     2384
     2385    semanticFailIfFalse(currentScope()->moduleScopeData().exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
     2386    maybeLocalNames.append(localName);
     2387    return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
     2388}
     2389
     2390template <typename LexerType>
     2391template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
     2392{
     2393    // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
     2394    ASSERT(match(EXPORT));
     2395    JSTokenLocation exportLocation(tokenLocation());
     2396    next();
     2397
     2398    switch (m_token.m_type) {
     2399    case TIMES: {
     2400        // export * FromClause ;
     2401        next();
     2402
     2403        failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
     2404        next();
     2405        auto moduleSpecifier = parseModuleSpecifier(context);
     2406        failIfFalse(moduleSpecifier, "Cannot parse the 'from' clause");
     2407        failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
     2408        return context.createExportAllDeclaration(exportLocation, moduleSpecifier);
     2409    }
     2410
     2411    case DEFAULT: {
     2412        // export default HoistableDeclaration[Default]
     2413        // export default ClassDeclaration[Default]
     2414        // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
     2415
     2416        next();
     2417
     2418        TreeStatement result = 0;
     2419        bool hasName = false;
     2420        bool isFunctionOrClassDeclaration = false;
     2421        SavePoint savePoint = createSavePoint();
     2422        if (match(FUNCTION)
     2423#if ENABLE(ES6_CLASS_SYNTAX)
     2424                || match(CLASSTOKEN)
     2425#endif
     2426                ) {
     2427            isFunctionOrClassDeclaration = true;
     2428            next();
     2429            // FIXME: When landing ES6 generators, we need to take care of that '*' comes.
     2430            hasName = match(IDENT);
     2431            restoreSavePoint(savePoint);
     2432        }
     2433
     2434        if (hasName) {
     2435            if (match(FUNCTION))
     2436                result = parseFunctionDeclaration(context);
     2437#if ENABLE(ES6_CLASS_SYNTAX)
     2438            else {
     2439                ASSERT(match(CLASSTOKEN));
     2440                result = parseClassDeclaration(context);
     2441            }
     2442#endif
     2443        } else {
     2444            JSTokenLocation location(tokenLocation());
     2445            JSTextPosition start = tokenStartPosition();
     2446            TreeExpression expression = parseAssignmentExpression(context);
     2447            failIfFalse(expression, "Cannot parse expression");
     2448            result = context.createExprStatement(location, expression, start, tokenEndPosition());
     2449            if (!isFunctionOrClassDeclaration)
     2450                failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
     2451        }
     2452        failIfFalse(result, "Cannot parse the declaration");
     2453        semanticFailIfFalse(currentScope()->moduleScopeData().exportName(m_vm->propertyNames->defaultKeyword), "Cannot export 'default' name twice.");
     2454
     2455        return context.createExportDefaultDeclaration(exportLocation, result);
     2456    }
     2457
     2458    case OPENBRACE: {
     2459        // export ExportClause FromClause ;
     2460        // export ExportClause ;
     2461        //
     2462        // ExportClause :
     2463        // { }
     2464        // { ExportsList }
     2465        // { ExportsList , }
     2466        //
     2467        // ExportsList :
     2468        // ExportSpecifier
     2469        // ExportsList , ExportSpecifier
     2470
     2471        next();
     2472
     2473        auto specifierList = context.createExportSpecifierList();
     2474        Vector<const Identifier*> maybeLocalNames;
     2475
     2476        bool hasKeywordForLocalBindings = false;
     2477        while (!match(CLOSEBRACE)) {
     2478            failIfFalse(matchIdentifierOrKeyword(), "Expected a variable name for the export declaration");
     2479            auto specifier = parseExportSpecifier(context, maybeLocalNames, hasKeywordForLocalBindings);
     2480            failIfFalse(specifier, "Cannot parse the named export");
     2481            context.appendExportSpecifier(specifierList, specifier);
     2482            if (!consume(COMMA))
     2483                break;
     2484        }
     2485        handleProductionOrFail(CLOSEBRACE, "}", "end", "export list");
     2486
     2487        typename TreeBuilder::ModuleSpecifier moduleSpecifier = 0;
     2488        if (matchContextualKeyword(m_vm->propertyNames->from)) {
     2489            next();
     2490            moduleSpecifier = parseModuleSpecifier(context);
     2491            failIfFalse(moduleSpecifier, "Cannot parse the 'from' clause");
     2492        }
     2493        failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
     2494
     2495        if (!moduleSpecifier) {
     2496            semanticFailIfTrue(hasKeywordForLocalBindings, "Cannot use keyword as exported variable name");
     2497            // Since this export declaration does not have module specifier part, it exports the local bindings.
     2498            // While the export declaration with module specifier does not have any effect on the current module's scope,
     2499            // the export named declaration without module specifier references the the local binding names.
     2500            // For example,
     2501            //   export { A, B, C as D } from "mod"
     2502            // does not have effect on the current module's scope. But,
     2503            //   export { A, B, C as D }
     2504            // will reference the current module's bindings.
     2505            for (const Identifier* localName : maybeLocalNames) {
     2506                currentScope()->useVariable(localName, m_vm->propertyNames->eval == *localName);
     2507                currentScope()->moduleScopeData().exportBinding(*localName);
     2508            }
     2509        }
     2510
     2511        return context.createExportNamedDeclaration(exportLocation, specifierList, moduleSpecifier);
     2512    }
     2513
     2514    default: {
     2515        // export VariableStatement
     2516        // export Declaration
     2517        TreeStatement result = 0;
     2518        switch (m_token.m_type) {
     2519        case VAR:
     2520            result = parseVariableDeclaration(context, DeclarationType::VarDeclaration, ExportType::Exported);
     2521            break;
     2522
     2523        case CONSTTOKEN:
     2524            result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration, ExportType::Exported);
     2525            break;
     2526
     2527        case LET:
     2528            result = parseVariableDeclaration(context, DeclarationType::LetDeclaration, ExportType::Exported);
     2529            break;
     2530
     2531        case FUNCTION:
     2532            result = parseFunctionDeclaration(context, ExportType::Exported);
     2533            break;
     2534
     2535#if ENABLE(ES6_CLASS_SYNTAX)
     2536        case CLASSTOKEN:
     2537            result = parseClassDeclaration(context, ExportType::Exported);
     2538            break;
     2539#endif
     2540
     2541        default:
     2542            failWithMessage("Expected either a declaration or a variable statement");
     2543            break;
     2544        }
     2545        failIfFalse(result, "Cannot parse the declaration");
     2546        return context.createExportLocalDeclaration(exportLocation, result);
     2547    }
     2548    }
     2549
     2550    RELEASE_ASSERT_NOT_REACHED();
     2551    return 0;
    21492552}
    21502553
     
    29273330
    29283331    if (baseIsSuper) {
     3332        semanticFailIfFalse(currentScope()->isFunction(), "super is only valid inside functions");
    29293333        base = context.createSuperExpr(location);
    29303334        next();
  • TabularUnified trunk/Source/JavaScriptCore/parser/Parser.h

    r187351 r187890  
    128128    return isEval(vm, ident) || isArguments(vm, ident);
    129129}
     130ALWAYS_INLINE static bool isIdentifierOrKeyword(const JSToken& token)
     131{
     132    return token.m_type == IDENT || token.m_type & KeywordTokenFlag;
     133}
     134
     135class ModuleScopeData : public RefCounted<ModuleScopeData> {
     136public:
     137    static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); }
     138
     139    const IdentifierSet& exportedBindings() const { return m_exportedBindings; }
     140
     141    bool exportName(const Identifier& exportedName)
     142    {
     143        return m_exportedNames.add(exportedName.impl()).isNewEntry;
     144    }
     145
     146    void exportBinding(const Identifier& localName)
     147    {
     148        m_exportedBindings.add(localName.impl());
     149    }
     150
     151private:
     152    IdentifierSet m_exportedNames { };
     153    IdentifierSet m_exportedBindings { };
     154};
    130155
    131156struct Scope {
     
    165190        , m_loopDepth(rhs.m_loopDepth)
    166191        , m_switchDepth(rhs.m_switchDepth)
     192        , m_moduleScopeData(rhs.m_moduleScopeData)
    167193    {
    168194        if (rhs.m_labels) {
     
    216242    }
    217243
     244    void setIsModule()
     245    {
     246        m_moduleScopeData = ModuleScopeData::create();
     247    }
     248
    218249    bool isFunction() const { return m_isFunction; }
    219250    bool isFunctionBoundary() const { return m_isFunctionBoundary; }
     
    235266
    236267        return m_lexicalVariables;
     268    }
     269
     270    ModuleScopeData& moduleScopeData() const
     271    {
     272        ASSERT(m_moduleScopeData);
     273        return *m_moduleScopeData;
    237274    }
    238275
     
    533570    IdentifierSet m_closedVariableCandidates;
    534571    IdentifierSet m_writtenVariables;
     572    RefPtr<ModuleScopeData> m_moduleScopeData { };
    535573};
    536574
     
    848886    }
    849887   
    850     ALWAYS_INLINE bool isofToken()
    851     {
    852         return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of;
     888    ALWAYS_INLINE bool matchContextualKeyword(const Identifier& identifier)
     889    {
     890        return m_token.m_type == IDENT && *m_token.m_data.ident == identifier;
     891    }
     892
     893    ALWAYS_INLINE bool matchIdentifierOrKeyword()
     894    {
     895        return isIdentifierOrKeyword(m_token);
    853896    }
    854897   
     
    10081051    template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength);
    10091052    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
     1053    enum class ExportType { Exported, NotExported };
    10101054#if ENABLE(ES6_CLASS_SYNTAX)
    1011     template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&);
     1055    template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported);
    10121056#endif
    1013     template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
    1014     template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType);
     1057    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported);
     1058    template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported);
    10151059    template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
    10161060    template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
     
    10481092    template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, unsigned&);
    10491093    enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
    1050     template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, bool& forLoopConstDoesNotHaveInitializer);
     1094    template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool& forLoopConstDoesNotHaveInitializer);
    10511095    template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&);
    10521096    template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&);
    1053     template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, const Identifier&, int depth, JSToken, AssignmentContext, const Identifier** duplicateIdentifier);
    1054     template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
     1097    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, int depth, JSToken, AssignmentContext, const Identifier** duplicateIdentifier);
     1098    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
    10551099    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext);
    10561100    template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDestructuringPattern(TreeBuilder&);
     1101    template <class TreeBuilder> TreeSourceElements parseModuleSourceElements(TreeBuilder&);
     1102    enum class ImportSpecifierType { NamespaceImport, NamedImport, DefaultImport };
     1103    template <class TreeBuilder> typename TreeBuilder::ImportSpecifier parseImportClauseItem(TreeBuilder&, ImportSpecifierType);
     1104    template <class TreeBuilder> typename TreeBuilder::ModuleSpecifier parseModuleSpecifier(TreeBuilder&);
     1105    template <class TreeBuilder> TreeStatement parseImportDeclaration(TreeBuilder&);
     1106    template <class TreeBuilder> typename TreeBuilder::ExportSpecifier parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings);
     1107    template <class TreeBuilder> TreeStatement parseExportDeclaration(TreeBuilder&);
    10571108
    10581109    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionParseType);
     
    11821233    CodeFeatures m_features;
    11831234    int m_numConstants;
     1235    JSParserCodeType m_codeType;
    11841236   
    11851237    struct DepthManager {
  • TabularUnified trunk/Source/JavaScriptCore/parser/ParserModes.h

    r186959 r187890  
    3434enum class JSParserStrictMode { NotStrict, Strict };
    3535enum class JSParserBuiltinMode { NotBuiltin, Builtin };
    36 enum class JSParserCodeType { Program, Function };
     36enum class JSParserCodeType { Program, Function, Module };
    3737
    3838enum class ConstructorKind { None, Base, Derived };
  • TabularUnified trunk/Source/JavaScriptCore/parser/ParserTokens.h

    r187763 r187890  
    7777    DEBUGGER,
    7878    ELSE,
     79    IMPORT,
     80    EXPORT,
    7981#if ENABLE(ES6_CLASS_SYNTAX)
    8082    CLASSTOKEN,
  • TabularUnified trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r187760 r187890  
    8484        TemplateStringResult, TemplateStringListResult,
    8585        TemplateExpressionListResult, TemplateExpr,
    86         TaggedTemplateExpr
     86        TaggedTemplateExpr,
     87        ModuleSpecifierResult,
     88        ImportSpecifierResult, ImportSpecifierListResult,
     89        ExportSpecifierResult, ExportSpecifierListResult
    8790    };
    8891    typedef int ExpressionType;
     
    125128    typedef int ClassExpression;
    126129#endif
     130    typedef int ModuleSpecifier;
     131    typedef int ImportSpecifier;
     132    typedef int ImportSpecifierList;
     133    typedef int ExportSpecifier;
     134    typedef int ExportSpecifierList;
    127135    typedef int Statement;
    128136    typedef int ClauseList;
     
    252260    int createDebugger(const JSTokenLocation&, int, int) { return StatementResult; }
    253261    int createConstStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
     262    int createModuleSpecifier(const JSTokenLocation&, const Identifier&) { return ModuleSpecifierResult; }
     263    ImportSpecifier createImportSpecifier(const JSTokenLocation&, const Identifier&, const Identifier&) { return ImportSpecifierResult; }
     264    ImportSpecifierList createImportSpecifierList() { return ImportSpecifierListResult; }
     265    void appendImportSpecifier(ImportSpecifierList, ImportSpecifier) { }
     266    int createImportDeclaration(const JSTokenLocation&, ImportSpecifierList, ModuleSpecifier) { return StatementResult; }
     267    int createExportAllDeclaration(const JSTokenLocation&, ModuleSpecifier) { return StatementResult; }
     268    int createExportDefaultDeclaration(const JSTokenLocation&, int) { return StatementResult; }
     269    int createExportLocalDeclaration(const JSTokenLocation&, int) { return StatementResult; }
     270    int createExportNamedDeclaration(const JSTokenLocation&, ExportSpecifierList, ModuleSpecifier) { return StatementResult; }
     271    ExportSpecifier createExportSpecifier(const JSTokenLocation&, const Identifier&, const Identifier&) { return ExportSpecifierResult; }
     272    ExportSpecifierList createExportSpecifierList() { return ExportSpecifierListResult; }
     273    void appendExportSpecifier(ExportSpecifierList, ExportSpecifier) { }
     274
    254275    int appendConstDecl(const JSTokenLocation&, int, const Identifier*, int) { return StatementResult; }
    255276    Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo<SyntaxChecker>&, SuperBinding)
  • TabularUnified trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp

    r184828 r187890  
    4040    , thisIdentifier(Identifier::fromString(vm, "this"))
    4141    , useStrictIdentifier(Identifier::fromString(vm, "use strict"))
     42    , timesIdentifier(Identifier::fromString(vm, "*"))
    4243    , m_builtinNames(new BuiltinNames(vm, this))
    4344    JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(INITIALIZE_KEYWORD)
  • TabularUnified trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r187575 r187890  
    7373    macro(anonymous) \
    7474    macro(arguments) \
     75    macro(as) \
    7576    macro(assign) \
    7677    macro(back) \
     
    113114    macro(forEach) \
    114115    macro(forward) \
     116    macro(from) \
    115117    macro(fromCharCode) \
    116118    macro(get) \
     
    320322        const Identifier thisIdentifier;
    321323        const Identifier useStrictIdentifier;
     324        const Identifier timesIdentifier;
    322325    private:
    323326        std::unique_ptr<BuiltinNames> m_builtinNames;
  • TabularUnified trunk/Source/JavaScriptCore/runtime/Completion.cpp

    r186959 r187890  
    6262}
    6363
     64bool checkModuleSyntax(VM& vm, const SourceCode& source, ParserError& error)
     65{
     66    JSLockHolder lock(vm);
     67    RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
     68    return !!parse<ModuleProgramNode>(
     69        &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin,
     70        JSParserStrictMode::Strict, JSParserCodeType::Module, error);
     71}
     72
    6473JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, NakedPtr<Exception>& returnedException)
    6574{
  • TabularUnified trunk/Source/JavaScriptCore/runtime/Completion.h

    r185608 r187890  
    3838JS_EXPORT_PRIVATE bool checkSyntax(VM&, const SourceCode&, ParserError&);
    3939JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0);
     40JS_EXPORT_PRIVATE bool checkModuleSyntax(VM&, const SourceCode&, ParserError&);
    4041JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, const SourceCode&, JSValue thisValue, NakedPtr<Exception>& returnedException);
    4142inline JSValue evaluate(ExecState* exec, const SourceCode& sourceCode, JSValue thisValue = JSValue())
  • TabularUnified trunk/Source/JavaScriptCore/tests/stress/tagged-templates-syntax.js

    r184337 r187890  
    6767testSyntax("(class extends Hello { constructor() { super()`${tag}${tag}` } })");
    6868
    69 testSyntaxError("super`Hello${tag}`", "SyntaxError: Cannot use super as tag for tagged templates.");
     69testSyntaxError("super`Hello${tag}`", "SyntaxError: super is only valid inside functions.");
    7070testSyntaxError("(class { say() { super`Hello${tag}` } })", "SyntaxError: Cannot use super as tag for tagged templates.");
Note: See TracChangeset for help on using the changeset viewer.