Ignore:
Timestamp:
Jul 31, 2016, 12:04:57 AM (9 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Module binding can be exported by multiple names
https://bugs.webkit.org/show_bug.cgi?id=160343

Reviewed by Saam Barati.

ES6 Module can export the same local binding by using multiple names.
For example,

`
var value = 42;

export { value };
export { value as value2 };
`

Currently, we only allowed one local binding to be exported with one name. So, in the above case,
the local binding "value" is exported as "value2" and "value" name is not exported. This is wrong.

To fix this issue, we collect the correspondence (local name => exported name) to the local bindings
in the parser. Previously, we only maintained the exported local bindings in the parser. And utilize
this information when creating the export entries in ModuleAnalyzer.

And this patch also moves ModuleScopeData from the Scope object to the Parser class since exported
names should be managed per-module, not per-scope.

This change fixes several test262 failures.

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

  • parser/ModuleAnalyzer.h:
  • parser/ModuleScopeData.h: Copied from Source/JavaScriptCore/parser/ModuleAnalyzer.h.

(JSC::ModuleScopeData::create):
(JSC::ModuleScopeData::exportedBindings):
(JSC::ModuleScopeData::exportName):
(JSC::ModuleScopeData::exportBinding):

  • parser/Nodes.cpp:

(JSC::ProgramNode::ProgramNode):
(JSC::ModuleProgramNode::ModuleProgramNode):
(JSC::EvalNode::EvalNode):
(JSC::FunctionNode::FunctionNode):

  • parser/Nodes.h:

(JSC::ModuleProgramNode::moduleScopeData):

  • parser/NodesAnalyzeModule.cpp:

(JSC::ExportDefaultDeclarationNode::analyzeModule):
(JSC::ExportNamedDeclarationNode::analyzeModule): Deleted.

  • parser/Parser.cpp:

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

  • parser/Parser.h:

(JSC::Parser::exportName):
(JSC::Parser<LexerType>::parse):
(JSC::ModuleScopeData::create): Deleted.
(JSC::ModuleScopeData::exportedBindings): Deleted.
(JSC::ModuleScopeData::exportName): Deleted.
(JSC::ModuleScopeData::exportBinding): Deleted.
(JSC::Scope::Scope): Deleted.
(JSC::Scope::setSourceParseMode): Deleted.
(JSC::Scope::moduleScopeData): Deleted.
(JSC::Scope::setIsModule): Deleted.

  • tests/modules/aliased-names.js: Added.
  • tests/modules/aliased-names/main.js: Added.

(change):

  • tests/stress/modules-syntax-error-with-names.js:

(export.Cocoa):
(SyntaxError.Cannot.export.a.duplicate.name):

  • tests/test262.yaml:
File:
1 copied

Legend:

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

    r203952 r203953  
    11/*
    22 * Copyright (C) 2015 Apple Inc. All rights reserved.
     3 * Copyright (C) 2016 Yusuke Suzuki <[email protected]>
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    2425 */
    2526
    26 #ifndef ModuleAnalyzer_h
    27 #define ModuleAnalyzer_h
     27#pragma once
    2828
    29 #include "Nodes.h"
     29#include "Identifier.h"
     30#include <wtf/RefPtr.h>
    3031
    3132namespace JSC {
    3233
    33 class JSModuleRecord;
    34 class SourceCode;
     34class ModuleScopeData : public RefCounted<ModuleScopeData> {
     35WTF_MAKE_NONCOPYABLE(ModuleScopeData);
     36WTF_MAKE_FAST_ALLOCATED;
     37public:
     38    typedef HashMap<RefPtr<UniquedStringImpl>, IdentifierSet, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
    3539
    36 class ModuleAnalyzer {
    37     WTF_MAKE_NONCOPYABLE(ModuleAnalyzer);
    38 public:
    39     ModuleAnalyzer(ExecState*, const Identifier& moduleKey, const SourceCode&, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables);
     40    static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); }
    4041
    41     JSModuleRecord* analyze(ModuleProgramNode&);
     42    const IdentifierAliasMap& exportedBindings() const { return m_exportedBindings; }
    4243
    43     VM& vm() { return *m_vm; }
     44    bool exportName(const Identifier& exportedName)
     45    {
     46        return m_exportedNames.add(exportedName.impl()).isNewEntry;
     47    }
    4448
    45     JSModuleRecord* moduleRecord() { return m_moduleRecord.get(); }
     49    void exportBinding(const Identifier& localName, const Identifier& exportedName)
     50    {
     51        m_exportedBindings.add(localName.impl(), IdentifierSet()).iterator->value.add(exportedName.impl());
     52    }
    4653
    47     void declareExportAlias(const Identifier& localName, const Identifier& exportName);
     54    void exportBinding(const Identifier& localName)
     55    {
     56        exportBinding(localName, localName);
     57    }
    4858
    4959private:
    50     typedef HashMap<RefPtr<UniquedStringImpl>, Identifier, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
     60    ModuleScopeData() = default;
    5161
    52     void exportVariable(const RefPtr<UniquedStringImpl>&, const VariableEnvironmentEntry&);
    53 
    54     Identifier exportedBinding(const RefPtr<UniquedStringImpl>& ident);
    55 
    56     VM* m_vm;
    57     Strong<JSModuleRecord> m_moduleRecord;
    58     IdentifierAliasMap m_aliasMap;
     62    IdentifierSet m_exportedNames { };
     63    IdentifierAliasMap m_exportedBindings { };
    5964};
    6065
    61 } // namespace JSC
    62 
    63 #endif // ModuleAnalyzer_h
     66} // namespace
Note: See TracChangeset for help on using the changeset viewer.