Ignore:
Timestamp:
Aug 12, 2015, 1:38:45 PM (10 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Add ES6 Modules preparsing phase to collect the dependencies
https://bugs.webkit.org/show_bug.cgi?id=147353

Reviewed by Geoffrey Garen.

This patch implements ModuleRecord and ModuleAnalyzer.
ModuleAnalyzer analyzes the produced AST from the parser.
By collaborating with the parser, ModuleAnalyzer collects the information
that is necessary to request the loading for the dependent modules and
construct module's environment and namespace object before executing the actual
module body.

In the parser, we annotate which variable is imported binding and which variable
is exported from the current module. This information is leveraged in the ModuleAnalyzer
to categorize the export entries.

To preparse the modules in the parser, we just add the new flag ModuleParseMode
instead of introducing a new TreeContext type. This is because only 2 users use the
parseModuleSourceElements; preparser and actual compiler. Adding the flag is simple
enough to switch the context to the SyntaxChecker when parsing the non-module related
statement in the preparsing phase.

To demonstrate the module analyzer, we added the new option dumpModuleRecord option
into the JSC shell. By specifying this, the result of analysis is dumped when the module
is parsed and analyzed.

(JSC::ASTBuilder::createExportDefaultDeclaration):

  • parser/ModuleAnalyzer.cpp: Added.

(JSC::ModuleAnalyzer::ModuleAnalyzer):
(JSC::ModuleAnalyzer::exportedBinding):
(JSC::ModuleAnalyzer::declareExportAlias):
(JSC::ModuleAnalyzer::exportVariable):
(JSC::ModuleAnalyzer::analyze):

  • parser/ModuleAnalyzer.h: Added.

(JSC::ModuleAnalyzer::vm):
(JSC::ModuleAnalyzer::moduleRecord):

  • parser/ModuleRecord.cpp: Added.

(JSC::printableName):
(JSC::ModuleRecord::dump):

  • parser/ModuleRecord.h: Added.

(JSC::ModuleRecord::ImportEntry::isNamespace):
(JSC::ModuleRecord::create):
(JSC::ModuleRecord::appendRequestedModule):
(JSC::ModuleRecord::addImportEntry):
(JSC::ModuleRecord::addExportEntry):
(JSC::ModuleRecord::addStarExportEntry):

  • parser/NodeConstructors.h:

(JSC::ModuleDeclarationNode::ModuleDeclarationNode):
(JSC::ImportDeclarationNode::ImportDeclarationNode):
(JSC::ExportAllDeclarationNode::ExportAllDeclarationNode):
(JSC::ExportDefaultDeclarationNode::ExportDefaultDeclarationNode):
(JSC::ExportLocalDeclarationNode::ExportLocalDeclarationNode):
(JSC::ExportNamedDeclarationNode::ExportNamedDeclarationNode):

  • parser/Nodes.h:

(JSC::ExportDefaultDeclarationNode::localName):

  • parser/NodesAnalyzeModule.cpp: Added.

(JSC::ScopeNode::analyzeModule):
(JSC::SourceElements::analyzeModule):
(JSC::ImportDeclarationNode::analyzeModule):
(JSC::ExportAllDeclarationNode::analyzeModule):
(JSC::ExportDefaultDeclarationNode::analyzeModule):
(JSC::ExportLocalDeclarationNode::analyzeModule):
(JSC::ExportNamedDeclarationNode::analyzeModule):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseModuleSourceElements):
(JSC::Parser<LexerType>::parseVariableDeclarationList):
(JSC::Parser<LexerType>::createBindingPattern):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClassDeclaration):
(JSC::Parser<LexerType>::parseImportClauseItem):
(JSC::Parser<LexerType>::parseExportSpecifier):
(JSC::Parser<LexerType>::parseExportDeclaration):

  • parser/Parser.h:

(JSC::Scope::lexicalVariables):
(JSC::Scope::declareLexicalVariable):
(JSC::Parser::declareVariable):
(JSC::Parser::exportName):
(JSC::Parser<LexerType>::parse):
(JSC::parse):

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

(JSC::SyntaxChecker::createExportDefaultDeclaration):

  • parser/VariableEnvironment.cpp:

(JSC::VariableEnvironment::markVariableAsImported):
(JSC::VariableEnvironment::markVariableAsExported):

  • parser/VariableEnvironment.h:

(JSC::VariableEnvironmentEntry::isExported):
(JSC::VariableEnvironmentEntry::isImported):
(JSC::VariableEnvironmentEntry::setIsExported):
(JSC::VariableEnvironmentEntry::setIsImported):

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

(JSC::checkModuleSyntax):

  • runtime/Options.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r188219 r188355  
    9999};
    100100
     101enum class DeclarationImportType {
     102    Imported,
     103    NotImported
     104};
     105
    101106enum DeclarationResult {
    102107    Valid = 0,
     
    258263
    259264    VariableEnvironment& declaredVariables() { return m_declaredVariables; }
     265    VariableEnvironment& lexicalVariables() { return m_lexicalVariables; }
    260266    VariableEnvironment& finalizeLexicalEnvironment()
    261267    {
     
    316322    }
    317323
    318     DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant)
     324    DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant, DeclarationImportType importType = DeclarationImportType::NotImported)
    319325    {
    320326        ASSERT(m_allowsLexicalDeclarations);
     
    327333        else
    328334            addResult.iterator->value.setIsLet();
     335
     336        if (importType == DeclarationImportType::Imported)
     337            addResult.iterator->value.setIsImported();
    329338
    330339        if (!addResult.isNewEntry)
     
    612621
    613622    template <class ParsedNode>
    614     std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, FunctionParseMode);
     623    std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, FunctionParseMode, ModuleParseMode);
    615624
    616625    JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
     
    770779    }
    771780   
    772     DeclarationResultMask declareVariable(const Identifier* ident, DeclarationType type = DeclarationType::VarDeclaration)
     781    DeclarationResultMask declareVariable(const Identifier* ident, DeclarationType type = DeclarationType::VarDeclaration, DeclarationImportType importType = DeclarationImportType::NotImported)
    773782    {
    774783        unsigned i = m_scopeStack.size() - 1;
     
    795804        }
    796805
    797         return m_scopeStack[i].declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration);
     806        return m_scopeStack[i].declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType);
    798807    }
    799808   
     
    826835    }
    827836
     837    bool exportName(const Identifier& ident)
     838    {
     839        ASSERT(currentScope().index() == 0);
     840        return currentScope()->moduleScopeData().exportName(ident);
     841    }
     842
    828843    ScopeStack m_scopeStack;
    829844   
     
    834849
    835850    Parser();
    836     String parseInner(const Identifier&, FunctionParseMode);
     851    String parseInner(const Identifier&, FunctionParseMode, ModuleParseMode);
    837852
    838853    void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&, VariableEnvironment&, CodeFeatures, int, const Vector<RefPtr<UniquedStringImpl>>&&);
     
    10991114    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext);
    11001115    template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDestructuringPattern(TreeBuilder&);
    1101     template <class TreeBuilder> TreeSourceElements parseModuleSourceElements(TreeBuilder&);
     1116    template <class TreeBuilder> TreeSourceElements parseModuleSourceElements(TreeBuilder&, ModuleParseMode);
    11021117    enum class ImportSpecifierType { NamespaceImport, NamedImport, DefaultImport };
    11031118    template <class TreeBuilder> typename TreeBuilder::ImportSpecifier parseImportClauseItem(TreeBuilder&, ImportSpecifierType);
     
    12561271template <typename LexerType>
    12571272template <class ParsedNode>
    1258 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, FunctionParseMode parseMode)
     1273std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, FunctionParseMode parseMode, ModuleParseMode moduleParseMode)
    12591274{
    12601275    int errLine;
     
    12731288    unsigned startColumn = m_source->startColumn() - 1;
    12741289
    1275     String parseError = parseInner(calleeName, parseMode);
     1290    String parseError = parseInner(calleeName, parseMode, moduleParseMode);
    12761291
    12771292    int lineNumber = m_lexer->lineNumber();
     
    13411356    JSParserStrictMode strictMode, JSParserCodeType codeType,
    13421357    ParserError& error, JSTextPosition* positionBeforeLastNewline = nullptr,
    1343     FunctionParseMode parseMode = NotAFunctionMode, ConstructorKind defaultConstructorKind = ConstructorKind::None,
    1344     ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded)
     1358    FunctionParseMode parseMode = NotAFunctionMode, ConstructorKind defaultConstructorKind = ConstructorKind::None,
     1359    ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded,
     1360    ModuleParseMode moduleParseMode = ModuleParseMode::Analyze)
    13451361{
    13461362    SamplingRegion samplingRegion("Parsing");
     
    13491365    if (source.provider()->source().is8Bit()) {
    13501366        Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, codeType, defaultConstructorKind, thisTDZMode);
    1351         std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode);
     1367        std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode, moduleParseMode);
    13521368        if (positionBeforeLastNewline)
    13531369            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     
    13621378    ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string");
    13631379    Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, codeType, defaultConstructorKind, thisTDZMode);
    1364     std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode);
     1380    std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, name, parseMode, moduleParseMode);
    13651381    if (positionBeforeLastNewline)
    13661382        *positionBeforeLastNewline = parser.positionBeforeLastNewline();
Note: See TracChangeset for help on using the changeset viewer.