Title: [279447] trunk
Revision
279447
Author
[email protected]
Date
2021-06-30 19:03:55 -0700 (Wed, 30 Jun 2021)

Log Message

[JSC] Private names should be handled by usedVariables mechanism
https://bugs.webkit.org/show_bug.cgi?id=227476
rdar://76049469

Reviewed by Saam Barati.
Source/_javascript_Core:

Private name handling in the current parser has many problems.

    1. The parser backtracks when it sees destructuring assignment, arrow function etc. In that case, the discarded code
       must not have any effect on the outside of that code. However, private name handling is annotating "used" of the
       upper scopes, which is wrong.
    2. In class _expression_, private name lookup intentionally skips the class-scope when parsing class heritage. But this
       is not correct since CodeBlock will perform lookup on the normal scope chain and this will look into the class-scope
       inconsistently. This means that we could encounter different private name at runtime. (it is tested in the added test).
    3. We skip inner function parsing when it is parsed previously. At that case, we must preserve private name annotation,
       but restored function information does not preserve that.

This patch changes how private name is handled.

    1. We were anyway defining #XXX variables which holds private symbols. So we track "use" information by the mechanism used
       for usual variables. We remove Used / Declared bits from PrivateNameEntry since they are not necessary at runtime, and
       these information is handled / tracked in Parser's Scope. For backtracking, we already have a mechanism to roll-back
       m_usedVariables, so using variable mechanism automatically fixes the problem.
    2. We define class-head-scope separately from class-scope. class-heritage _expression_ can see class name, but it cannot use
       private names. Previously, our implementation attempted to achieve that by hacky way: skipping this class-scope for private
       names only while parsing class-heritage. But this was wrong since it does not consider CodeBlock's linking phase as described
       in the problem (2). Instead, we just define class-head-scope which holds class constructor name.
    3. We clean up popScopeInternal to populate lexical-variables and function-stack. Previously, we are stealing them before popping
       the scope when necessary, but this is a hack and a bit wrong since scope's popping operation needs to access these information
       in some cases. Instead, popScopeInternal populates them after popping the scope.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::pushClassHeadLexicalScope):
(JSC::BytecodeGenerator::popClassHeadLexicalScope):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ClassExprNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createClassExpr):
(JSC::ASTBuilder::createBlockStatement):
(JSC::ASTBuilder::createForLoop):
(JSC::ASTBuilder::createForInLoop):
(JSC::ASTBuilder::createForOfLoop):
(JSC::ASTBuilder::createTryStatement):
(JSC::ASTBuilder::createSwitchStatement):
* parser/NodeConstructors.h:
(JSC::ForNode::ForNode):
(JSC::TryNode::TryNode):
(JSC::ClassExprNode::ClassExprNode):
(JSC::SwitchNode::SwitchNode):
(JSC::BlockNode::BlockNode):
(JSC::EnumerationNode::EnumerationNode):
(JSC::ForInNode::ForInNode):
(JSC::ForOfNode::ForOfNode):
* parser/Nodes.cpp:
(JSC::ScopeNode::ScopeNode):
(JSC::ProgramNode::ProgramNode):
(JSC::ModuleProgramNode::ModuleProgramNode):
(JSC::EvalNode::EvalNode):
(JSC::FunctionNode::FunctionNode):
(JSC::VariableEnvironmentNode::VariableEnvironmentNode):
* parser/Nodes.h:
(JSC::VariableEnvironmentNode::VariableEnvironmentNode): Deleted.
* parser/Parser.cpp:
(JSC::isPrivateFieldName):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseForStatement):
(JSC::Parser<LexerType>::parseSwitchStatement):
(JSC::Parser<LexerType>::parseTryStatement):
(JSC::Parser<LexerType>::parseBlockStatement):
(JSC::Parser<LexerType>::parseFunctionDeclarationStatement):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseBinaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression):
(JSC::Parser<LexerType>::usePrivateName): Deleted.
* parser/Parser.h:
(JSC::Scope::finalizeLexicalEnvironment):
(JSC::Scope::takeLexicalEnvironment):
(JSC::Scope::takeDeclaredVariables):
(JSC::Scope::takeFunctionDeclarations):
(JSC::Scope::forEachUsedVariable):
(JSC::Scope::usePrivateName):
(JSC::Scope::currentUsedVariablesSize):
(JSC::Parser::popScopeInternal):
(JSC::Parser::popScope):
(JSC::Parser<LexerType>::parse):
(JSC::Scope::copyUndeclaredPrivateNamesTo): Deleted.
(JSC::Scope::hasUsedButUndeclaredPrivateNames const): Deleted.
(JSC::Parser::privateNameScope): Deleted.
(JSC::Parser::copyUndeclaredPrivateNamesToOuterScope): Deleted.
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createClassExpr):
(JSC::SyntaxChecker::createBlockStatement):
(JSC::SyntaxChecker::createForLoop):
(JSC::SyntaxChecker::createForInLoop):
(JSC::SyntaxChecker::createForOfLoop):
(JSC::SyntaxChecker::createTryStatement):
(JSC::SyntaxChecker::createSwitchStatement):
* parser/VariableEnvironment.cpp:
(JSC::VariableEnvironmentEntry::dump const):
(JSC::VariableEnvironment::declarePrivateField):
(JSC::VariableEnvironment::declarePrivateAccessor):
(JSC::VariableEnvironment::declarePrivateMethod):
(JSC::VariableEnvironment::dump const):
* parser/VariableEnvironment.h:
(JSC::VariableEnvironment::declarePrivateField):
(JSC::VariableEnvironment::privateNameEnvironment):
(JSC::VariableEnvironment::addPrivateNamesFrom):
(JSC::PrivateNameEntry::isUsed const): Deleted.
(JSC::PrivateNameEntry::isDeclared const): Deleted.
(JSC::PrivateNameEntry::setIsUsed): Deleted.
(JSC::PrivateNameEntry::setIsDeclared): Deleted.
(JSC::VariableEnvironment::usePrivateName): Deleted.
(JSC::VariableEnvironment::copyPrivateNamesTo const): Deleted.
(JSC::VariableEnvironment::copyUndeclaredPrivateNamesTo const): Deleted.

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (279446 => 279447)


--- trunk/JSTests/ChangeLog	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/JSTests/ChangeLog	2021-07-01 02:03:55 UTC (rev 279447)
@@ -1,3 +1,11 @@
+2021-06-29  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Private names should be handled by usedVariables mechanism
+        https://bugs.webkit.org/show_bug.cgi?id=227476
+        rdar://76049469
+
+        Reviewed by Saam Barati.
+
 2021-06-30  Mikhail R. Gadelha  <[email protected]>
 
         Unskip interpreter-wasm.js on ARM and MIPS

Modified: trunk/JSTests/stress/undeclared-private-field-in-eval.js (279446 => 279447)


--- trunk/JSTests/stress/undeclared-private-field-in-eval.js	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/JSTests/stress/undeclared-private-field-in-eval.js	2021-07-01 02:03:55 UTC (rev 279447)
@@ -13,7 +13,7 @@
 
     assert(!!error);
     assert(error instanceof SyntaxError);
-    assert(error.message === "Cannot reference undeclared private names");
+    assert(error.message.startsWith("Cannot reference undeclared private names"));
 }
 
 class C {

Modified: trunk/Source/_javascript_Core/ChangeLog (279446 => 279447)


--- trunk/Source/_javascript_Core/ChangeLog	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-07-01 02:03:55 UTC (rev 279447)
@@ -1,3 +1,122 @@
+2021-06-30  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Private names should be handled by usedVariables mechanism
+        https://bugs.webkit.org/show_bug.cgi?id=227476
+        rdar://76049469
+
+        Reviewed by Saam Barati.
+
+        Private name handling in the current parser has many problems.
+
+            1. The parser backtracks when it sees destructuring assignment, arrow function etc. In that case, the discarded code
+               must not have any effect on the outside of that code. However, private name handling is annotating "used" of the
+               upper scopes, which is wrong.
+            2. In class _expression_, private name lookup intentionally skips the class-scope when parsing class heritage. But this
+               is not correct since CodeBlock will perform lookup on the normal scope chain and this will look into the class-scope
+               inconsistently. This means that we could encounter different private name at runtime. (it is tested in the added test).
+            3. We skip inner function parsing when it is parsed previously. At that case, we must preserve private name annotation,
+               but restored function information does not preserve that.
+
+        This patch changes how private name is handled.
+
+            1. We were anyway defining #XXX variables which holds private symbols. So we track "use" information by the mechanism used
+               for usual variables. We remove Used / Declared bits from PrivateNameEntry since they are not necessary at runtime, and
+               these information is handled / tracked in Parser's Scope. For backtracking, we already have a mechanism to roll-back
+               m_usedVariables, so using variable mechanism automatically fixes the problem.
+            2. We define class-head-scope separately from class-scope. class-heritage _expression_ can see class name, but it cannot use
+               private names. Previously, our implementation attempted to achieve that by hacky way: skipping this class-scope for private
+               names only while parsing class-heritage. But this was wrong since it does not consider CodeBlock's linking phase as described
+               in the problem (2). Instead, we just define class-head-scope which holds class constructor name.
+            3. We clean up popScopeInternal to populate lexical-variables and function-stack. Previously, we are stealing them before popping
+               the scope when necessary, but this is a hack and a bit wrong since scope's popping operation needs to access these information
+               in some cases. Instead, popScopeInternal populates them after popping the scope.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::pushClassHeadLexicalScope):
+        (JSC::BytecodeGenerator::popClassHeadLexicalScope):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ClassExprNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createClassExpr):
+        (JSC::ASTBuilder::createBlockStatement):
+        (JSC::ASTBuilder::createForLoop):
+        (JSC::ASTBuilder::createForInLoop):
+        (JSC::ASTBuilder::createForOfLoop):
+        (JSC::ASTBuilder::createTryStatement):
+        (JSC::ASTBuilder::createSwitchStatement):
+        * parser/NodeConstructors.h:
+        (JSC::ForNode::ForNode):
+        (JSC::TryNode::TryNode):
+        (JSC::ClassExprNode::ClassExprNode):
+        (JSC::SwitchNode::SwitchNode):
+        (JSC::BlockNode::BlockNode):
+        (JSC::EnumerationNode::EnumerationNode):
+        (JSC::ForInNode::ForInNode):
+        (JSC::ForOfNode::ForOfNode):
+        * parser/Nodes.cpp:
+        (JSC::ScopeNode::ScopeNode):
+        (JSC::ProgramNode::ProgramNode):
+        (JSC::ModuleProgramNode::ModuleProgramNode):
+        (JSC::EvalNode::EvalNode):
+        (JSC::FunctionNode::FunctionNode):
+        (JSC::VariableEnvironmentNode::VariableEnvironmentNode):
+        * parser/Nodes.h:
+        (JSC::VariableEnvironmentNode::VariableEnvironmentNode): Deleted.
+        * parser/Parser.cpp:
+        (JSC::isPrivateFieldName):
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::parseForStatement):
+        (JSC::Parser<LexerType>::parseSwitchStatement):
+        (JSC::Parser<LexerType>::parseTryStatement):
+        (JSC::Parser<LexerType>::parseBlockStatement):
+        (JSC::Parser<LexerType>::parseFunctionDeclarationStatement):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parseBinaryExpression):
+        (JSC::Parser<LexerType>::parseMemberExpression):
+        (JSC::Parser<LexerType>::usePrivateName): Deleted.
+        * parser/Parser.h:
+        (JSC::Scope::finalizeLexicalEnvironment):
+        (JSC::Scope::takeLexicalEnvironment):
+        (JSC::Scope::takeDeclaredVariables):
+        (JSC::Scope::takeFunctionDeclarations):
+        (JSC::Scope::forEachUsedVariable):
+        (JSC::Scope::usePrivateName):
+        (JSC::Scope::currentUsedVariablesSize):
+        (JSC::Parser::popScopeInternal):
+        (JSC::Parser::popScope):
+        (JSC::Parser<LexerType>::parse):
+        (JSC::Scope::copyUndeclaredPrivateNamesTo): Deleted.
+        (JSC::Scope::hasUsedButUndeclaredPrivateNames const): Deleted.
+        (JSC::Parser::privateNameScope): Deleted.
+        (JSC::Parser::copyUndeclaredPrivateNamesToOuterScope): Deleted.
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createClassExpr):
+        (JSC::SyntaxChecker::createBlockStatement):
+        (JSC::SyntaxChecker::createForLoop):
+        (JSC::SyntaxChecker::createForInLoop):
+        (JSC::SyntaxChecker::createForOfLoop):
+        (JSC::SyntaxChecker::createTryStatement):
+        (JSC::SyntaxChecker::createSwitchStatement):
+        * parser/VariableEnvironment.cpp:
+        (JSC::VariableEnvironmentEntry::dump const):
+        (JSC::VariableEnvironment::declarePrivateField):
+        (JSC::VariableEnvironment::declarePrivateAccessor):
+        (JSC::VariableEnvironment::declarePrivateMethod):
+        (JSC::VariableEnvironment::dump const):
+        * parser/VariableEnvironment.h:
+        (JSC::VariableEnvironment::declarePrivateField):
+        (JSC::VariableEnvironment::privateNameEnvironment):
+        (JSC::VariableEnvironment::addPrivateNamesFrom):
+        (JSC::PrivateNameEntry::isUsed const): Deleted.
+        (JSC::PrivateNameEntry::isDeclared const): Deleted.
+        (JSC::PrivateNameEntry::setIsUsed): Deleted.
+        (JSC::PrivateNameEntry::setIsDeclared): Deleted.
+        (JSC::VariableEnvironment::usePrivateName): Deleted.
+        (JSC::VariableEnvironment::copyPrivateNamesTo const): Deleted.
+        (JSC::VariableEnvironment::copyUndeclaredPrivateNamesTo const): Deleted.
+
 2021-06-30  Mark Lam  <[email protected]>
 
         ARM64: Disable selection of BFI instruction variants by default.

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (279446 => 279447)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-07-01 02:03:55 UTC (rev 279447)
@@ -1992,6 +1992,16 @@
         *constantSymbolTableResult = constantSymbolTableResultTemp;
 }
 
+void BytecodeGenerator::pushClassHeadLexicalScope(VariableEnvironment& environment)
+{
+    pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+}
+
+void BytecodeGenerator::popClassHeadLexicalScope(VariableEnvironment& environment)
+{
+    popLexicalScopeInternal(environment);
+}
+
 void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType,
     RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType, ScopeRegisterType scopeRegisterType)
 {

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (279446 => 279447)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -986,6 +986,9 @@
         void emitOutOfLineCatchHandler(RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData*);
         void emitOutOfLineFinallyHandler(RegisterID* exceptionRegister, RegisterID* completionTypeRegister, TryData*);
 
+        void pushClassHeadLexicalScope(VariableEnvironment&);
+        void popClassHeadLexicalScope(VariableEnvironment&);
+
     private:
         static constexpr int CurrentLexicalScopeIndex = -2;
         static constexpr int OutermostLexicalScopeIndex = -1;

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (279446 => 279447)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-07-01 02:03:55 UTC (rev 279447)
@@ -5189,6 +5189,16 @@
 {
     StrictModeScope strictModeScope(generator);
 
+    if (!m_name.isNull())
+        generator.pushClassHeadLexicalScope(m_classHeadEnvironment);
+
+    // Class heritage must be evaluated outside of private fields access.
+    RefPtr<RegisterID> superclass;
+    if (m_classHeritage) {
+        superclass = generator.newTemporary();
+        generator.emitNode(superclass.get(), m_classHeritage);
+    }
+
     if (m_needsLexicalScope)
         generator.pushLexicalScope(this, BytecodeGenerator::ScopeType::ClassScope, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
 
@@ -5200,12 +5210,6 @@
     if (shouldEmitPrivateBrand)
         generator.emitCreatePrivateBrand(m_position, m_position, m_position);
 
-    RefPtr<RegisterID> superclass;
-    if (m_classHeritage) {
-        superclass = generator.newTemporary();
-        generator.emitNode(superclass.get(), m_classHeritage);
-    }
-
     RefPtr<RegisterID> constructor = generator.tempDestination(dst);
     bool needsHomeObject = false;
 
@@ -5272,7 +5276,7 @@
         }
     }
 
-    if (m_needsLexicalScope && !m_name.isNull()) {
+    if (!m_name.isNull()) {
         Variable classNameVar = generator.variable(m_name);
         RELEASE_ASSERT(classNameVar.isResolved());
         RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
@@ -5293,11 +5297,14 @@
         generator.emitCall(generator.newTemporary(), staticFieldInitializer.get(), NoExpectedFunction, args, position(), position(), position(), DebuggableCall::No);
     }
 
+    if (hasPrivateNames)
+        generator.popPrivateAccessNames();
+
     if (m_needsLexicalScope)
         generator.popLexicalScope(this);
 
-    if (hasPrivateNames)
-        generator.popPrivateAccessNames();
+    if (!m_name.isNull())
+        generator.popClassHeadLexicalScope(m_classHeadEnvironment);
 
     return generator.move(generator.finalDestination(dst, constructor.get()), constructor.get());
 }

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -415,11 +415,11 @@
         return new (m_parserArena) DefineFieldNode(location, ident, initializer, type);
     }
 
-    ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment& classEnvironment, ExpressionNode* constructor,
+    ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment&& classHeadEnvironment, VariableEnvironment&& classEnvironment, ExpressionNode* constructor,
         ExpressionNode* parentClass, PropertyListNode* classElements, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end)
     {
         SourceCode source = m_sourceCode->subExpression(classInfo.startOffset, classInfo.endOffset, classInfo.startLine, classInfo.startColumn);
-        ClassExprNode* node = new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, classElements);
+        ClassExprNode* node = new (m_parserArena) ClassExprNode(location, *classInfo.className, source, WTFMove(classHeadEnvironment), WTFMove(classEnvironment), constructor, parentClass, classElements);
         setExceptionLocation(node, start, divot, end);
         return node;
     }
@@ -587,9 +587,9 @@
         return decl;
     }
 
-    StatementNode* createBlockStatement(const JSTokenLocation& location, JSC::SourceElements* elements, int startLine, int endLine, VariableEnvironment& lexicalVariables, DeclarationStacks::FunctionStack&& functionStack)
+    StatementNode* createBlockStatement(const JSTokenLocation& location, JSC::SourceElements* elements, int startLine, int endLine, VariableEnvironment&& lexicalVariables, DeclarationStacks::FunctionStack&& functionStack)
     {
-        BlockNode* block = new (m_parserArena) BlockNode(location, elements, lexicalVariables, WTFMove(functionStack));
+        BlockNode* block = new (m_parserArena) BlockNode(location, elements, WTFMove(lexicalVariables), WTFMove(functionStack));
         block->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
         return block;
     }
@@ -608,39 +608,39 @@
         return result;
     }
 
-    StatementNode* createForLoop(const JSTokenLocation& location, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end, VariableEnvironment& lexicalVariables)
+    StatementNode* createForLoop(const JSTokenLocation& location, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end, VariableEnvironment&& lexicalVariables)
     {
-        ForNode* result = new (m_parserArena) ForNode(location, initializer, condition, iter, statements, lexicalVariables);
+        ForNode* result = new (m_parserArena) ForNode(location, initializer, condition, iter, statements, WTFMove(lexicalVariables));
         result->setLoc(start, end, location.startOffset, location.lineStartOffset);
         return result;
     }
 
-    StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+    StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment&& lexicalVariables)
     {
-        ForInNode* result = new (m_parserArena) ForInNode(location, lhs, iter, statements, lexicalVariables);
+        ForInNode* result = new (m_parserArena) ForInNode(location, lhs, iter, statements, WTFMove(lexicalVariables));
         result->setLoc(start, end, location.startOffset, location.lineStartOffset);
         setExceptionLocation(result, eStart, eDivot, eEnd);
         return result;
     }
     
-    StatementNode* createForInLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+    StatementNode* createForInLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment&& lexicalVariables)
     {
         auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr);
-        return createForInLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables);
+        return createForInLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, WTFMove(lexicalVariables));
     }
     
-    StatementNode* createForOfLoop(bool isForAwait, const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+    StatementNode* createForOfLoop(bool isForAwait, const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment&& lexicalVariables)
     {
-        ForOfNode* result = new (m_parserArena) ForOfNode(isForAwait, location, lhs, iter, statements, lexicalVariables);
+        ForOfNode* result = new (m_parserArena) ForOfNode(isForAwait, location, lhs, iter, statements, WTFMove(lexicalVariables));
         result->setLoc(start, end, location.startOffset, location.lineStartOffset);
         setExceptionLocation(result, eStart, eDivot, eEnd);
         return result;
     }
     
-    StatementNode* createForOfLoop(bool isForAwait, const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+    StatementNode* createForOfLoop(bool isForAwait, const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment&& lexicalVariables)
     {
         auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr);
-        return createForOfLoop(isForAwait, location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables);
+        return createForOfLoop(isForAwait, location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, WTFMove(lexicalVariables));
     }
 
     bool isBindingNode(const DestructuringPattern& pattern)
@@ -732,17 +732,17 @@
         return result;
     }
 
-    StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine, VariableEnvironment& catchEnvironment)
+    StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine, VariableEnvironment&& catchEnvironment)
     {
-        TryNode* result = new (m_parserArena) TryNode(location, tryBlock, catchPattern, catchBlock, catchEnvironment, finallyBlock);
+        TryNode* result = new (m_parserArena) TryNode(location, tryBlock, catchPattern, catchBlock, WTFMove(catchEnvironment), finallyBlock);
         result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
         return result;
     }
 
-    StatementNode* createSwitchStatement(const JSTokenLocation& location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine, VariableEnvironment& lexicalVariables, DeclarationStacks::FunctionStack&& functionStack)
+    StatementNode* createSwitchStatement(const JSTokenLocation& location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine, VariableEnvironment&& lexicalVariables, DeclarationStacks::FunctionStack&& functionStack)
     {
         CaseBlockNode* cases = new (m_parserArena) CaseBlockNode(firstClauses, defaultClause, secondClauses);
-        SwitchNode* result = new (m_parserArena) SwitchNode(location, expr, cases, lexicalVariables, WTFMove(functionStack));
+        SwitchNode* result = new (m_parserArena) SwitchNode(location, expr, cases, WTFMove(lexicalVariables), WTFMove(functionStack));
         result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
         return result;
     }

Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/NodeConstructors.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -941,9 +941,9 @@
     {
     }
 
-    inline ForNode::ForNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, VariableEnvironment& lexicalVariables)
+    inline ForNode::ForNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, VariableEnvironment&& lexicalVariables)
         : StatementNode(location)
-        , VariableEnvironmentNode(lexicalVariables)
+        , VariableEnvironmentNode(WTFMove(lexicalVariables))
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_expr3(expr3)
@@ -995,9 +995,9 @@
         m_expr->setIsOnlyChildOfStatement();
     }
 
-    inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock)
+    inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, VariableEnvironment&& catchEnvironment, StatementNode* finallyBlock)
         : StatementNode(location)
-        , VariableEnvironmentNode(catchEnvironment)
+        , VariableEnvironmentNode(WTFMove(catchEnvironment))
         , m_tryBlock(tryBlock)
         , m_catchPattern(catchPattern)
         , m_catchBlock(catchBlock)
@@ -1071,9 +1071,10 @@
     {
     }
 
-    inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, const SourceCode& classSource, VariableEnvironment& classEnvironment, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* classElements)
+    inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, const SourceCode& classSource, VariableEnvironment&& classHeadEnvironment, VariableEnvironment&& classEnvironment, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* classElements)
         : ExpressionNode(location)
-        , VariableEnvironmentNode(classEnvironment)
+        , VariableEnvironmentNode(WTFMove(classEnvironment))
+        , m_classHeadEnvironment(WTFMove(classHeadEnvironment))
         , m_classSource(classSource)
         , m_name(name)
         , m_ecmaName(&name)
@@ -1080,7 +1081,7 @@
         , m_constructorExpression(constructorExpression)
         , m_classHeritage(classHeritage)
         , m_classElements(classElements)
-        , m_needsLexicalScope(!name.isNull() || PropertyListNode::shouldCreateLexicalScopeForClass(classElements))
+        , m_needsLexicalScope(PropertyListNode::shouldCreateLexicalScopeForClass(classElements))
     {
     }
 
@@ -1108,24 +1109,24 @@
     {
     }
 
-    inline SwitchNode::SwitchNode(const JSTokenLocation& location, ExpressionNode* expr, CaseBlockNode* block, VariableEnvironment& lexicalVariables, FunctionStack&& functionStack)
+    inline SwitchNode::SwitchNode(const JSTokenLocation& location, ExpressionNode* expr, CaseBlockNode* block, VariableEnvironment&& lexicalVariables, FunctionStack&& functionStack)
         : StatementNode(location)
-        , VariableEnvironmentNode(lexicalVariables, WTFMove(functionStack))
+        , VariableEnvironmentNode(WTFMove(lexicalVariables), WTFMove(functionStack))
         , m_expr(expr)
         , m_block(block)
     {
     }
 
-    inline BlockNode::BlockNode(const JSTokenLocation& location, SourceElements* statements, VariableEnvironment& lexicalVariables, FunctionStack&& functionStack)
+    inline BlockNode::BlockNode(const JSTokenLocation& location, SourceElements* statements, VariableEnvironment&& lexicalVariables, FunctionStack&& functionStack)
         : StatementNode(location)
-        , VariableEnvironmentNode(lexicalVariables, WTFMove(functionStack))
+        , VariableEnvironmentNode(WTFMove(lexicalVariables), WTFMove(functionStack))
         , m_statements(statements)
     {
     }
 
-    inline EnumerationNode::EnumerationNode(const JSTokenLocation& location, ExpressionNode* lexpr, ExpressionNode* expr, StatementNode* statement, VariableEnvironment& lexicalVariables)
+    inline EnumerationNode::EnumerationNode(const JSTokenLocation& location, ExpressionNode* lexpr, ExpressionNode* expr, StatementNode* statement, VariableEnvironment&& lexicalVariables)
         : StatementNode(location)
-        , VariableEnvironmentNode(lexicalVariables)
+        , VariableEnvironmentNode(WTFMove(lexicalVariables))
         , m_lexpr(lexpr)
         , m_expr(expr)
         , m_statement(statement)
@@ -1133,13 +1134,13 @@
         ASSERT(lexpr);
     }
     
-    inline ForInNode::ForInNode(const JSTokenLocation& location, ExpressionNode* lexpr, ExpressionNode* expr, StatementNode* statement, VariableEnvironment& lexicalVariables)
-        : EnumerationNode(location, lexpr, expr, statement, lexicalVariables)
+    inline ForInNode::ForInNode(const JSTokenLocation& location, ExpressionNode* lexpr, ExpressionNode* expr, StatementNode* statement, VariableEnvironment&& lexicalVariables)
+        : EnumerationNode(location, lexpr, expr, statement, WTFMove(lexicalVariables))
     {
     }
     
-    inline ForOfNode::ForOfNode(bool isForAwait, const JSTokenLocation& location, ExpressionNode* lexpr, ExpressionNode* expr, StatementNode* statement, VariableEnvironment& lexicalVariables)
-        : EnumerationNode(location, lexpr, expr, statement, lexicalVariables)
+    inline ForOfNode::ForOfNode(bool isForAwait, const JSTokenLocation& location, ExpressionNode* lexpr, ExpressionNode* expr, StatementNode* statement, VariableEnvironment&& lexicalVariables)
+        : EnumerationNode(location, lexpr, expr, statement, WTFMove(lexicalVariables))
         , m_isForAwait(isForAwait)
     {
     }

Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/Nodes.cpp	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp	2021-07-01 02:03:55 UTC (rev 279447)
@@ -131,10 +131,10 @@
 {
 }
 
-ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment&& varEnvironment, FunctionStack&& funcStack, VariableEnvironment&& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
     : StatementNode(endLocation)
     , ParserArenaRoot(parserArena)
-    , VariableEnvironmentNode(lexicalVariables, WTFMove(funcStack))
+    , VariableEnvironmentNode(WTFMove(lexicalVariables), WTFMove(funcStack))
     , m_startLineNumber(startLocation.line)
     , m_startStartOffset(startLocation.startOffset)
     , m_startLineStartOffset(startLocation.lineStartOffset)
@@ -142,11 +142,11 @@
     , m_lexicalScopeFeatures(lexicalScopeFeatures)
     , m_innerArrowFunctionCodeFeatures(innerArrowFunctionCodeFeatures)
     , m_source(source)
+    , m_varDeclarations(WTFMove(varEnvironment))
     , m_sloppyModeHoistedFunctions(WTFMove(sloppyModeHoistedFunctions))
     , m_numConstants(numConstants)
     , m_statements(children)
 {
-    m_varDeclarations.swap(varEnvironment);
 }
 
 StatementNode* ScopeNode::singleStatement() const
@@ -166,8 +166,8 @@
 
 // ------------------------------ 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_startColumn(startColumn)
     , m_endColumn(endColumn)
 {
@@ -175,8 +175,8 @@
 
 // ------------------------------ 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&& moduleScopeData)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&& moduleScopeData)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_startColumn(startColumn)
     , m_endColumn(endColumn)
     , m_usesAwait(features & AwaitFeature)
@@ -186,8 +186,8 @@
 
 // ------------------------------ 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_endColumn(endColumn)
 {
 }
@@ -306,8 +306,8 @@
 
 // ------------------------------ 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
-    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, 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, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
+    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, WTFMove(varEnvironment), WTFMove(funcStack), WTFMove(lexicalVariables), WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_parameters(parameters)
     , m_startColumn(startColumn)
     , m_endColumn(endColumn)
@@ -360,15 +360,15 @@
     return false;
 }
 
-VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables)
+VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment&& lexicalVariables)
+    : m_lexicalVariables(WTFMove(lexicalVariables))
 {
-    m_lexicalVariables.swap(lexicalVariables);
 }
 
-VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables, FunctionStack&& functionStack)
+VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment&& lexicalVariables, FunctionStack&& functionStack)
+    : m_lexicalVariables(WTFMove(lexicalVariables))
+    , m_functionStack(WTFMove(functionStack))
 {
-    m_lexicalVariables.swap(lexicalVariables);
-    m_functionStack = WTFMove(functionStack);
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -273,13 +273,10 @@
     public:
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        VariableEnvironmentNode()
-        {
-        }
+        VariableEnvironmentNode() = default;
+        VariableEnvironmentNode(VariableEnvironment&& lexicalDeclaredVariables);
+        VariableEnvironmentNode(VariableEnvironment&& lexicalDeclaredVariables, FunctionStack&&);
 
-        VariableEnvironmentNode(VariableEnvironment& lexicalDeclaredVariables);
-        VariableEnvironmentNode(VariableEnvironment& lexicalDeclaredVariables, FunctionStack&&);
-
         VariableEnvironment& lexicalVariables() { return m_lexicalVariables; }
         FunctionStack& functionStack() { return m_functionStack; }
 
@@ -1624,7 +1621,7 @@
     class BlockNode final : public StatementNode, public VariableEnvironmentNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(BlockNode);
     public:
-        BlockNode(const JSTokenLocation&, SourceElements*, VariableEnvironment&, FunctionStack&&);
+        BlockNode(const JSTokenLocation&, SourceElements*, VariableEnvironment&&, FunctionStack&&);
 
         StatementNode* singleStatement() const;
         StatementNode* lastStatement() const;
@@ -1746,7 +1743,7 @@
     class ForNode final : public StatementNode, public VariableEnvironmentNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(ForNode);
     public:
-        ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*, VariableEnvironment&);
+        ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*, VariableEnvironment&&);
 
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = nullptr) final;
@@ -1762,7 +1759,7 @@
     class EnumerationNode : public StatementNode, public ThrowableExpressionData, public VariableEnvironmentNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(EnumerationNode);
     public:
-        EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&);
+        EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&&);
 
         ExpressionNode* lexpr() const { return m_lexpr; }
         ExpressionNode* expr() const { return m_expr; }
@@ -1776,7 +1773,7 @@
     class ForInNode final : public EnumerationNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(ForInNode);
     public:
-        ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&);
+        ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&&);
 
     private:
         RegisterID* tryGetBoundLocal(BytecodeGenerator&);
@@ -1788,7 +1785,7 @@
     class ForOfNode final : public EnumerationNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(ForOfNode);
     public:
-        ForOfNode(bool, const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&);
+        ForOfNode(bool, const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&&);
         bool isForOfNode() const final { return true; }
         bool isForAwait() const { return m_isForAwait; }
 
@@ -1878,7 +1875,7 @@
     class TryNode final : public StatementNode, public VariableEnvironmentNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(TryNode);
     public:
-        TryNode(const JSTokenLocation&, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock);
+        TryNode(const JSTokenLocation&, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, VariableEnvironment&& catchEnvironment, StatementNode* finallyBlock);
 
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = nullptr) final;
@@ -1898,7 +1895,7 @@
         using ParserArenaRoot::operator new;
 
         ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, LexicalScopeFeatures);
-        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
+        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&&, FunctionStack&&, VariableEnvironment&&, UniquedStringImplPtrSet&&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
 
         const SourceCode& source() const { return m_source; }
         intptr_t sourceID() const { return m_source.providerID(); }
@@ -1974,7 +1971,7 @@
 
     class ProgramNode final : public ScopeNode {
     public:
-        ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&&, FunctionStack&&, VariableEnvironment&&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         unsigned startColumn() const { return m_startColumn; }
         unsigned endColumn() const { return m_endColumn; }
@@ -1989,7 +1986,7 @@
 
     class EvalNode final : public ScopeNode {
     public:
-        EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&&, FunctionStack&&, VariableEnvironment&&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         ALWAYS_INLINE unsigned startColumn() const { return 0; }
         unsigned endColumn() const { return m_endColumn; }
@@ -2004,7 +2001,7 @@
 
     class ModuleProgramNode final : public ScopeNode {
     public:
-        ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&&, FunctionStack&&, VariableEnvironment&&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         unsigned startColumn() const { return m_startColumn; }
         unsigned endColumn() const { return m_endColumn; }
@@ -2262,7 +2259,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, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&&, FunctionStack&&, VariableEnvironment&&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         FunctionParameters* parameters() const { return m_parameters; }
 
@@ -2378,7 +2375,7 @@
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(ClassExprNode);
     public:
         ClassExprNode(const JSTokenLocation&, const Identifier&, const SourceCode& classSource,
-            VariableEnvironment& classEnvironment, ExpressionNode* constructorExpresssion,
+            VariableEnvironment&& classHeadEnvironment, VariableEnvironment&& classEnvironment, ExpressionNode* constructorExpresssion,
             ExpressionNode* parentClass, PropertyListNode* classElements);
 
         const Identifier& name() { return m_name; }
@@ -2393,6 +2390,7 @@
 
         bool isClassExprNode() const final { return true; }
 
+        VariableEnvironment m_classHeadEnvironment;
         SourceCode m_classSource;
         const Identifier& m_name;
         const Identifier* m_ecmaName;
@@ -2675,7 +2673,7 @@
     class SwitchNode final : public StatementNode, public VariableEnvironmentNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(SwitchNode);
     public:
-        SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*, VariableEnvironment&, FunctionStack&&);
+        SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*, VariableEnvironment&&, FunctionStack&&);
 
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = nullptr) final;

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2021-07-01 02:03:55 UTC (rev 279447)
@@ -214,6 +214,11 @@
     out.print(*m_data.cooked);
 }
 
+static ALWAYS_INLINE bool isPrivateFieldName(UniquedStringImpl* uid)
+{
+    return uid->length() && uid->at(0) == '#';
+}
+
 template <typename LexerType>
 Expected<typename Parser<LexerType>::ParseInnerResult, String> Parser<LexerType>::parseInner(const Identifier& calleeName, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition, const FixedVector<JSTextPosition>* classFieldLocations, const PrivateNameEnvironment* parentScopePrivateNames)
 {
@@ -291,8 +296,21 @@
     if (!sourceElements || !validEnding)
         return makeUnexpected(hasError() ? m_errorMessage : "Parser error"_s);
 
-    if (hasPrivateNames && scope->hasUsedButUndeclaredPrivateNames())
-        return makeUnexpected("Cannot reference undeclared private names");
+    if (Options::usePrivateClassFields() && !m_lexer->isReparsingFunction() && m_seenPrivateNameUseInNonReparsingFunctionMode) {
+        String errorMessage;
+        scope->forEachUsedVariable([&] (UniquedStringImpl* impl) {
+            if (!isPrivateFieldName(impl))
+                return IterationStatus::Continue;
+            if (parentScopePrivateNames && parentScopePrivateNames->contains(impl))
+                return IterationStatus::Continue;
+            if (scope->lexicalVariables().contains(impl))
+                return IterationStatus::Continue;
+            errorMessage = makeString("Cannot reference undeclared private names: \"", String(impl), "\"");
+            return IterationStatus::Done;
+        });
+        if (!errorMessage.isNull())
+            return makeUnexpected(errorMessage);
+    }
 
     IdentifierSet capturedVariables;
     UniquedStringImplPtrSet sloppyModeHoistedFunctions;
@@ -302,6 +320,7 @@
     VariableEnvironment& varDeclarations = scope->declaredVariables();
     for (auto& entry : capturedVariables)
         varDeclarations.markVariableAsCaptured(entry);
+    scope->finalizeLexicalEnvironment();
 
     if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode)) {
         if (scope->usedVariablesContains(m_vm.propertyNames->arguments.impl()))
@@ -311,7 +330,7 @@
     CodeFeatures features = context.features();
     if (scope->shadowsArguments())
         features |= ShadowsArgumentsFeature;
-    if (m_seenTaggedTemplate)
+    if (m_seenTaggedTemplateInNonReparsingFunctionMode)
         features |= NoEvalCacheFeature;
     if (scope->hasNonSimpleParameterList())
         features |= NonSimpleParameterListFeature;
@@ -331,7 +350,7 @@
     }
 #endif // ASSERT_ENABLED
 
-    return ParseInnerResult { parameters, sourceElements, scope->takeFunctionDeclarations(), WTFMove(varDeclarations), WTFMove(sloppyModeHoistedFunctions), features, context.numConstants() };
+    return ParseInnerResult { parameters, sourceElements, scope->takeFunctionDeclarations(), scope->takeDeclaredVariables(), scope->takeLexicalEnvironment(), WTFMove(sloppyModeHoistedFunctions), features, context.numConstants() };
 }
 
 template <typename LexerType>
@@ -1384,23 +1403,16 @@
     bool isConstDeclaration = match(CONSTTOKEN);
     bool forLoopConstDoesNotHaveInitializer = false;
 
-    VariableEnvironment dummySet;
-    VariableEnvironment* lexicalVariables = nullptr;
     AutoCleanupLexicalScope lexicalScope;
 
-    auto gatherLexicalVariablesIfNecessary = [&] {
+    auto popLexicalScopeIfNecessary = [&]() -> VariableEnvironment {
         if (isLetDeclaration || isConstDeclaration) {
-            ScopeRef scope = lexicalScope.scope();
-            lexicalVariables = &scope->finalizeLexicalEnvironment();
-        } else
-            lexicalVariables = &dummySet;
+            auto [lexicalVariables, functionDeclarations] = popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
+            return lexicalVariables;
+        }
+        return { };
     };
 
-    auto popLexicalScopeIfNecessary = [&] {
-        if (isLetDeclaration || isConstDeclaration)
-            popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
-    };
-
     if (isVarDeclaration || isLetDeclaration || isConstDeclaration) {
         /*
          for (var/let/const IDENT in/of _expression_) statement
@@ -1477,19 +1489,13 @@
         TreeStatement statement = parseStatement(context, unused);
         endLoop();
         failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
-        gatherLexicalVariablesIfNecessary();
-        TreeStatement result;
+        VariableEnvironment lexicalVariables = popLexicalScopeIfNecessary();
         if (isOfEnumeration)
-            result = context.createForOfLoop(isAwaitFor, location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
-        else {
-            ASSERT(!isAwaitFor);
-            if (isVarDeclaration && forInInitializer)
-                result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
-            else
-                result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
-        }
-        popLexicalScopeIfNecessary();
-        return result;
+            return context.createForOfLoop(isAwaitFor, location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
+        ASSERT(!isAwaitFor);
+        if (isVarDeclaration && forInInitializer)
+            return context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
+        return context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
     }
     
     if (!match(SEMICOLON)) {
@@ -1542,10 +1548,8 @@
         TreeStatement statement = parseStatement(context, unused);
         endLoop();
         failIfFalse(statement, "Expected a statement as the body of a for loop");
-        gatherLexicalVariablesIfNecessary();
-        TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
-        popLexicalScopeIfNecessary();
-        return result;
+        VariableEnvironment lexicalVariables = popLexicalScopeIfNecessary();
+        return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, WTFMove(lexicalVariables));
     }
     
     // For-in and For-of loop
@@ -1579,30 +1583,22 @@
     TreeStatement statement = parseStatement(context, unused);
     endLoop();
     failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
-    gatherLexicalVariablesIfNecessary();
-    TreeStatement result;
     if (pattern) {
         ASSERT(!decls);
+        VariableEnvironment lexicalVariables = popLexicalScopeIfNecessary();
         if (isOfEnumeration)
-            result = context.createForOfLoop(isAwaitFor, location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
-        else {
-            ASSERT(!isAwaitFor);
-            result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
-        }
-
-        popLexicalScopeIfNecessary();
-        return result;
+            return context.createForOfLoop(isAwaitFor, location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
+        ASSERT(!isAwaitFor);
+        return context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
     }
 
     semanticFailIfFalse(isSimpleAssignmentTarget(context, decls), "Left side of assignment is not a reference");
+
+    VariableEnvironment lexicalVariables = popLexicalScopeIfNecessary();
     if (isOfEnumeration)
-        result = context.createForOfLoop(isAwaitFor, location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
-    else {
-        ASSERT(!isAwaitFor);
-        result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
-    }
-    popLexicalScopeIfNecessary();
-    return result;
+        return context.createForOfLoop(isAwaitFor, location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
+    ASSERT(!isAwaitFor);
+    return context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, WTFMove(lexicalVariables));
 }
 
 template <typename LexerType>
@@ -1751,9 +1747,8 @@
     endSwitch();
     handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
     
-    TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
-    popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
-    return result;
+    auto [lexicalEnvironment, functionDeclarations] = popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
+    return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, WTFMove(lexicalEnvironment), WTFMove(functionDeclarations));
 }
 
 template <typename LexerType>
@@ -1820,6 +1815,7 @@
     failIfFalse(tryBlock, "Cannot parse the body of try block");
     int lastLine = m_lastTokenEndPosition.line;
     VariableEnvironment catchEnvironment; 
+    DeclarationStacks::FunctionStack functionStack;
     if (match(CATCH)) {
         next();
         
@@ -1849,9 +1845,9 @@
             constexpr bool isCatchBlock = true;
             catchBlock = parseBlockStatement(context, isCatchBlock);
             failIfFalse(catchBlock, "Unable to parse 'catch' block");
-            catchEnvironment = catchScope->finalizeLexicalEnvironment();
+            std::tie(catchEnvironment, functionStack) = popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
+            ASSERT(functionStack.isEmpty());
             RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
-            popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
         }
     }
     
@@ -1862,7 +1858,7 @@
         failIfFalse(finallyBlock, "Cannot parse finally body");
     }
     failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
-    return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
+    return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, WTFMove(catchEnvironment));
 }
 
 template <typename LexerType>
@@ -1899,17 +1895,17 @@
     JSTokenLocation location(tokenLocation());
     int startOffset = m_token.m_data.offset;
     int start = tokenLine();
-    VariableEnvironment emptyEnvironment;
-    DeclarationStacks::FunctionStack emptyFunctionStack;
+    VariableEnvironment lexicalEnvironment;
+    DeclarationStacks::FunctionStack functionStack;
     next();
     if (match(CLOSEBRACE)) {
         int endOffset = m_token.m_data.offset;
         next();
-        TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
+        if (shouldPushLexicalScope)
+            std::tie(lexicalEnvironment, functionStack) = popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
+        TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, WTFMove(lexicalEnvironment), WTFMove(functionStack));
         context.setStartOffset(result, startOffset);
         context.setEndOffset(result, endOffset);
-        if (shouldPushLexicalScope)
-            popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
         return result;
     }
     TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
@@ -1917,12 +1913,11 @@
     matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
     int endOffset = m_token.m_data.offset;
     next();
-    TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
+    if (shouldPushLexicalScope)
+        std::tie(lexicalEnvironment, functionStack) = popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
+    TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, WTFMove(lexicalEnvironment), WTFMove(functionStack));
     context.setStartOffset(result, startOffset);
     context.setEndOffset(result, endOffset);
-    if (shouldPushLexicalScope)
-        popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
-
     return result;
 }
 
@@ -2095,9 +2090,8 @@
     failIfFalse(function, "Expected valid function statement after 'function' keyword");
     TreeSourceElements sourceElements = context.createSourceElements();
     context.appendStatement(sourceElements, function);
-    TreeStatement result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
-    popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
-    return result;
+    auto [lexicalEnvironment, functionDeclarations] = popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
+    return context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, WTFMove(lexicalEnvironment), WTFMove(functionDeclarations));
 }
 
 template <typename LexerType>
@@ -2606,6 +2600,7 @@
             if (TreeBuilder::NeedsFreeVariableInfo)
                 parentScope->addClosedVariableCandidateUnconditionally(impl);
         }
+        return IterationStatus::Continue;
     });
 
     auto performParsingFunctionBody = [&] {
@@ -2890,14 +2885,25 @@
     info.startColumn = tokenColumn();
     info.startOffset = location.startOffset;
 
-    AutoPopScopeRef classScope(this, pushScope());
-    classScope->setIsLexicalScope();
-    classScope->preventVarDeclarations();
-    classScope->setStrictMode();
-    bool declaresPrivateMethod = false;
-    bool declaresPrivateAccessor = false;
-    bool declaresStaticPrivateMethod = false;
-    bool declaresStaticPrivateAccessor = false;
+    // We have a subtle problem here. Class heritage evaluation should find class declaration's constructor name, but should not find private name evaluation.
+    // For example,
+    //
+    //     class A extends (
+    //         class {
+    //             constructor() {
+    //                 print(A); // This is OK.
+    //                 print(A.#test); // This is SyntaxError.
+    //             }
+    //         }) {
+    //         static #test = 42;
+    //     }
+    //
+    // We need to create two scopes here since private name lookup will traverse scope at linking time in CodeBlock.
+    // This classHeadScope is similar to functionScope in FunctionExpression with name.
+    AutoPopScopeRef classHeadScope(this, pushScope());
+    classHeadScope->setIsLexicalScope();
+    classHeadScope->preventVarDeclarations();
+    classHeadScope->setStrictMode();
     next();
 
     ASSERT_WITH_MESSAGE(requirements != FunctionNameRequirements::Unnamed, "Currently, there is no caller that uses FunctionNameRequirements::Unnamed for class syntax.");
@@ -2905,7 +2911,7 @@
     if (match(IDENT) || isAllowedIdentifierAwait(m_token)) {
         info.className = m_token.m_data.ident;
         next();
-        failIfTrue(classScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
+        failIfTrue(classHeadScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
     } else if (requirements == FunctionNameRequirements::Named) {
         if (match(OPENBRACE))
             semanticFail("Class statements must have a name");
@@ -2921,12 +2927,22 @@
         parentClass = parseMemberExpression(context);
         failIfFalse(parentClass, "Cannot parse the parent class name");
     }
-    classScope->setIsClassScope();
     const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base;
 
     JSTextPosition classHeadEnd = lastTokenEndPosition();
     consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
 
+    AutoPopScopeRef classScope(this, pushScope());
+    classScope->setIsLexicalScope();
+    classScope->preventVarDeclarations();
+    classScope->setStrictMode();
+    classScope->setIsClassScope();
+
+    bool declaresPrivateMethod = false;
+    bool declaresPrivateAccessor = false;
+    bool declaresStaticPrivateMethod = false;
+    bool declaresStaticPrivateAccessor = false;
+
     TreeExpression constructor = 0;
     TreePropertyList classElements = 0;
     TreePropertyList classElementsTail = 0;
@@ -3168,14 +3184,11 @@
             classElements->setHasPrivateAccessors(declaresPrivateAccessor || declaresStaticPrivateAccessor);
     }
 
-    if (Options::usePrivateClassFields()) {
-        // Fail if there are no parent private name scopes and any used-but-undeclared private names.
-        semanticFailIfFalse(copyUndeclaredPrivateNamesToOuterScope(), "Cannot reference undeclared private names");
-    }
-
-    auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, classElements, start, divot, classHeadEnd);
-    popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
-    return classExpression;
+    auto [lexicalEnvironment, functionDeclarations] = popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
+    auto [classHeadEnvironment, classHeadFunctionDeclarations] = popScope(classHeadScope, TreeBuilder::NeedsFreeVariableInfo);
+    ASSERT(functionDeclarations.isEmpty());
+    ASSERT(classHeadFunctionDeclarations.isEmpty());
+    return context.createClassExpr(location, info, WTFMove(classHeadEnvironment), WTFMove(lexicalEnvironment), constructor, parentClass, classElements, start, divot, classHeadEnd);
 }
 
 template <typename LexerType>
@@ -4237,8 +4250,8 @@
         if (Options::usePrivateIn() && match(PRIVATENAME)) {
             const Identifier* ident = m_token.m_data.ident;
             ASSERT(ident);
-            semanticFailIfFalse(usePrivateName(ident), "Cannot reference private names outside of class");
-            currentScope()->useVariable(ident, false);
+            currentScope()->usePrivateName(*ident);
+            m_seenPrivateNameUseInNonReparsingFunctionMode = true;
             next();
             semanticFailIfTrue(m_token.m_type != INTOKEN, "Bare private name can only be used as the left-hand side of an `in` _expression_");
             current = context.createPrivateIdentifierNode(location, *ident);
@@ -5048,22 +5061,6 @@
 }
 
 template <typename LexerType>
-bool Parser<LexerType>::usePrivateName(const Identifier* ident)
-{
-    if (m_lexer->isReparsingFunction())
-        return true;
-
-    if (auto maybeCurrent = findPrivateNameScope()) {
-        ScopeRef current = maybeCurrent.value();
-        if (!current->hasPrivateName(*ident))
-            current->usePrivateName(*ident);
-        return true;
-    }
-
-    return false;
-}
-
-template <typename LexerType>
 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
 {
     TreeExpression base = 0;
@@ -5272,9 +5269,9 @@
                     failIfTrue(baseIsSuper, "Cannot access private names from super");
                     if (UNLIKELY(currentScope()->evalContextType() == EvalContextType::InstanceFieldEvalContext))
                         semanticFailIfFalse(currentScope()->hasPrivateName(*ident), "Cannot reference undeclared private field '", ident->impl(), "'");
-                    semanticFailIfFalse(usePrivateName(ident), "Cannot reference private names outside of class");
+                    currentScope()->usePrivateName(*ident);
+                    m_seenPrivateNameUseInNonReparsingFunctionMode = true;
                     m_parserState.lastPrivateName = ident;
-                    currentScope()->useVariable(ident, false);
                     type = DotType::PrivateMember;
                     m_token.m_type = IDENT;
                 }
@@ -5294,7 +5291,7 @@
                 failIfFalse(templateLiteral, "Cannot parse template literal");
                 base = context.createTaggedTemplate(startLocation, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
                 m_parserState.nonLHSCount = nonLHSCount;
-                m_seenTaggedTemplate = true;
+                m_seenTaggedTemplateInNonReparsingFunctionMode = true;
                 break;
             }
             default:

Modified: trunk/Source/_javascript_Core/parser/Parser.h (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/Parser.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -23,6 +23,7 @@
 #pragma once
 
 #include "ExecutableInfo.h"
+#include "IterationStatus.h"
 #include "Lexer.h"
 #include "ModuleScopeData.h"
 #include "Nodes.h"
@@ -319,16 +320,17 @@
     const HashSet<UniquedStringImpl*>& closedVariableCandidates() const { return m_closedVariableCandidates; }
     VariableEnvironment& declaredVariables() { return m_declaredVariables; }
     VariableEnvironment& lexicalVariables() { return m_lexicalVariables; }
-    VariableEnvironment& finalizeLexicalEnvironment() 
-    { 
+    void finalizeLexicalEnvironment()
+    {
         if (m_usesEval || m_needsFullActivation)
             m_lexicalVariables.markAllVariablesAsCaptured();
         else
             computeLexicallyCapturedVariablesAndPurgeCandidates();
-
-        return m_lexicalVariables;
     }
 
+    VariableEnvironment takeLexicalEnvironment() { return WTFMove(m_lexicalVariables); }
+    VariableEnvironment takeDeclaredVariables() { return WTFMove(m_declaredVariables); }
+
     void computeLexicallyCapturedVariablesAndPurgeCandidates()
     {
         // Because variables may be defined at any time in the range of a lexical scope, we must
@@ -421,7 +423,7 @@
         ASSERT(node);
         m_functionDeclarations.append(node);
     }
-    DeclarationStacks::FunctionStack&& takeFunctionDeclarations() { return WTFMove(m_functionDeclarations); }
+    DeclarationStacks::FunctionStack takeFunctionDeclarations() { return WTFMove(m_functionDeclarations); }
     
 
     DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant, DeclarationImportType importType = DeclarationImportType::NotImported)
@@ -480,28 +482,6 @@
         return m_lexicalVariables.hasPrivateName(ident);
     }
 
-    void copyUndeclaredPrivateNamesTo(Scope& other)
-    {
-        m_lexicalVariables.copyUndeclaredPrivateNamesTo(other.m_lexicalVariables);
-    }
-
-    bool hasUsedButUndeclaredPrivateNames() const
-    {
-        if (m_lexicalVariables.privateNamesSize() > 0) {
-            for (auto entry : m_lexicalVariables.privateNames()) {
-                if (entry.value.isUsed() && !entry.value.isDeclared())
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    void usePrivateName(const Identifier& ident)
-    {
-        ASSERT(m_allowsLexicalDeclarations);
-        m_lexicalVariables.usePrivateName(ident);
-    }
-
     DeclarationResultMask declarePrivateMethod(const Identifier& ident, ClassElementTag tag)
     {
         ASSERT(m_allowsLexicalDeclarations);
@@ -611,8 +591,10 @@
     void forEachUsedVariable(const Func& func)
     {
         for (const UniquedStringImplPtrSet& set : m_usedVariables) {
-            for (UniquedStringImpl* impl : set)
-                func(impl);
+            for (UniquedStringImpl* impl : set) {
+                if (func(impl) == IterationStatus::Done)
+                    return;
+            }
         }
     }
     void useVariable(const Identifier* ident, bool isEval)
@@ -624,10 +606,14 @@
         m_usesEval |= isEval;
         m_usedVariables.last().add(impl);
     }
+    void usePrivateName(const Identifier& ident)
+    {
+        ASSERT(m_allowsLexicalDeclarations);
+        useVariable(&ident, false);
+    }
 
     void pushUsedVariableSet() { m_usedVariables.append(UniquedStringImplPtrSet()); }
     size_t currentUsedVariablesSize() { return m_usedVariables.size(); }
-
     void revertToPreviousUsedVariables(size_t size) { m_usedVariables.resize(size); }
 
     void setNeedsFullActivation() { m_needsFullActivation = true; }
@@ -1280,31 +1266,6 @@
         return std::nullopt;
     }
 
-    ScopeRef privateNameScope()
-    {
-        ASSERT(m_scopeStack.size());
-        unsigned i = m_scopeStack.size() - 1;
-        while (i && !m_scopeStack[i].isPrivateNameScope())
-            i--;
-
-        ASSERT(m_scopeStack[i].isPrivateNameScope());
-        return ScopeRef(&m_scopeStack, i);
-    }
-
-    bool copyUndeclaredPrivateNamesToOuterScope()
-    {
-        ScopeRef current = privateNameScope();
-        unsigned i = current.index() - 1;
-        while (i && !m_scopeStack[i].isPrivateNameScope())
-            i--;
-
-        if (!i)
-            return !current->hasUsedButUndeclaredPrivateNames();
-
-        current->copyUndeclaredPrivateNamesTo(m_scopeStack[i]);
-        return true;
-    }
-
     ScopeRef closestParentOrdinaryFunctionNonLexicalScope()
     {
         unsigned i = m_scopeStack.size() - 1;
@@ -1342,40 +1303,46 @@
         return currentScope();
     }
 
-    void popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
+    std::tuple<VariableEnvironment, DeclarationStacks::FunctionStack> popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
     {
         EXCEPTION_ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
         ASSERT(m_scopeStack.size() > 1);
-        m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
+        Scope& lastScope = m_scopeStack.last();
+
+        // Finalize lexical variables.
+        lastScope.finalizeLexicalEnvironment();
+        m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&lastScope, shouldTrackClosedVariables);
         
-        if (m_scopeStack.last().isArrowFunction())
-            m_scopeStack.last().setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded();
+        if (lastScope.isArrowFunction())
+            lastScope.setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded();
         
-        if (!(m_scopeStack.last().isFunctionBoundary() && !m_scopeStack.last().isArrowFunctionBoundary()))
-            m_scopeStack[m_scopeStack.size() - 2].mergeInnerArrowFunctionFeatures(m_scopeStack.last().innerArrowFunctionFeatures());
+        if (!(lastScope.isFunctionBoundary() && !lastScope.isArrowFunctionBoundary()))
+            m_scopeStack[m_scopeStack.size() - 2].mergeInnerArrowFunctionFeatures(lastScope.innerArrowFunctionFeatures());
 
-        if (!m_scopeStack.last().isFunctionBoundary() && m_scopeStack.last().needsFullActivation())
+        if (!lastScope.isFunctionBoundary() && lastScope.needsFullActivation())
             m_scopeStack[m_scopeStack.size() - 2].setNeedsFullActivation();
+        std::tuple result { lastScope.takeLexicalEnvironment(), lastScope.takeFunctionDeclarations() };
         m_scopeStack.removeLast();
+        return result;
     }
     
-    ALWAYS_INLINE void popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
+    ALWAYS_INLINE std::tuple<VariableEnvironment, DeclarationStacks::FunctionStack> popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
     {
-        popScopeInternal(scope, shouldTrackClosedVariables);
+        return popScopeInternal(scope, shouldTrackClosedVariables);
     }
     
-    ALWAYS_INLINE void popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
+    ALWAYS_INLINE std::tuple<VariableEnvironment, DeclarationStacks::FunctionStack> popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
     {
         scope.setPopped();
-        popScopeInternal(scope, shouldTrackClosedVariables);
+        return popScopeInternal(scope, shouldTrackClosedVariables);
     }
 
-    ALWAYS_INLINE void popScope(AutoCleanupLexicalScope& cleanupScope, bool shouldTrackClosedVariables)
+    ALWAYS_INLINE std::tuple<VariableEnvironment, DeclarationStacks::FunctionStack> popScope(AutoCleanupLexicalScope& cleanupScope, bool shouldTrackClosedVariables)
     {
         RELEASE_ASSERT(cleanupScope.isValid());
         ScopeRef& scope = cleanupScope.scope();
         cleanupScope.setPopped();
-        popScopeInternal(scope, shouldTrackClosedVariables);
+        return popScopeInternal(scope, shouldTrackClosedVariables);
     }
 
     NEVER_INLINE DeclarationResultMask declareHoistedVariable(const Identifier* ident)
@@ -1509,6 +1476,7 @@
         SourceElements* sourceElements;
         DeclarationStacks::FunctionStack functionDeclarations;
         VariableEnvironment varDeclarations;
+        VariableEnvironment lexicalVariables;
         UniquedStringImplPtrSet sloppyModeHoistedFunctions;
         CodeFeatures features;
         int numConstants;
@@ -1839,8 +1807,6 @@
 
     template <class TreeBuilder> ALWAYS_INLINE bool isSimpleAssignmentTarget(TreeBuilder&, TreeExpression);
 
-    ALWAYS_INLINE bool usePrivateName(const Identifier*);
-
     ALWAYS_INLINE int isBinaryOperator(JSTokenType);
     bool allowAutomaticSemicolon();
     
@@ -2123,8 +2089,9 @@
     RefPtr<ModuleScopeData> m_moduleScopeData;
     DebuggerParseData* m_debuggerParseData;
     CallOrApplyDepthScope* m_callOrApplyDepthScope { nullptr };
-    bool m_seenTaggedTemplate { false };
     bool m_isInsideOrdinaryFunction;
+    bool m_seenTaggedTemplateInNonReparsingFunctionMode { false };
+    bool m_seenPrivateNameUseInNonReparsingFunctionMode { false };
 };
 
 
@@ -2172,9 +2139,9 @@
                                     startColumn,
                                     endColumn,
                                     parseResult.value().sourceElements,
-                                    parseResult.value().varDeclarations,
+                                    WTFMove(parseResult.value().varDeclarations),
                                     WTFMove(parseResult.value().functionDeclarations),
-                                    currentScope()->finalizeLexicalEnvironment(),
+                                    WTFMove(parseResult.value().lexicalVariables),
                                     WTFMove(parseResult.value().sloppyModeHoistedFunctions),
                                     parseResult.value().parameters,
                                     *m_source,

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -192,7 +192,7 @@
     ExpressionType createYield(const JSTokenLocation&) { return YieldExpr; }
     ExpressionType createYield(const JSTokenLocation&, ExpressionType, bool, int, int, int) { return YieldExpr; }
     ExpressionType createAwait(const JSTokenLocation&, ExpressionType, int, int, int) { return AwaitExpr; }
-    ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, int, int, int) { return ClassExpr; }
+    ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&&, VariableEnvironment&&, ExpressionType, ExpressionType, PropertyList, int, int, int) { return ClassExpr; }
     ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     ExpressionType createGeneratorFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&, const Identifier&) { return FunctionExpr; }
     ExpressionType createAsyncFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
@@ -251,13 +251,13 @@
     int createDefineField(const JSTokenLocation&, const Identifier*, int, DefineFieldNode::Type) { return 0; }
     int createClassDeclStatement(const JSTokenLocation&, ClassExpression,
         const JSTextPosition&, const JSTextPosition&, int, int) { return StatementResult; }
-    int createBlockStatement(const JSTokenLocation&, int, int, int, VariableEnvironment&, DeclarationStacks::FunctionStack&&) { return StatementResult; }
+    int createBlockStatement(const JSTokenLocation&, int, int, int, VariableEnvironment&&, DeclarationStacks::FunctionStack&&) { return StatementResult; }
     int createExprStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
     int createIfStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
     int createIfStatement(const JSTokenLocation&, int, int, int, int, int) { return StatementResult; }
-    int createForLoop(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
-    int createForInLoop(const JSTokenLocation&, int, int, int, const JSTokenLocation&, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
-    int createForOfLoop(bool, const JSTokenLocation&, int, int, int, const JSTokenLocation&, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
+    int createForLoop(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&&) { return StatementResult; }
+    int createForInLoop(const JSTokenLocation&, int, int, int, const JSTokenLocation&, int, int, int, int, int, VariableEnvironment&&) { return StatementResult; }
+    int createForOfLoop(bool, const JSTokenLocation&, int, int, int, const JSTokenLocation&, int, int, int, int, int, VariableEnvironment&&) { return StatementResult; }
     int createEmptyStatement(const JSTokenLocation&) { return StatementResult; }
     int createDeclarationStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
     int createReturnStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
@@ -265,8 +265,8 @@
     int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
     int createContinueStatement(const JSTokenLocation&, int, int) { return StatementResult; }
     int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
-    int createTryStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
-    int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&, DeclarationStacks::FunctionStack&&) { return StatementResult; }
+    int createTryStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&&) { return StatementResult; }
+    int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&&, DeclarationStacks::FunctionStack&&) { return StatementResult; }
     int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
     int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int) { return StatementResult; }
     int createDoWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }

Modified: trunk/Source/_javascript_Core/parser/VariableEnvironment.cpp (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/VariableEnvironment.cpp	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/VariableEnvironment.cpp	2021-07-01 02:03:55 UTC (rev 279447)
@@ -25,10 +25,17 @@
 
 #include "config.h"
 #include "VariableEnvironment.h"
+#include <wtf/CommaPrinter.h>
+#include <wtf/HexNumber.h>
 #include <wtf/text/UniquedStringImpl.h>
 
 namespace JSC {
 
+void VariableEnvironmentEntry::dump(PrintStream& out) const
+{
+    out.print(hex(m_bits));
+}
+
 VariableEnvironment& VariableEnvironment::operator=(const VariableEnvironment& other)
 {
     VariableEnvironment env(other);
@@ -104,6 +111,16 @@
     findResult->value.setIsExported();
 }
 
+VariableEnvironment::Map::AddResult VariableEnvironment::declarePrivateField(const RefPtr<UniquedStringImpl>& identifier)
+{
+    getOrAddPrivateName(identifier.get());
+    auto entry = VariableEnvironmentEntry();
+    entry.setIsPrivateField();
+    entry.setIsConst();
+    entry.setIsCaptured();
+    return m_map.add(identifier, entry);
+}
+
 VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateAccessor(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry accessorTraits)
 {
     if (!m_rareData)
@@ -112,7 +129,7 @@
     auto findResult = m_rareData->m_privateNames.find(identifier);
 
     if (findResult == m_rareData->m_privateNames.end()) {
-        PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | accessorTraits.bits());
+        PrivateNameEntry meta(accessorTraits.bits());
 
         auto entry = VariableEnvironmentEntry();
         if (accessorTraits.isSetter())
@@ -130,43 +147,25 @@
     }
 
     PrivateNameEntry currentEntry = findResult->value;
-    if (currentEntry.isDeclared()) {
-        if ((accessorTraits.isSetter() && !currentEntry.isGetter())
-            || (accessorTraits.isGetter() && !currentEntry.isSetter()))
-            return PrivateDeclarationResult::DuplicatedName;
+    if ((accessorTraits.isSetter() && !currentEntry.isGetter())
+        || (accessorTraits.isGetter() && !currentEntry.isSetter()))
+        return PrivateDeclarationResult::DuplicatedName;
 
-        if (accessorTraits.isStatic() != currentEntry.isStatic())
-            return PrivateDeclarationResult::InvalidStaticNonStatic;
+    if (accessorTraits.isStatic() != currentEntry.isStatic())
+        return PrivateDeclarationResult::InvalidStaticNonStatic;
 
-        PrivateNameEntry meta(currentEntry.bits() | accessorTraits.bits());
-        m_rareData->m_privateNames.set(identifier, meta);
+    PrivateNameEntry meta(currentEntry.bits() | accessorTraits.bits());
+    m_rareData->m_privateNames.set(identifier, meta);
 
-        auto entryIterator = m_map.find(identifier);
-        ASSERT(entryIterator != m_map.end());
-        if (accessorTraits.isSetter())
-            entryIterator->value.setIsPrivateSetter();
-        else {
-            ASSERT(accessorTraits.isGetter());
-            entryIterator->value.setIsPrivateGetter();
-        }
-
-        return PrivateDeclarationResult::Success;
-    }
-
-    // it was previously used, mark it as declared.
-    auto entry = VariableEnvironmentEntry();
+    auto entryIterator = m_map.find(identifier);
+    ASSERT(entryIterator != m_map.end());
     if (accessorTraits.isSetter())
-        entry.setIsPrivateSetter();
+        entryIterator->value.setIsPrivateSetter();
     else {
         ASSERT(accessorTraits.isGetter());
-        entry.setIsPrivateGetter();
+        entryIterator->value.setIsPrivateGetter();
     }
-    entry.setIsConst();
-    entry.setIsCaptured();
-    m_map.add(identifier, entry);
 
-    PrivateNameEntry newEntry(currentEntry.bits() | PrivateNameEntry::Traits::IsDeclared | accessorTraits.bits());
-    m_rareData->m_privateNames.set(identifier, newEntry);
     return PrivateDeclarationResult::Success;
 }
 
@@ -188,7 +187,7 @@
     auto findResult = m_rareData->m_privateNames.find(identifier);
 
     if (findResult == m_rareData->m_privateNames.end()) {
-        PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsMethod | addionalTraits);
+        PrivateNameEntry meta(PrivateNameEntry::Traits::IsMethod | addionalTraits);
 
         auto entry = VariableEnvironmentEntry();
         entry.setIsPrivateMethod();
@@ -200,19 +199,14 @@
         return addResult.isNewEntry;
     }
 
-    if (findResult->value.isDeclared())
-        return false; // Error: declaring a duplicate private name.
+    return false; // Error: declaring a duplicate private name.
+}
 
-    auto entry = VariableEnvironmentEntry();
-    entry.setIsPrivateMethod();
-    entry.setIsConst();
-    entry.setIsCaptured();
-    m_map.add(identifier, entry);
-
-    // it was previously used, mark it as declared.
-    PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsUsed | PrivateNameEntry::Traits::IsMethod | addionalTraits);
-    auto addResult = m_rareData->m_privateNames.set(identifier, meta);
-    return !addResult.isNewEntry;
+void VariableEnvironment::dump(PrintStream& out) const
+{
+    CommaPrinter comma(", ");
+    for (auto& pair : m_map)
+        out.print(comma, pair.key, " => ", pair.value);
 }
 
 void CompactTDZEnvironment::sortCompact(Compact& compact)

Modified: trunk/Source/_javascript_Core/parser/VariableEnvironment.h (279446 => 279447)


--- trunk/Source/_javascript_Core/parser/VariableEnvironment.h	2021-07-01 00:48:51 UTC (rev 279446)
+++ trunk/Source/_javascript_Core/parser/VariableEnvironment.h	2021-07-01 02:03:55 UTC (rev 279447)
@@ -74,6 +74,8 @@
         return m_bits == other.m_bits;
     }
 
+    void dump(PrintStream&) const;
+
 private:
     enum Traits : uint16_t {
         IsCaptured = 1 << 0,
@@ -107,8 +109,6 @@
 public:
     PrivateNameEntry(uint16_t traits = 0) { m_bits = traits; }
 
-    ALWAYS_INLINE bool isUsed() const { return m_bits & IsUsed; }
-    ALWAYS_INLINE bool isDeclared() const { return m_bits & IsDeclared; }
     ALWAYS_INLINE bool isMethod() const { return m_bits & IsMethod; }
     ALWAYS_INLINE bool isSetter() const { return m_bits & IsSetter; }
     ALWAYS_INLINE bool isGetter() const { return m_bits & IsGetter; }
@@ -117,9 +117,6 @@
 
     bool isPrivateMethodOrAccessor() const { return isMethod() || isSetter() || isGetter(); }
 
-    ALWAYS_INLINE void setIsUsed() { m_bits |= IsUsed; }
-    ALWAYS_INLINE void setIsDeclared() { m_bits |= IsDeclared; }
-
     uint16_t bits() const { return m_bits; }
 
     bool operator==(const PrivateNameEntry& other) const
@@ -129,12 +126,10 @@
 
     enum Traits : uint16_t {
         None = 0,
-        IsUsed = 1 << 0,
-        IsDeclared = 1 << 1,
-        IsMethod = 1 << 2,
-        IsGetter = 1 << 3,
-        IsSetter = 1 << 4,
-        IsStatic = 1 << 5,
+        IsMethod = 1 << 0,
+        IsGetter = 1 << 1,
+        IsSetter = 1 << 2,
+        IsStatic = 1 << 3,
     };
 
 private:
@@ -206,7 +201,6 @@
     using PrivateNamesRange = WTF::IteratorRange<PrivateNameEnvironment::iterator>;
 
     ALWAYS_INLINE Map::AddResult declarePrivateField(const Identifier& identifier) { return declarePrivateField(identifier.impl()); }
-    ALWAYS_INLINE void usePrivateName(const Identifier& identifier) { usePrivateName(identifier.impl()); }
 
     bool declarePrivateMethod(const Identifier& identifier) { return declarePrivateMethod(identifier.impl()); }
     bool declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits addionalTraits = PrivateNameEntry::Traits::None);
@@ -232,23 +226,7 @@
     PrivateDeclarationResult declareStaticPrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl(), PrivateNameEntry::Traits::IsStatic); }
     PrivateDeclarationResult declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits = PrivateNameEntry::Traits::None);
 
-    Map::AddResult declarePrivateField(const RefPtr<UniquedStringImpl>& identifier)
-    {
-        auto& meta = getOrAddPrivateName(identifier.get());
-        meta.setIsDeclared();
-        auto entry = VariableEnvironmentEntry();
-        entry.setIsPrivateField();
-        entry.setIsConst();
-        entry.setIsCaptured();
-        return m_map.add(identifier, entry);
-    }
-    void usePrivateName(const RefPtr<UniquedStringImpl>& identifier)
-    {
-        auto& meta = getOrAddPrivateName(identifier.get());
-        meta.setIsUsed();
-        if (meta.isDeclared())
-            find(identifier)->value.setIsCaptured();
-    }
+    Map::AddResult declarePrivateField(const RefPtr<UniquedStringImpl>&);
 
     ALWAYS_INLINE PrivateNamesRange privateNames() const
     {
@@ -264,6 +242,13 @@
         return m_rareData->m_privateNames.size();
     }
 
+    ALWAYS_INLINE PrivateNameEnvironment* privateNameEnvironment()
+    {
+        if (!m_rareData)
+            return nullptr;
+        return &m_rareData->m_privateNames;
+    }
+
     ALWAYS_INLINE const PrivateNameEnvironment* privateNameEnvironment() const
     {
         if (!m_rareData)
@@ -304,20 +289,6 @@
         return m_rareData->m_privateNames.contains(identifier.impl());
     }
 
-    ALWAYS_INLINE void copyPrivateNamesTo(VariableEnvironment& other) const
-    {
-        if (!m_rareData)
-            return;
-        if (!other.m_rareData)
-            other.m_rareData = WTF::makeUnique<VariableEnvironment::RareData>();
-        if (privateNamesSize() > 0) {
-            for (auto entry : privateNames()) {
-                if (!(entry.value.isUsed() && entry.value.isDeclared()))
-                    other.m_rareData->m_privateNames.add(entry.key, entry.value);
-            }
-        }
-    }
-
     ALWAYS_INLINE void addPrivateNamesFrom(const PrivateNameEnvironment* privateNameEnvironment)
     {
         if (!privateNameEnvironment)
@@ -326,24 +297,10 @@
         if (!m_rareData)
             m_rareData = makeUnique<VariableEnvironment::RareData>();
 
-        for (auto entry : *privateNameEnvironment) {
-            ASSERT(entry.value.isDeclared());
+        for (auto entry : *privateNameEnvironment)
             m_rareData->m_privateNames.add(entry.key, entry.value);
-        }
     }
 
-    ALWAYS_INLINE void copyUndeclaredPrivateNamesTo(VariableEnvironment& outer) const {
-        // Used by the Parser to transfer recorded uses of PrivateNames from an
-        // inner PrivateNameEnvironment into an outer one, in case a PNE is used
-        // earlier in the source code than it is defined.
-        if (privateNamesSize() > 0) {
-            for (auto entry : privateNames()) {
-                if (entry.value.isUsed() && !entry.value.isDeclared())
-                    outer.getOrAddPrivateName(entry.key.get()).setIsUsed();
-            }
-        }
-    }
-
     struct RareData {
         WTF_MAKE_STRUCT_FAST_ALLOCATED;
 
@@ -357,6 +314,8 @@
         PrivateNameEnvironment m_privateNames;
     };
 
+    void dump(PrintStream&) const;
+
 private:
     friend class CachedVariableEnvironment;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to