Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (203952 => 203953)
--- trunk/Source/_javascript_Core/ChangeLog 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-07-31 07:04:57 UTC (rev 203953)
@@ -1,3 +1,82 @@
+2016-07-31 Yusuke Suzuki <[email protected]>
+
+ [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.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * parser/ModuleAnalyzer.cpp:
+ (JSC::ModuleAnalyzer::exportVariable):
+ (JSC::ModuleAnalyzer::analyze):
+ (JSC::ModuleAnalyzer::exportedBinding): Deleted.
+ (JSC::ModuleAnalyzer::declareExportAlias): Deleted.
+ * parser/ModuleAnalyzer.h:
+ * parser/ModuleScopeData.h: Copied from Source/_javascript_Core/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:
+
2016-07-30 Mark Lam <[email protected]>
Assertion failure while setting the length of an ArrayClass array.
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (203952 => 203953)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-07-31 07:04:57 UTC (rev 203953)
@@ -2130,6 +2130,7 @@
FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; };
FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
+ A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */ = {isa = PBXBuildFile; fileRef = 000BEAF0DF604481AF6AB68C /* ModuleScopeData.h */; settings = {ATTRIBUTES = (Private, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -4417,6 +4418,7 @@
FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PingPongStackOverflowTest.h; path = API/tests/PingPongStackOverflowTest.h; sourceTree = "<group>"; };
FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
+ 000BEAF0DF604481AF6AB68C /* ModuleScopeData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleScopeData.h; path = ModuleScopeData.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -5582,6 +5584,7 @@
A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */,
79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */,
79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */,
+ 000BEAF0DF604481AF6AB68C /* ModuleScopeData.h */,
);
path = parser;
sourceTree = "<group>";
@@ -8229,6 +8232,7 @@
86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
262D85B71C0D650F006ACB61 /* AirFixPartialRegisterStalls.h in Headers */,
86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
+ A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: trunk/Source/_javascript_Core/parser/ModuleAnalyzer.cpp (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/ModuleAnalyzer.cpp 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/ModuleAnalyzer.cpp 2016-07-31 07:04:57 UTC (rev 203953)
@@ -31,6 +31,7 @@
#include "JSCellInlines.h"
#include "JSGlobalObject.h"
#include "JSModuleRecord.h"
+#include "ModuleScopeData.h"
#include "StrongInlines.h"
namespace JSC {
@@ -42,21 +43,8 @@
{
}
-Identifier ModuleAnalyzer::exportedBinding(const RefPtr<UniquedStringImpl>& ident)
+void ModuleAnalyzer::exportVariable(ModuleProgramNode& moduleProgramNode, const RefPtr<UniquedStringImpl>& localName, const VariableEnvironmentEntry& variable)
{
- const auto iterator = m_aliasMap.find(ident);
- if (iterator != m_aliasMap.end())
- return iterator->value;
- return Identifier::fromUid(&vm(), ident.get());
-}
-
-void ModuleAnalyzer::declareExportAlias(const Identifier& localName, const Identifier& exportName)
-{
- m_aliasMap.add(localName.impl(), exportName);
-}
-
-void ModuleAnalyzer::exportVariable(const RefPtr<UniquedStringImpl>& localName, const VariableEnvironmentEntry& variable)
-{
// In the parser, we already marked the variables as Exported and Imported.
// By leveraging this information, we collect the information that is needed
// to construct the module environment.
@@ -74,11 +62,10 @@
if (!variable.isExported())
return;
- const Identifier exportName = exportedBinding(localName);
-
// Exported module local variable.
if (!variable.isImported()) {
- moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(exportName, Identifier::fromUid(m_vm, localName.get())));
+ for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get()))
+ moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(Identifier::fromUid(m_vm, exportName.get()), Identifier::fromUid(m_vm, localName.get())));
return;
}
@@ -89,7 +76,8 @@
//
// Sec 15.2.1.16.1 step 11-a-ii-2-b https://tc39.github.io/ecma262/#sec-parsemodule
// Namespace export is handled as local export since a namespace object binding itself is implemented as a local binding.
- moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(exportName, Identifier::fromUid(m_vm, localName.get())));
+ for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get()))
+ moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createLocal(Identifier::fromUid(m_vm, exportName.get()), Identifier::fromUid(m_vm, localName.get())));
return;
}
@@ -99,7 +87,8 @@
Optional<JSModuleRecord::ImportEntry> optionalImportEntry = moduleRecord()->tryGetImportEntry(localName.get());
ASSERT(optionalImportEntry);
const JSModuleRecord::ImportEntry& importEntry = *optionalImportEntry;
- moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createIndirect(exportName, importEntry.importName, importEntry.moduleRequest));
+ for (auto& exportName : moduleProgramNode.moduleScopeData().exportedBindings().get(localName.get()))
+ moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createIndirect(Identifier::fromUid(m_vm, exportName.get()), importEntry.importName, importEntry.moduleRequest));
}
@@ -148,10 +137,10 @@
//
// export * from "mod"
for (const auto& pair : m_moduleRecord->declaredVariables())
- exportVariable(pair.key, pair.value);
+ exportVariable(moduleProgramNode, pair.key, pair.value);
for (const auto& pair : m_moduleRecord->lexicalVariables())
- exportVariable(pair.key, pair.value);
+ exportVariable(moduleProgramNode, pair.key, pair.value);
if (Options::dumpModuleRecord())
m_moduleRecord->dump();
Modified: trunk/Source/_javascript_Core/parser/ModuleAnalyzer.h (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/ModuleAnalyzer.h 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/ModuleAnalyzer.h 2016-07-31 07:04:57 UTC (rev 203953)
@@ -44,18 +44,11 @@
JSModuleRecord* moduleRecord() { return m_moduleRecord.get(); }
- void declareExportAlias(const Identifier& localName, const Identifier& exportName);
-
private:
- typedef HashMap<RefPtr<UniquedStringImpl>, Identifier, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
+ void exportVariable(ModuleProgramNode&, const RefPtr<UniquedStringImpl>&, const VariableEnvironmentEntry&);
- void exportVariable(const RefPtr<UniquedStringImpl>&, const VariableEnvironmentEntry&);
-
- Identifier exportedBinding(const RefPtr<UniquedStringImpl>& ident);
-
VM* m_vm;
Strong<JSModuleRecord> m_moduleRecord;
- IdentifierAliasMap m_aliasMap;
};
} // namespace JSC
Copied: trunk/Source/_javascript_Core/parser/ModuleScopeData.h (from rev 203952, trunk/Source/_javascript_Core/parser/ModuleAnalyzer.h) (0 => 203953)
--- trunk/Source/_javascript_Core/parser/ModuleScopeData.h (rev 0)
+++ trunk/Source/_javascript_Core/parser/ModuleScopeData.h 2016-07-31 07:04:57 UTC (rev 203953)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Yusuke Suzuki <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Identifier.h"
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+class ModuleScopeData : public RefCounted<ModuleScopeData> {
+WTF_MAKE_NONCOPYABLE(ModuleScopeData);
+WTF_MAKE_FAST_ALLOCATED;
+public:
+ typedef HashMap<RefPtr<UniquedStringImpl>, IdentifierSet, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
+
+ static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); }
+
+ const IdentifierAliasMap& exportedBindings() const { return m_exportedBindings; }
+
+ bool exportName(const Identifier& exportedName)
+ {
+ return m_exportedNames.add(exportedName.impl()).isNewEntry;
+ }
+
+ void exportBinding(const Identifier& localName, const Identifier& exportedName)
+ {
+ m_exportedBindings.add(localName.impl(), IdentifierSet()).iterator->value.add(exportedName.impl());
+ }
+
+ void exportBinding(const Identifier& localName)
+ {
+ exportBinding(localName, localName);
+ }
+
+private:
+ ModuleScopeData() = default;
+
+ IdentifierSet m_exportedNames { };
+ IdentifierAliasMap m_exportedBindings { };
+};
+
+} // namespace
Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/Nodes.cpp 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp 2016-07-31 07:04:57 UTC (rev 203953)
@@ -117,7 +117,7 @@
// ------------------------------ ProgramNode -----------------------------
-ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
: ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
, m_startColumn(startColumn)
, m_endColumn(endColumn)
@@ -126,16 +126,17 @@
// ------------------------------ ModuleProgramNode -----------------------------
-ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&& moduleScopeData)
: ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
, m_startColumn(startColumn)
, m_endColumn(endColumn)
+ , m_moduleScopeData(*WTFMove(moduleScopeData))
{
}
// ------------------------------ EvalNode -----------------------------
-EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
: ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
, m_endColumn(endColumn)
{
@@ -181,7 +182,7 @@
// ------------------------------ FunctionNode -----------------------------
-FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
: ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
, m_parameters(parameters)
, m_startColumn(startColumn)
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2016-07-31 07:04:57 UTC (rev 203953)
@@ -52,6 +52,7 @@
class JSScope;
class ScopeNode;
class ModuleAnalyzer;
+ class ModuleScopeData;
typedef SmallPtrSet<UniquedStringImpl*> UniquedStringImplPtrSet;
@@ -1644,7 +1645,7 @@
class ProgramNode : public ScopeNode {
public:
- ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
+ ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
unsigned startColumn() const { return m_startColumn; }
unsigned endColumn() const { return m_endColumn; }
@@ -1659,7 +1660,7 @@
class EvalNode : public ScopeNode {
public:
- EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
+ EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
ALWAYS_INLINE unsigned startColumn() const { return 0; }
unsigned endColumn() const { return m_endColumn; }
@@ -1674,7 +1675,7 @@
class ModuleProgramNode : public ScopeNode {
public:
- ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
+ ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
unsigned startColumn() const { return m_startColumn; }
unsigned endColumn() const { return m_endColumn; }
@@ -1681,10 +1682,16 @@
static const bool scopeIsFunction = false;
+ ModuleScopeData& moduleScopeData()
+ {
+ return m_moduleScopeData;
+ }
+
private:
void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
unsigned m_startColumn;
unsigned m_endColumn;
+ Ref<ModuleScopeData> m_moduleScopeData;
};
class ModuleNameNode : public Node {
@@ -1915,7 +1922,7 @@
class FunctionNode final : public ScopeNode {
public:
- FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
+ FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
FunctionParameters* parameters() const { return m_parameters; }
Modified: trunk/Source/_javascript_Core/parser/NodesAnalyzeModule.cpp (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/NodesAnalyzeModule.cpp 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/NodesAnalyzeModule.cpp 2016-07-31 07:04:57 UTC (rev 203953)
@@ -65,9 +65,8 @@
analyzer.moduleRecord()->addStarExportEntry(m_moduleName->moduleName());
}
-void ExportDefaultDeclarationNode::analyzeModule(ModuleAnalyzer& analyzer)
+void ExportDefaultDeclarationNode::analyzeModule(ModuleAnalyzer&)
{
- analyzer.declareExportAlias(m_localName, analyzer.vm().propertyNames->defaultKeyword);
}
void ExportLocalDeclarationNode::analyzeModule(ModuleAnalyzer&)
@@ -86,11 +85,7 @@
// In this case, no local variable names are imported into the current module.
// "v" indirectly points the binding in "mod".
analyzer.moduleRecord()->addExportEntry(JSModuleRecord::ExportEntry::createIndirect(specifier->exportedName(), specifier->localName(), m_moduleName->moduleName()));
- continue;
}
-
- if (specifier->localName() != specifier->exportedName())
- analyzer.declareExportAlias(specifier->localName(), specifier->exportedName());
}
}
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2016-07-31 07:04:57 UTC (rev 203953)
@@ -234,6 +234,9 @@
if (strictMode == JSParserStrictMode::Strict)
scope->setStrictMode();
+ if (parseMode == SourceParseMode::ModuleAnalyzeMode || parseMode == SourceParseMode::ModuleEvaluateMode)
+ m_moduleScopeData = ModuleScopeData::create();
+
next();
}
@@ -476,7 +479,8 @@
propagateError();
- for (const auto& uid : currentScope()->moduleScopeData().exportedBindings()) {
+ for (const auto& pair : m_moduleScopeData->exportedBindings()) {
+ const auto& uid = pair.key;
if (currentScope()->hasDeclaredVariable(uid)) {
currentScope()->declaredVariables().markVariableAsExported(uid);
continue;
@@ -708,7 +712,7 @@
}
if (exportType == ExportType::Exported) {
semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
- currentScope()->moduleScopeData().exportBinding(*name);
+ m_moduleScopeData->exportBinding(*name);
}
if (hasInitializer) {
@@ -828,7 +832,7 @@
if (exportType == ExportType::Exported) {
semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
- currentScope()->moduleScopeData().exportBinding(name);
+ m_moduleScopeData->exportBinding(name);
}
return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
}
@@ -2229,7 +2233,7 @@
internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
if (exportType == ExportType::Exported) {
semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
- currentScope()->moduleScopeData().exportBinding(*functionInfo.name);
+ m_moduleScopeData->exportBinding(*functionInfo.name);
}
TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
@@ -2255,7 +2259,7 @@
internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
if (exportType == ExportType::Exported) {
semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
- currentScope()->moduleScopeData().exportBinding(*info.className);
+ m_moduleScopeData->exportBinding(*info.className);
}
JSTextPosition classEnd = lastTokenEndPosition();
@@ -2786,7 +2790,7 @@
}
template <typename LexerType>
-template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings)
+template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings)
{
// ExportSpecifier :
// IdentifierName
@@ -2808,7 +2812,7 @@
}
semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
- maybeLocalNames.append(localName);
+ maybeExportedLocalNames.append(std::make_pair(localName, exportedName));
return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
}
@@ -2896,7 +2900,7 @@
failIfFalse(result, "Cannot parse the declaration");
semanticFailIfFalse(exportName(m_vm->propertyNames->defaultKeyword), "Only one 'default' export is allowed");
- currentScope()->moduleScopeData().exportBinding(*localName);
+ m_moduleScopeData->exportBinding(*localName, m_vm->propertyNames->defaultKeyword);
return context.createExportDefaultDeclaration(exportLocation, result, *localName);
}
@@ -2916,12 +2920,12 @@
next();
auto specifierList = context.createExportSpecifierList();
- Vector<const Identifier*> maybeLocalNames;
+ Vector<std::pair<const Identifier*, const Identifier*>> maybeExportedLocalNames;
bool hasKeywordForLocalBindings = false;
while (!match(CLOSEBRACE)) {
failIfFalse(matchIdentifierOrKeyword(), "Expected a variable name for the export declaration");
- auto specifier = parseExportSpecifier(context, maybeLocalNames, hasKeywordForLocalBindings);
+ auto specifier = parseExportSpecifier(context, maybeExportedLocalNames, hasKeywordForLocalBindings);
failIfFalse(specifier, "Cannot parse the named export");
context.appendExportSpecifier(specifierList, specifier);
if (!consume(COMMA))
@@ -2947,8 +2951,11 @@
// does not have effect on the current module's scope. But,
// export { A, B, C as D }
// will reference the current module's bindings.
- for (const Identifier* localName : maybeLocalNames)
- currentScope()->moduleScopeData().exportBinding(*localName);
+ for (const auto& pair : maybeExportedLocalNames) {
+ const Identifier* localName = pair.first;
+ const Identifier* exportedName = pair.second;
+ m_moduleScopeData->exportBinding(*localName, *exportedName);
+ }
}
return context.createExportNamedDeclaration(exportLocation, specifierList, moduleName);
Modified: trunk/Source/_javascript_Core/parser/Parser.h (203952 => 203953)
--- trunk/Source/_javascript_Core/parser/Parser.h 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2016-07-31 07:04:57 UTC (rev 203953)
@@ -28,6 +28,7 @@
#include "Executable.h"
#include "JSGlobalObject.h"
#include "Lexer.h"
+#include "ModuleScopeData.h"
#include "Nodes.h"
#include "ParserArena.h"
#include "ParserError.h"
@@ -128,27 +129,6 @@
return token.m_type == IDENT || token.m_type & KeywordTokenFlag;
}
-class ModuleScopeData : public RefCounted<ModuleScopeData> {
-public:
- static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); }
-
- const IdentifierSet& exportedBindings() const { return m_exportedBindings; }
-
- bool exportName(const Identifier& exportedName)
- {
- return m_exportedNames.add(exportedName.impl()).isNewEntry;
- }
-
- void exportBinding(const Identifier& localName)
- {
- m_exportedBindings.add(localName.impl());
- }
-
-private:
- IdentifierSet m_exportedNames { };
- IdentifierSet m_exportedBindings { };
-};
-
struct Scope {
WTF_MAKE_NONCOPYABLE(Scope);
@@ -216,7 +196,6 @@
, m_lexicalVariables(WTFMove(other.m_lexicalVariables))
, m_usedVariables(WTFMove(other.m_usedVariables))
, m_closedVariableCandidates(WTFMove(other.m_closedVariableCandidates))
- , m_moduleScopeData(WTFMove(other.m_moduleScopeData))
, m_functionDeclarations(WTFMove(other.m_functionDeclarations))
{
}
@@ -277,11 +256,8 @@
break;
case SourceParseMode::ProgramMode:
- break;
-
case SourceParseMode::ModuleAnalyzeMode:
case SourceParseMode::ModuleEvaluateMode:
- setIsModule();
break;
}
}
@@ -313,12 +289,6 @@
return m_lexicalVariables;
}
- ModuleScopeData& moduleScopeData() const
- {
- ASSERT(m_moduleScopeData);
- return *m_moduleScopeData;
- }
-
void computeLexicallyCapturedVariablesAndPurgeCandidates()
{
// Because variables may be defined at any time in the range of a lexical scope, we must
@@ -731,11 +701,6 @@
m_isArrowFunction = true;
}
- void setIsModule()
- {
- m_moduleScopeData = ModuleScopeData::create();
- }
-
const VM* m_vm;
bool m_shadowsArguments;
bool m_usesEval;
@@ -771,7 +736,6 @@
Vector<UniquedStringImplPtrSet, 6> m_usedVariables;
UniquedStringImplPtrSet m_sloppyModeHoistableFunctionCandidates;
HashSet<UniquedStringImpl*> m_closedVariableCandidates;
- RefPtr<ModuleScopeData> m_moduleScopeData;
DeclarationStacks::FunctionStack m_functionDeclarations;
};
@@ -1176,7 +1140,8 @@
bool exportName(const Identifier& ident)
{
ASSERT(currentScope().index() == 0);
- return currentScope()->moduleScopeData().exportName(ident);
+ ASSERT(m_moduleScopeData);
+ return m_moduleScopeData->exportName(ident);
}
ScopeStack m_scopeStack;
@@ -1442,7 +1407,7 @@
template <class TreeBuilder> typename TreeBuilder::ImportSpecifier parseImportClauseItem(TreeBuilder&, ImportSpecifierType);
template <class TreeBuilder> typename TreeBuilder::ModuleName parseModuleName(TreeBuilder&);
template <class TreeBuilder> TreeStatement parseImportDeclaration(TreeBuilder&);
- template <class TreeBuilder> typename TreeBuilder::ExportSpecifier parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings);
+ template <class TreeBuilder> typename TreeBuilder::ExportSpecifier parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings);
template <class TreeBuilder> TreeStatement parseExportDeclaration(TreeBuilder&);
enum class FunctionDefinitionType { _expression_, Declaration, Method };
@@ -1623,6 +1588,7 @@
ExpressionErrorClassifier* m_expressionErrorClassifier;
bool m_isEvalContext;
bool m_immediateParentAllowsFunctionDeclarationInStatement;
+ RefPtr<ModuleScopeData> m_moduleScopeData;
struct DepthManager {
DepthManager(int* depth)
@@ -1697,7 +1663,8 @@
*m_source,
m_features,
currentScope()->innerArrowFunctionFeatures(),
- m_numConstants);
+ m_numConstants,
+ WTFMove(m_moduleScopeData));
result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset());
result->setEndOffset(m_lexer->currentOffset());
Added: trunk/Source/_javascript_Core/tests/modules/aliased-names/main.js (0 => 203953)
--- trunk/Source/_javascript_Core/tests/modules/aliased-names/main.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/modules/aliased-names/main.js 2016-07-31 07:04:57 UTC (rev 203953)
@@ -0,0 +1,10 @@
+var a = 42;
+
+function change(value)
+{
+ a = value;
+}
+
+export { a }
+export { a as b }
+export { change }
Added: trunk/Source/_javascript_Core/tests/modules/aliased-names.js (0 => 203953)
--- trunk/Source/_javascript_Core/tests/modules/aliased-names.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/modules/aliased-names.js 2016-07-31 07:04:57 UTC (rev 203953)
@@ -0,0 +1,8 @@
+import { a, b, change } from 'aliased-names/main.js'
+import { shouldBe, shouldThrow } from "./resources/assert.js";
+
+shouldBe(a, 42);
+shouldBe(b, 42);
+change(400);
+shouldBe(a, 400);
+shouldBe(b, 400);
Modified: trunk/Source/_javascript_Core/tests/stress/modules-syntax-error-with-names.js (203952 => 203953)
--- trunk/Source/_javascript_Core/tests/stress/modules-syntax-error-with-names.js 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/tests/stress/modules-syntax-error-with-names.js 2016-07-31 07:04:57 UTC (rev 203953)
@@ -192,28 +192,63 @@
export default 20;
`, `SyntaxError: Only one 'default' export is allowed.:4`);
+checkModuleSyntaxError(String.raw`
+var a = 42;
+var b = 55;
+export { a as Cocoa, b as Cocoa };
+`, `SyntaxError: Cannot export a duplicate name 'Cocoa'.:4`);
+
+checkModuleSyntaxError(String.raw`
+var a = 42;
+var b = 55;
+export { a as Cocoa, b as Cocoa };
+`, `SyntaxError: Cannot export a duplicate name 'Cocoa'.:4`);
+
+checkModuleSyntaxError(String.raw`
+var Cocoa = 42;
+var b = 55;
+export { Cocoa, b as Cocoa };
+`, `SyntaxError: Cannot export a duplicate name 'Cocoa'.:4`);
+
+checkModuleSyntaxError(String.raw`
+export var Cocoa = 42;
+var b = 55;
+export { b as Cocoa };
+`, `SyntaxError: Cannot export a duplicate name 'Cocoa'.:4`);
+
+checkModuleSyntaxError(String.raw`
+var a = 42;
+export { a as Cocoa };
+export function Cocoa() { }
+`, `SyntaxError: Cannot export a duplicate function name: 'Cocoa'.:5`);
+
+checkModuleSyntaxError(String.raw`
+var a = 42;
+export { a as Cocoa };
+export class Cocoa { }
+`, `SyntaxError: Cannot export a duplicate class name: 'Cocoa'.:5`);
+
// FIXME: These tests also should be passed. But now, var and lexical declared names can be co-exist on Script / Module top level scope.
// This will be fixed when this issue is fixed for Script environment.
// http://www.ecma-international.org/ecma-262/6.0/#sec-scripts-static-semantics-early-errors
// http://www.ecma-international.org/ecma-262/6.0/#sec-module-semantics-static-semantics-early-errors
-//
+checkModuleSyntaxError(String.raw`
+import A from "Cocoa"
+var A = 20;
+`, `SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'A'.:3`);
+
// checkModuleSyntaxError(String.raw`
-// import A from "Cocoa"
// var A = 20;
-// `, ``);
-//
-// checkModuleSyntaxError(String.raw`
-// var A = 20;
// import A from "Cocoa"
// `, ``);
-//
+
+checkModuleSyntaxError(String.raw`
+import A from "Cocoa"
+var A = 20;
+`, `SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'A'.:3`);
+
// checkModuleSyntaxError(String.raw`
-// import A from "Cocoa"
// var A = 20;
-// `, ``);
-//
-// checkModuleSyntaxError(String.raw`
-// var A = 20;
// import A from "Cocoa"
// `, ``);
Modified: trunk/Source/_javascript_Core/tests/test262.yaml (203952 => 203953)
--- trunk/Source/_javascript_Core/tests/test262.yaml 2016-07-31 01:08:37 UTC (rev 203952)
+++ trunk/Source/_javascript_Core/tests/test262.yaml 2016-07-31 07:04:57 UTC (rev 203953)
@@ -71230,7 +71230,7 @@
- path: test262/test/language/module-code/instn-star-props-nrml-star_FIXTURE.js
cmd: prepareTest262Fixture
- path: test262/test/language/module-code/instn-star-props-nrml.js
- cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+ cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/instn-star-star-cycle-2_FIXTURE.js
cmd: prepareTest262Fixture
- path: test262/test/language/module-code/instn-star-star-cycle-indirect-x_FIXTURE.js
@@ -71256,11 +71256,11 @@
- path: test262/test/language/module-code/namespace/Symbol.iterator/this-val-not-ns.js
cmd: runTest262 :fail, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/Symbol.iterator/values-binding-types.js
- cmd: runTest262 :fail, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
+ cmd: runTest262 :normal, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/Symbol.iterator/values-binding-types_.js
cmd: prepareTest262Fixture
- path: test262/test/language/module-code/namespace/Symbol.iterator/values-order.js
- cmd: runTest262 :fail, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
+ cmd: runTest262 :normal, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/Symbol.toStringTag.js
cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/internals/define-own-property.js
@@ -71308,11 +71308,11 @@
- path: test262/test/language/module-code/namespace/internals/is-extensible.js
cmd: runTest262 :normal, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/internals/own-property-keys-binding-types.js
- cmd: runTest262 :fail, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
+ cmd: runTest262 :normal, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/internals/own-property-keys-binding-types_FIXTURE.js
cmd: prepareTest262Fixture
- path: test262/test/language/module-code/namespace/internals/own-property-keys-sort.js
- cmd: runTest262 :fail, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
+ cmd: runTest262 :normal, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/internals/prevent-extensions.js
cmd: runTest262 :normal, "NoException", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:module]
- path: test262/test/language/module-code/namespace/internals/set-prototype-of.js